From b7cc05ba8564ca22a17fef25f1fbd7338e09ab9f Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Tue, 24 Oct 2023 18:54:57 -0400
Subject: [PATCH 001/327] (test): Add Functions test harnesses & additional
foundry unit tests (#11011)
* (test): Add Functions test harnesses & additional unit tests
* (test): Add transmitter balance helpers
* Update gas snapshot from helper functions
---
contracts/foundry.toml | 6 +-
.../gas-snapshots/functions.gas-snapshot | 318 +++++++++---------
.../tests/v1_X/FunctionsBilling.t.sol | 242 ++++++++++---
.../tests/v1_X/FunctionsClient.t.sol | 44 ++-
.../tests/v1_X/FunctionsCoordinator.t.sol | 216 ++++++++++--
.../tests/v1_X/FunctionsRouter.t.sol | 4 +-
.../tests/v1_X/FunctionsSubscriptions.t.sol | 60 +---
.../src/v0.8/functions/tests/v1_X/README.md | 15 +-
.../src/v0.8/functions/tests/v1_X/Setup.t.sol | 49 ++-
.../testhelpers/FunctionsClientHarness.sol | 24 ++
.../testhelpers/FunctionsClientTestHelper.sol | 2 +-
.../FunctionsClientWithEmptyCallback.sol | 2 +-
.../FunctionsCoordinatorHarness.sol | 119 +++++++
.../FunctionsCoordinatorTestHelper.sol | 2 +-
.../testhelpers/FunctionsRouterHarness.sol | 30 ++
.../FunctionsSubscriptionsHarness.sol | 54 +++
.../v1_X/testhelpers/FunctionsTestHelper.sol | 2 +-
17 files changed, 884 insertions(+), 305 deletions(-)
create mode 100644 contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol
create mode 100644 contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol
create mode 100644 contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol
create mode 100644 contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol
diff --git a/contracts/foundry.toml b/contracts/foundry.toml
index 1228ce3ec0..cf27c0f2a8 100644
--- a/contracts/foundry.toml
+++ b/contracts/foundry.toml
@@ -18,9 +18,9 @@ block_number = 12345
[profile.functions]
solc_version = '0.8.19'
-src = 'src/v0.8/functions'
-test = 'src/v0.8/functions/tests'
-gas_price = 3000000000
+src = 'src/v0.8/functions/dev/v1_X'
+test = 'src/v0.8/functions/tests/v1_X'
+gas_price = 3_000_000_000 # 3 gwei
[profile.vrf]
optimizer_runs = 1000
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index b629835060..d575c8ca19 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,177 +1,195 @@
-FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32391)
-FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 53182)
-FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 53285)
+FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
+FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
+FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
+FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32458)
+FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 53227)
+FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 53330)
+FunctionsBilling_GetAdminFee:test_GetAdminFee_Success() (gas: 18226)
FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 23671)
+FunctionsBilling_GetDONFee:test_GetDONFee_Success() (gas: 15792)
+FunctionsBilling_GetWeiPerUnitLink:test_GetWeiPerUnitLink_Success() (gas: 31773)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70138)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: 106295)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 140174)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 142502)
FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13296)
-FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 146657)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 498113)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 199261)
-FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 54991)
-FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 11933)
-FunctionsOracle_sendRequest:testEmptyRequestDataReverts() (gas: 13452)
-FunctionsOracle_setDONPublicKey:testEmptyPublicKeyReverts() (gas: 10974)
-FunctionsOracle_setDONPublicKey:testOnlyOwnerReverts() (gas: 11255)
-FunctionsOracle_setDONPublicKey:testSetDONPublicKeySuccess() (gas: 126453)
-FunctionsOracle_setDONPublicKey:testSetDONPublicKey_gas() (gas: 97580)
-FunctionsOracle_setRegistry:testEmptyPublicKeyReverts() (gas: 10635)
-FunctionsOracle_setRegistry:testOnlyOwnerReverts() (gas: 10927)
-FunctionsOracle_setRegistry:testSetRegistrySuccess() (gas: 35791)
-FunctionsOracle_setRegistry:testSetRegistry_gas() (gas: 31987)
-FunctionsOracle_typeAndVersion:testTypeAndVersionSuccess() (gas: 6905)
+FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 147278)
+FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 18974)
+FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 38251)
+FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8801)
+FunctionsClient_Constructor:test_Constructor_Success() (gas: 7573)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 498114)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 199285)
+FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14623)
+FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22923)
+FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55059)
+FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 11984)
+FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15334)
+FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 106496)
+FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15313)
+FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 656556)
+FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20364)
+FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 101275)
+FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13892)
+FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 651248)
+FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22703)
+FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 107681)
+FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 18957)
+FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 19690)
FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 246)
FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 223)
FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 225)
-FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12073)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 169899)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 160226)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38092)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35224)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 178394)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28063)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 153900)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 296711)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 310303)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2484943)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 515428)
-FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 18005)
-FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12926)
-FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37136)
-FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13871)
-FunctionsRouter_GetContractById:test_GetContractById_SuccessIfRouteExists() (gas: 17395)
-FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16382)
-FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 23934)
-FunctionsRouter_GetProposedContractSet:test_GetProposedContractSet_Success() (gas: 25958)
-FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28034)
-FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41004)
-FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24551)
-FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13315)
-FunctionsRouter_Pause:test_Pause_Success() (gas: 20298)
-FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14768)
-FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21670)
-FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfLengthMismatch() (gas: 14647)
-FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNewContract() (gas: 19025)
-FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23369)
-FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (gas: 118456)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59304)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 192796)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29405)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57926)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 186209)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50902)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25061)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29111)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34247)
-FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 284999)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65800)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 35991)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29897)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57488)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27482)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35696)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40766)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 291551)
-FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 192728)
-FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 30687)
-FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13380)
-FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13337)
-FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77421)
+FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12007)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 169900)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 160227)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38115)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35238)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 178373)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 153924)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 296712)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 310327)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2484946)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 515433)
+FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 17983)
+FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12904)
+FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37159)
+FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13849)
+FunctionsRouter_GetContractById:test_GetContractById_SuccessIfRouteExists() (gas: 17373)
+FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16383)
+FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 23935)
+FunctionsRouter_GetProposedContractSet:test_GetProposedContractSet_Success() (gas: 25936)
+FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28103)
+FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41093)
+FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24626)
+FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13338)
+FunctionsRouter_Pause:test_Pause_Success() (gas: 20344)
+FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14791)
+FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21693)
+FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfLengthMismatch() (gas: 14670)
+FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNewContract() (gas: 19048)
+FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23392)
+FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (gas: 118479)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59347)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 192799)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29426)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57925)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 186299)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50947)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25082)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29132)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34291)
+FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 285026)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65843)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 36012)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29896)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57533)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27503)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35717)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40810)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 291595)
+FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 192791)
+FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 30688)
+FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13403)
+FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13293)
+FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77400)
FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24437)
-FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 60653)
-FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13293)
-FunctionsRouter_UpdateContracts:test_UpdateContracts_Success() (gas: 38716)
-FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60324)
-FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 60962)
-FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 94675)
-FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62691)
-FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 214576)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 137833)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164777)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12926)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 57789)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87142)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18051)
-FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 95481)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15085)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 57929)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89316)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20191)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 193763)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 114636)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 125891)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessRecieveDeposit() (gas: 311486)
+FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 60676)
+FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13336)
+FunctionsRouter_UpdateContracts:test_UpdateContracts_Success() (gas: 38732)
+FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60326)
+FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 60987)
+FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 94677)
+FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62693)
+FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 214560)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 137893)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164837)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12946)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 57809)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87162)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18094)
+FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 95480)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15041)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 57885)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89272)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20148)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 193688)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 114506)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 125832)
+FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 74973)
FunctionsSubscriptions_Constructor:test_Constructor_Success() (gas: 7654)
-FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28637)
-FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 17948)
-FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 351723)
-FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 16225)
-FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13100)
-FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 40858)
-FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 30959)
-FunctionsSubscriptions_GetSubscriptionCount:test_GetSubscriptionCount_Success() (gas: 12967)
-FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16523)
-FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13436)
-FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 59568)
-FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15032)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 28401, ~: 28401)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 30913, ~: 30913)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14248, ~: 14248)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 35870, ~: 35870)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 59685, ~: 59685)
+FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28660)
+FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 17994)
+FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 351726)
+FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 16226)
+FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13101)
+FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 40903)
+FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 30937)
+FunctionsSubscriptions_GetSubscriptionCount:test_GetSubscriptionCount_Success() (gas: 12968)
+FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16547)
+FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13459)
+FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 59592)
+FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15010)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 28446, ~: 28446)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 30958, ~: 30958)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14293, ~: 14293)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 35938, ~: 35938)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 59686, ~: 59686)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15638)
-FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20833)
+FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20856)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 59732)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessSetsBalanceToZero() (gas: 57701)
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12818)
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15549)
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 54867)
-FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49624)
+FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49607)
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessSubOwnerRefunded() (gas: 50896)
-FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 164300)
+FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 164303)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17924)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 210)
-FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15533)
+FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15555)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfNoAmount() (gas: 37396)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 52130)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 54413)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 37790)
-FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 15025)
-FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 175897)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27610)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57707)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15000)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 75130)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17959)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20104)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68217)
-FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 82791)
-FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15532)
-FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success(uint64) (runs: 256, μ: 41699, ~: 41704)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30238)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 14997)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 57778)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87186)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18004)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 191195)
+FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 14981)
+FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 175857)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27611)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57709)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15001)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 75131)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17960)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20128)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68196)
+FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 82749)
+FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15554)
+FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success(uint64) (runs: 256, μ: 41717, ~: 41721)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30260)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 15019)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 57800)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87208)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18049)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 191221)
FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 41979)
-FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12847)
-FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15640)
-FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 35549)
-FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfPaused() (gas: 25910)
-FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25239)
-FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28220)
-FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 57752)
-FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26368)
-FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15714)
-FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 152510)
+FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12891)
+FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15684)
+FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 35594)
+FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfPaused() (gas: 25955)
+FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25261)
+FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28242)
+FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 57754)
+FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26390)
+FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15759)
+FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 152576)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94815)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25837)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 44348)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23597)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866530)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 26003)
-FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946591)
+FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946547)
FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104851)
FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15469)
FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 51794)
@@ -188,8 +206,8 @@ FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas
FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13727)
FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22073)
Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84675)
-Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79067)
-Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73353)
-Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38501)
-Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 964209)
-Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 156929)
\ No newline at end of file
+Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79087)
+Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73375)
+Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38546)
+Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 964214)
+Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 156934)
\ No newline at end of file
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
index 14188fdc04..82dea8672c 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
@@ -4,12 +4,17 @@ pragma solidity ^0.8.19;
import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol";
import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol";
import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol";
+import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol";
+import {Routable} from "../../dev/v1_X/Routable.sol";
-import {FunctionsRouterSetup, FunctionsSubscriptionSetup, FunctionsMultipleFulfillmentsSetup} from "./Setup.t.sol";
+import {FunctionsRouterSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsMultipleFulfillmentsSetup} from "./Setup.t.sol";
/// @notice #constructor
-contract FunctionsBilling_Constructor {
-
+contract FunctionsBilling_Constructor is FunctionsSubscriptionSetup {
+ function test_Constructor_Success() public {
+ assertEq(address(s_functionsRouter), s_functionsCoordinator.getRouter_HARNESS());
+ assertEq(address(s_linkEthFeed), s_functionsCoordinator.getLinkToNativeFeed_HARNESS());
+ }
}
/// @notice #getConfig
@@ -32,28 +37,94 @@ contract FunctionsBilling_GetConfig is FunctionsRouterSetup {
}
/// @notice #updateConfig
-contract FunctionsBilling_UpdateConfig {
+contract FunctionsBilling_UpdateConfig is FunctionsRouterSetup {
+ FunctionsBilling.Config internal configToSet;
+
+ function setUp() public virtual override {
+ FunctionsRouterSetup.setUp();
+
+ configToSet = FunctionsBilling.Config({
+ feedStalenessSeconds: getCoordinatorConfig().feedStalenessSeconds * 2,
+ gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback * 2,
+ gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback * 2,
+ requestTimeoutSeconds: getCoordinatorConfig().requestTimeoutSeconds * 2,
+ donFee: getCoordinatorConfig().donFee * 2,
+ maxSupportedRequestDataVersion: getCoordinatorConfig().maxSupportedRequestDataVersion * 2,
+ fulfillmentGasPriceOverEstimationBP: getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP * 2,
+ fallbackNativePerUnitLink: getCoordinatorConfig().fallbackNativePerUnitLink * 2,
+ minimumEstimateGasPriceWei: getCoordinatorConfig().minimumEstimateGasPriceWei * 2
+ });
+ }
+ function test_UpdateConfig_RevertIfNotOwner() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ vm.expectRevert("Only callable by owner");
+ s_functionsCoordinator.updateConfig(configToSet);
+ }
+
+ event ConfigUpdated(FunctionsBilling.Config config);
+
+ function test_UpdateConfig_Success() public {
+ // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true).
+ bool checkTopic1 = false;
+ bool checkTopic2 = false;
+ bool checkTopic3 = false;
+ bool checkData = true;
+ vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData);
+ emit ConfigUpdated(configToSet);
+
+ s_functionsCoordinator.updateConfig(configToSet);
+
+ FunctionsBilling.Config memory config = s_functionsCoordinator.getConfig();
+ assertEq(config.feedStalenessSeconds, configToSet.feedStalenessSeconds);
+ assertEq(config.gasOverheadAfterCallback, configToSet.gasOverheadAfterCallback);
+ assertEq(config.gasOverheadBeforeCallback, configToSet.gasOverheadBeforeCallback);
+ assertEq(config.requestTimeoutSeconds, configToSet.requestTimeoutSeconds);
+ assertEq(config.donFee, configToSet.donFee);
+ assertEq(config.maxSupportedRequestDataVersion, configToSet.maxSupportedRequestDataVersion);
+ assertEq(config.fulfillmentGasPriceOverEstimationBP, configToSet.fulfillmentGasPriceOverEstimationBP);
+ assertEq(config.fallbackNativePerUnitLink, configToSet.fallbackNativePerUnitLink);
+ assertEq(config.minimumEstimateGasPriceWei, configToSet.minimumEstimateGasPriceWei);
+ }
}
/// @notice #getDONFee
-contract FunctionsBilling_GetDONFee {
+contract FunctionsBilling_GetDONFee is FunctionsRouterSetup {
+ function test_GetDONFee_Success() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+ uint72 donFee = s_functionsCoordinator.getDONFee(new bytes(0));
+ assertEq(donFee, s_donFee);
+ }
}
/// @notice #getAdminFee
-contract FunctionsBilling_GetAdminFee {
+contract FunctionsBilling_GetAdminFee is FunctionsRouterSetup {
+ function test_GetAdminFee_Success() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+ uint72 adminFee = s_functionsCoordinator.getAdminFee();
+ assertEq(adminFee, s_adminFee);
+ }
}
/// @notice #getWeiPerUnitLink
-contract FunctionsBilling_GetWeiPerUnitLink {
-
-}
+contract FunctionsBilling_GetWeiPerUnitLink is FunctionsRouterSetup {
+ function test_GetWeiPerUnitLink_Success() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
-/// @notice #_getJuelsPerGas
-contract FunctionsBilling__GetJuelsPerGas {
- // TODO: make contract internal function helper
+ uint256 weiPerUnitLink = s_functionsCoordinator.getWeiPerUnitLink();
+ assertEq(weiPerUnitLink, uint256(LINK_ETH_RATE));
+ }
}
/// @notice #estimateCost
@@ -109,7 +180,7 @@ contract FunctionsBilling_EstimateCost is FunctionsSubscriptionSetup {
callbackGasLimit,
gasPriceWei
);
- uint96 expectedCostEstimate = 16375000000000200;
+ uint96 expectedCostEstimate = 51110500000000200;
assertEq(costEstimate, expectedCostEstimate);
}
@@ -134,7 +205,7 @@ contract FunctionsBilling_EstimateCost is FunctionsSubscriptionSetup {
callbackGasLimit,
gasPriceWei
);
- uint96 expectedCostEstimate = 81875000000000200;
+ uint96 expectedCostEstimate = 255552500000000200;
assertEq(costEstimate, expectedCostEstimate);
}
}
@@ -149,24 +220,115 @@ contract FunctionsBilling__StartBilling {
// TODO: make contract internal function helper
}
-/// @notice #_computeRequestId
-contract FunctionsBilling__ComputeRequestId {
- // TODO: make contract internal function helper
-}
-
/// @notice #_fulfillAndBill
contract FunctionsBilling__FulfillAndBill {
// TODO: make contract internal function helper
}
/// @notice #deleteCommitment
-contract FunctionsBilling_DeleteCommitment {
+contract FunctionsBilling_DeleteCommitment is FunctionsClientRequestSetup {
+ function test_DeleteCommitment_RevertIfNotRouter() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ vm.expectRevert(Routable.OnlyCallableByRouter.selector);
+ s_functionsCoordinator.deleteCommitment(s_requests[1].requestId);
+ }
+
+ event CommitmentDeleted(bytes32 requestId);
+
+ function test_DeleteCommitment_Success() public {
+ // Send as Router
+ vm.stopPrank();
+ vm.startPrank(address(s_functionsRouter));
+
+ // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true).
+ bool checkTopic1 = false;
+ bool checkTopic2 = false;
+ bool checkTopic3 = false;
+ bool checkData = true;
+ vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData);
+ emit CommitmentDeleted(s_requests[1].requestId);
+ s_functionsCoordinator.deleteCommitment(s_requests[1].requestId);
+ }
}
/// @notice #oracleWithdraw
-contract FunctionsBilling_OracleWithdraw {
+contract FunctionsBilling_OracleWithdraw is FunctionsMultipleFulfillmentsSetup {
+ function test_OracleWithdraw_RevertWithNoBalance() public {
+ uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances();
+ _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0);
+ // Send as stranger, which has no balance
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector);
+
+ // Attempt to withdraw with no amount, which would withdraw the full balance
+ s_functionsCoordinator.oracleWithdraw(STRANGER_ADDRESS, 0);
+
+ uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances();
+ _assertTransmittersAllHaveBalance(transmitterBalancesAfter, 0);
+ }
+
+ function test_OracleWithdraw_RevertIfInsufficientBalance() public {
+ // Send as transmitter 1, which has transmitted 1 report
+ vm.stopPrank();
+ vm.startPrank(NOP_TRANSMITTER_ADDRESS_1);
+
+ vm.expectRevert(FunctionsBilling.InsufficientBalance.selector);
+
+ // Attempt to withdraw more than the Coordinator has assigned
+ s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, s_fulfillmentCoordinatorBalance + 1);
+ }
+
+ function test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() public {
+ uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances();
+ _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0);
+
+ // Send as transmitter 1, which has transmitted 1 report
+ vm.stopPrank();
+ vm.startPrank(NOP_TRANSMITTER_ADDRESS_1);
+
+ uint96 expectedTransmitterBalance = s_fulfillmentCoordinatorBalance / 3;
+
+ // Attempt to withdraw half of balance
+ uint96 halfBalance = expectedTransmitterBalance / 2;
+ s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, halfBalance);
+
+ uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances();
+ assertEq(transmitterBalancesAfter[0], halfBalance);
+ assertEq(transmitterBalancesAfter[1], 0);
+ assertEq(transmitterBalancesAfter[2], 0);
+ assertEq(transmitterBalancesAfter[3], 0);
+ }
+
+ function test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() public {
+ uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances();
+ _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0);
+
+ // Send as transmitter 1, which has transmitted 1 report
+ vm.stopPrank();
+ vm.startPrank(NOP_TRANSMITTER_ADDRESS_1);
+
+ // Attempt to withdraw with no amount, which will withdraw the full balance
+ s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, 0);
+
+ // 3 report transmissions have been made
+ uint96 totalDonFees = s_donFee * 3;
+ // 4 transmitters will share the DON fees
+ uint96 donFeeShare = totalDonFees / 4;
+ uint96 expectedTransmitterBalance = ((s_fulfillmentCoordinatorBalance - totalDonFees) / 3) + donFeeShare;
+
+ uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances();
+ assertEq(transmitterBalancesAfter[0], expectedTransmitterBalance);
+ assertEq(transmitterBalancesAfter[1], 0);
+ assertEq(transmitterBalancesAfter[2], 0);
+ assertEq(transmitterBalancesAfter[3], 0);
+ }
}
/// @notice #oracleWithdrawAll
@@ -188,37 +350,29 @@ contract FunctionsBilling_OracleWithdrawAll is FunctionsMultipleFulfillmentsSetu
}
function test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() public {
- uint256 transmitter1BalanceBefore = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1);
- assertEq(transmitter1BalanceBefore, 0);
- uint256 transmitter2BalanceBefore = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_2);
- assertEq(transmitter2BalanceBefore, 0);
- uint256 transmitter3BalanceBefore = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_3);
- assertEq(transmitter3BalanceBefore, 0);
- uint256 transmitter4BalanceBefore = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_4);
- assertEq(transmitter4BalanceBefore, 0);
+ uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances();
+ _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0);
s_functionsCoordinator.oracleWithdrawAll();
uint96 expectedTransmitterBalance = s_fulfillmentCoordinatorBalance / 3;
- uint256 transmitter1BalanceAfter = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1);
- assertEq(transmitter1BalanceAfter, expectedTransmitterBalance);
- uint256 transmitter2BalanceAfter = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_2);
- assertEq(transmitter2BalanceAfter, expectedTransmitterBalance);
- uint256 transmitter3BalanceAfter = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_3);
- assertEq(transmitter3BalanceAfter, expectedTransmitterBalance);
+ uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances();
+ assertEq(transmitterBalancesAfter[0], expectedTransmitterBalance);
+ assertEq(transmitterBalancesAfter[1], expectedTransmitterBalance);
+ assertEq(transmitterBalancesAfter[2], expectedTransmitterBalance);
// Transmitter 4 has no balance
- uint256 transmitter4BalanceAfter = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_4);
- assertEq(transmitter4BalanceAfter, 0);
+ assertEq(transmitterBalancesAfter[3], 0);
}
}
-/// @notice #_getTransmitters
-contract FunctionsBilling__GetTransmitters {
- // TODO: make contract internal function helper
-}
-
/// @notice #_disperseFeePool
-contract FunctionsBilling__DisperseFeePool {
- // TODO: make contract internal function helper
+contract FunctionsBilling__DisperseFeePool is FunctionsRouterSetup {
+ function test__DisperseFeePool_RevertIfNotSet() public {
+ // Manually set s_feePool (at slot 11) to 1 to get past first check in _disperseFeePool
+ vm.store(address(s_functionsCoordinator), bytes32(uint256(11)), bytes32(uint256(1)));
+
+ vm.expectRevert(FunctionsBilling.NoTransmittersSet.selector);
+ s_functionsCoordinator.disperseFeePool_HARNESS();
+ }
}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol
index d6a3be1684..363827645c 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol
@@ -2,22 +2,23 @@
pragma solidity ^0.8.19;
import {BaseTest} from "./BaseTest.t.sol";
+import {FunctionsClient} from "../../dev/v1_X/FunctionsClient.sol";
import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol";
import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol";
import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol";
import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol";
-import {FunctionsSubscriptionSetup} from "./Setup.t.sol";
+import {FunctionsClientSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol";
/// @notice #constructor
-contract FunctionsClient_Constructor {
-
+contract FunctionsClient_Constructor is FunctionsClientSetup {
+ function test_Constructor_Success() public {
+ assertEq(address(s_functionsRouter), s_functionsClient.getRouter_HARNESS());
+ }
}
/// @notice #_sendRequest
contract FunctionsClient__SendRequest is FunctionsSubscriptionSetup {
- // TODO: make contract internal function helper
-
function test__SendRequest_RevertIfInvalidCallbackGasLimit() public {
// Build minimal valid request data
string memory sourceCode = "return 'hello world';";
@@ -43,12 +44,35 @@ contract FunctionsClient__SendRequest is FunctionsSubscriptionSetup {
}
}
-/// @notice #fulfillRequest
-contract FunctionsClient_FulfillRequest {
+/// @notice #handleOracleFulfillment
+contract FunctionsClient_HandleOracleFulfillment is FunctionsClientRequestSetup {
+ function test_HandleOracleFulfillment_RevertIfNotRouter() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
-}
+ vm.expectRevert(FunctionsClient.OnlyRouterCanFulfill.selector);
+ s_functionsClient.handleOracleFulfillment(s_requests[1].requestId, new bytes(0), new bytes(0));
+ }
-/// @notice #handleOracleFulfillment
-contract FunctionsClient_HandleOracleFulfillment {
+ event RequestFulfilled(bytes32 indexed id);
+ event ResponseReceived(bytes32 indexed requestId, bytes result, bytes err);
+
+ function test_HandleOracleFulfillment_Success() public {
+ // Send as Router
+ vm.stopPrank();
+ vm.startPrank(address(s_functionsRouter));
+ // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true).
+ bool checkTopic1 = false;
+ bool checkTopic2 = false;
+ bool checkTopic3 = false;
+ bool checkData = true;
+ vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData);
+ emit ResponseReceived(s_requests[1].requestId, new bytes(0), new bytes(0));
+ vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData);
+ emit RequestFulfilled(s_requests[1].requestId);
+
+ s_functionsClient.handleOracleFulfillment(s_requests[1].requestId, new bytes(0), new bytes(0));
+ }
}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol
index 893aa6408b..7166add19f 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol
@@ -4,9 +4,13 @@ pragma solidity ^0.8.19;
import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol";
import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol";
import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol";
+import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol";
import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol";
+import {Routable} from "../../dev/v1_X/Routable.sol";
-import {FunctionsRouterSetup} from "./Setup.t.sol";
+import {BaseTest} from "./BaseTest.t.sol";
+import {FunctionsRouterSetup, FunctionsDONSetup, FunctionsSubscriptionSetup} from "./Setup.t.sol";
+import "forge-std/console.sol";
/// @notice #constructor
contract FunctionsCoordinator_Constructor is FunctionsRouterSetup {
@@ -17,48 +21,220 @@ contract FunctionsCoordinator_Constructor is FunctionsRouterSetup {
}
/// @notice #getThresholdPublicKey
-contract FunctionsCoordinator_GetThresholdPublicKey {
+contract FunctionsCoordinator_GetThresholdPublicKey is FunctionsDONSetup {
+ function test_GetThresholdPublicKey_RevertIfEmpty() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+ // Reverts when empty
+ vm.expectRevert(FunctionsCoordinator.EmptyPublicKey.selector);
+ s_functionsCoordinator.getThresholdPublicKey();
+ }
+
+ function test_GetThresholdPublicKey_Success() public {
+ s_functionsCoordinator.setThresholdPublicKey(s_thresholdKey);
+
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ bytes memory thresholdKey = s_functionsCoordinator.getThresholdPublicKey();
+ assertEq(thresholdKey, s_thresholdKey);
+ }
}
/// @notice #setThresholdPublicKey
-contract FunctionsCoordinator_SetThresholdPublicKey {
+contract FunctionsCoordinator_SetThresholdPublicKey is FunctionsDONSetup {
+ function test_SetThresholdPublicKey_RevertNotOwner() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ vm.expectRevert("Only callable by owner");
+ bytes memory newThresholdKey = new bytes(0);
+ s_functionsCoordinator.setThresholdPublicKey(newThresholdKey);
+ }
+
+ function test_SetThresholdPublicKey_Success() public {
+ s_functionsCoordinator.setThresholdPublicKey(s_thresholdKey);
+
+ bytes memory thresholdKey = s_functionsCoordinator.getThresholdPublicKey();
+ assertEq(thresholdKey, s_thresholdKey);
+ }
}
/// @notice #getDONPublicKey
-contract FunctionsCoordinator_GetDONPublicKey {
+contract FunctionsCoordinator_GetDONPublicKey is FunctionsDONSetup {
+ function test_GetDONPublicKey_RevertIfEmpty() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ // Reverts when empty
+ vm.expectRevert(FunctionsCoordinator.EmptyPublicKey.selector);
+ s_functionsCoordinator.getDONPublicKey();
+ }
+
+ function test_GetDONPublicKey_Success() public {
+ s_functionsCoordinator.setDONPublicKey(s_donKey);
+
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+ bytes memory donKey = s_functionsCoordinator.getDONPublicKey();
+ assertEq(donKey, s_donKey);
+ }
}
/// @notice #setDONPublicKey
-contract FunctionsCoordinator__SetDONPublicKey {
+contract FunctionsCoordinator_SetDONPublicKey is FunctionsDONSetup {
+ function test_SetDONPublicKey_RevertNotOwner() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
+
+ vm.expectRevert("Only callable by owner");
+ s_functionsCoordinator.setDONPublicKey(s_donKey);
+ }
+
+ function test_SetDONPublicKey_Success() public {
+ s_functionsCoordinator.setDONPublicKey(s_donKey);
+ bytes memory donKey = s_functionsCoordinator.getDONPublicKey();
+ assertEq(donKey, s_donKey);
+ }
}
/// @notice #_isTransmitter
-contract FunctionsCoordinator_IsTransmitter {
- // TODO: make contract internal function helper
+contract FunctionsCoordinator__IsTransmitter is FunctionsDONSetup {
+ function test__IsTransmitter_SuccessFound() public {
+ bool isTransmitter = s_functionsCoordinator.isTransmitter_HARNESS(NOP_TRANSMITTER_ADDRESS_1);
+ assertEq(isTransmitter, true);
+ }
+
+ function test__IsTransmitter_SuccessNotFound() public {
+ bool isTransmitter = s_functionsCoordinator.isTransmitter_HARNESS(STRANGER_ADDRESS);
+ assertEq(isTransmitter, false);
+ }
}
-/// @notice #setNodePublicKey
-contract FunctionsCoordinator_SetNodePublicKey {
+/// @notice #startRequest
+contract FunctionsCoordinator_StartRequest is FunctionsSubscriptionSetup {
+ function test_StartRequest_RevertIfNotRouter() public {
+ // Send as stranger
+ vm.stopPrank();
+ vm.startPrank(STRANGER_ADDRESS);
-}
+ vm.expectRevert(Routable.OnlyCallableByRouter.selector);
-/// @notice #deleteNodePublicKey
-contract FunctionsCoordinator_DeleteNodePublicKey {
+ s_functionsCoordinator.startRequest(
+ FunctionsResponse.RequestMeta({
+ requestingContract: address(s_functionsClient),
+ data: new bytes(0),
+ subscriptionId: s_subscriptionId,
+ dataVersion: FunctionsRequest.REQUEST_DATA_VERSION,
+ flags: bytes32(0),
+ callbackGasLimit: 5_500,
+ adminFee: s_adminFee,
+ initiatedRequests: 0,
+ completedRequests: 0,
+ availableBalance: s_subscriptionInitialFunding,
+ subscriptionOwner: OWNER_ADDRESS
+ })
+ );
+ }
-}
+ event OracleRequest(
+ bytes32 indexed requestId,
+ address indexed requestingContract,
+ address requestInitiator,
+ uint64 subscriptionId,
+ address subscriptionOwner,
+ bytes data,
+ uint16 dataVersion,
+ bytes32 flags,
+ uint64 callbackGasLimit,
+ FunctionsResponse.Commitment commitment
+ );
-/// @notice #getAllNodePublicKeys
-contract FunctionsCoordinator_GetAllNodePublicKeys {
+ function test_StartRequest_Success() public {
+ // Send as Router
+ vm.stopPrank();
+ vm.startPrank(address(s_functionsRouter));
+ (, , address txOrigin) = vm.readCallers();
-}
+ bytes memory _requestData = new bytes(0);
+ uint32 _callbackGasLimit = 5_500;
+ uint96 costEstimate = s_functionsCoordinator.estimateCost(
+ s_subscriptionId,
+ _requestData,
+ _callbackGasLimit,
+ tx.gasprice
+ );
+ uint32 timeoutTimestamp = uint32(block.timestamp + getCoordinatorConfig().requestTimeoutSeconds);
+ bytes32 expectedRequestId = keccak256(
+ abi.encode(
+ address(s_functionsCoordinator),
+ address(s_functionsClient),
+ s_subscriptionId,
+ 1,
+ keccak256(_requestData),
+ FunctionsRequest.REQUEST_DATA_VERSION,
+ _callbackGasLimit,
+ costEstimate,
+ timeoutTimestamp,
+ txOrigin
+ )
+ );
-/// @notice #startRequest
-contract FunctionsCoordinator_StartRequest {
+ FunctionsResponse.Commitment memory expectedComittment = FunctionsResponse.Commitment({
+ adminFee: s_adminFee,
+ coordinator: address(s_functionsCoordinator),
+ client: address(s_functionsClient),
+ subscriptionId: s_subscriptionId,
+ callbackGasLimit: _callbackGasLimit,
+ estimatedTotalCostJuels: costEstimate,
+ timeoutTimestamp: timeoutTimestamp,
+ requestId: expectedRequestId,
+ donFee: s_donFee,
+ gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback,
+ gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback
+ });
+ // topic0 (function signature, always checked), topic1 (true), topic2 (true), NOT topic3 (false), and data (true).
+ vm.expectEmit(true, true, false, true);
+ emit OracleRequest({
+ requestId: expectedRequestId,
+ requestingContract: address(s_functionsClient),
+ requestInitiator: txOrigin,
+ subscriptionId: s_subscriptionId,
+ subscriptionOwner: OWNER_ADDRESS,
+ data: _requestData,
+ dataVersion: FunctionsRequest.REQUEST_DATA_VERSION,
+ flags: bytes32(0),
+ callbackGasLimit: _callbackGasLimit,
+ commitment: expectedComittment
+ });
+
+ s_functionsCoordinator.startRequest(
+ FunctionsResponse.RequestMeta({
+ requestingContract: address(s_functionsClient),
+ data: _requestData,
+ subscriptionId: s_subscriptionId,
+ dataVersion: FunctionsRequest.REQUEST_DATA_VERSION,
+ flags: bytes32(0),
+ callbackGasLimit: 5_500,
+ adminFee: s_adminFee,
+ initiatedRequests: 0,
+ completedRequests: 0,
+ availableBalance: s_subscriptionInitialFunding,
+ subscriptionOwner: OWNER_ADDRESS
+ })
+ );
+ }
}
/// @notice #_beforeSetConfig
@@ -73,10 +249,10 @@ contract FunctionsCoordinator__GetTransmitters {
/// @notice #_report
contract FunctionsCoordinator__Report {
-
+ // TODO: make contract internal function helper
}
/// @notice #_onlyOwner
contract FunctionsCoordinator__OnlyOwner {
-
+ // TODO: make contract internal function helper
}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol
index b9b6e1d574..081fe2f664 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol
@@ -938,7 +938,7 @@ contract FunctionsRouter_Fulfill is FunctionsClientRequestSetup {
uint32 callbackGasLimit = s_requests[requestToFulfill].requestData.callbackGasLimit;
// Coordinator sends enough gas that would get through callback and payment, but fail after
- uint256 gasToUse = getCoordinatorConfig().gasOverheadBeforeCallback + callbackGasLimit + 100000;
+ uint256 gasToUse = getCoordinatorConfig().gasOverheadBeforeCallback + callbackGasLimit + 10_000;
// topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true).
bool checkTopic1RequestId = true;
@@ -1221,7 +1221,7 @@ contract FunctionsRouter_Fulfill is FunctionsClientRequestSetup {
emit RequestProcessed({
requestId: s_requests[requestToFulfill].requestId,
subscriptionId: s_subscriptionId,
- totalCostJuels: _getExpectedCost(5393), // gasUsed is manually taken
+ totalCostJuels: _getExpectedCost(5416), // gasUsed is manually taken
transmitter: NOP_TRANSMITTER_ADDRESS_1,
resultCode: FunctionsResponse.FulfillResult.FULFILLED,
response: bytes(response),
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
index 8046bf7d93..df905fb8be 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
@@ -1122,62 +1122,14 @@ contract FunctionsSubscriptions_CancelSubscription is FunctionsSubscriptionSetup
uint256 balanceAfterWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS);
assertEq(balanceBeforeWithdraw + expectedDepositWithheld, balanceAfterWithdraw);
}
+}
- function test_CancelSubscription_SuccessRecieveDeposit() public {
- // Complete 1 request = subscriptionDepositMinimumRequests
- vm.recordLogs();
- bytes32 requestId = s_functionsClient.sendRequest(
- s_donId,
- "return 'hello world';",
- new bytes(0),
- new string[](0),
- new bytes[](0),
- s_subscriptionId,
- 5500
- );
-
- // Get commitment data from OracleRequest event log
- Vm.Log[] memory entries = vm.getRecordedLogs();
- (, , , , , , , FunctionsResponse.Commitment memory commitment) = abi.decode(
- entries[0].data,
- (address, uint64, address, bytes, uint16, bytes32, uint64, FunctionsResponse.Commitment)
- );
-
- // Send as transmitter 1
- vm.stopPrank();
- vm.startPrank(NOP_TRANSMITTER_ADDRESS_1);
-
- // Build report
- bytes32[] memory requestIds = new bytes32[](1);
- requestIds[0] = requestId;
- bytes[] memory results = new bytes[](1);
- results[0] = bytes("hello world!");
- bytes[] memory errors = new bytes[](1);
- // No error
- bytes[] memory onchainMetadata = new bytes[](1);
- onchainMetadata[0] = abi.encode(commitment);
- bytes[] memory offchainMetadata = new bytes[](1);
- // No offchain metadata
- bytes memory report = abi.encode(requestIds, results, errors, onchainMetadata, offchainMetadata);
-
- // Build signers
- address[31] memory signers;
- signers[0] = NOP_SIGNER_ADDRESS_1;
-
- // Send report
- vm.recordLogs();
- s_functionsCoordinator.callReportWithSigners(report, signers);
-
- // Get actual cost from RequestProcessed event log
- Vm.Log[] memory entries2 = vm.getRecordedLogs();
- (uint96 totalCostJuels, , , , , ) = abi.decode(
- entries2[2].data,
- (uint96, address, FunctionsResponse.FulfillResult, bytes, bytes, bytes)
- );
+/// @notice #cancelSubscription
+contract FunctionsSubscriptions_CancelSubscription_ReceiveDeposit is FunctionsFulfillmentSetup {
+ event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount);
- // Return to sending as owner
- vm.stopPrank();
- vm.startPrank(OWNER_ADDRESS);
+ function test_CancelSubscription_SuccessRecieveDeposit() public {
+ uint96 totalCostJuels = s_fulfillmentRouterOwnerBalance + s_fulfillmentCoordinatorBalance;
uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS);
diff --git a/contracts/src/v0.8/functions/tests/v1_X/README.md b/contracts/src/v0.8/functions/tests/v1_X/README.md
index 6400a28dc7..5f96532fb4 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/README.md
+++ b/contracts/src/v0.8/functions/tests/v1_X/README.md
@@ -5,18 +5,21 @@ First set the foundry profile to Functions:
export FOUNDRY_PROFILE=functions
```
-To run all test files use:
+**To run tests use**:
+
+All Functions test files:
```
-forge test -vv
+forge test -vvv
```
To run a specific file use:
```
-forge test -vv --mp src/v0.8/functions/tests/v1_X/[File Name].t.sol
+forge test -vvv --mp src/v0.8/functions/tests/v1_X/[File Name].t.sol
```
-To see coverage:
-First ensure that the correct files are being evaluated. For example, if only v1 contracts are, then temporarily change the Functions profile in `./foundry.toml`.
+**To see coverage**:
+First ensure that the correct files are being evaluated. For example, if only v0 contracts are, then temporarily change the Functions profile in `./foundry.toml`.
+
```
-forge coverage
+forge coverage --ir-minimum
```
\ No newline at end of file
diff --git a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
index f603e83281..0c08fd20cd 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
@@ -2,21 +2,21 @@
pragma solidity ^0.8.19;
import {BaseTest} from "./BaseTest.t.sol";
-import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol";
-import {FunctionsCoordinatorTestHelper} from "./testhelpers/FunctionsCoordinatorTestHelper.sol";
+import {FunctionsClientHarness} from "./testhelpers/FunctionsClientHarness.sol";
+import {FunctionsRouterHarness, FunctionsRouter} from "./testhelpers/FunctionsRouterHarness.sol";
+import {FunctionsCoordinatorHarness} from "./testhelpers/FunctionsCoordinatorHarness.sol";
import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol";
import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol";
import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol";
import {TermsOfServiceAllowList} from "../../dev/v1_X/accessControl/TermsOfServiceAllowList.sol";
-import {FunctionsClientUpgradeHelper} from "./testhelpers/FunctionsClientUpgradeHelper.sol";
import {MockLinkToken} from "../../../mocks/MockLinkToken.sol";
import "forge-std/Vm.sol";
/// @notice Set up to deploy the following contracts: FunctionsRouter, FunctionsCoordinator, LINK/ETH Feed, ToS Allow List, and LINK token
contract FunctionsRouterSetup is BaseTest {
- FunctionsRouter internal s_functionsRouter;
- FunctionsCoordinatorTestHelper internal s_functionsCoordinator; // TODO: use actual FunctionsCoordinator instead of helper
+ FunctionsRouterHarness internal s_functionsRouter;
+ FunctionsCoordinatorHarness internal s_functionsCoordinator;
MockV3Aggregator internal s_linkEthFeed;
TermsOfServiceAllowList internal s_termsOfServiceAllowList;
MockLinkToken internal s_linkToken;
@@ -36,9 +36,9 @@ contract FunctionsRouterSetup is BaseTest {
function setUp() public virtual override {
BaseTest.setUp();
s_linkToken = new MockLinkToken();
- s_functionsRouter = new FunctionsRouter(address(s_linkToken), getRouterConfig());
+ s_functionsRouter = new FunctionsRouterHarness(address(s_linkToken), getRouterConfig());
s_linkEthFeed = new MockV3Aggregator(0, LINK_ETH_RATE);
- s_functionsCoordinator = new FunctionsCoordinatorTestHelper(
+ s_functionsCoordinator = new FunctionsCoordinatorHarness(
address(s_functionsRouter),
getCoordinatorConfig(),
address(s_linkEthFeed)
@@ -68,8 +68,8 @@ contract FunctionsRouterSetup is BaseTest {
return
FunctionsBilling.Config({
feedStalenessSeconds: 24 * 60 * 60, // 1 day
- gasOverheadAfterCallback: 50_000, // TODO: update
- gasOverheadBeforeCallback: 100_00, // TODO: update
+ gasOverheadAfterCallback: 93_942,
+ gasOverheadBeforeCallback: 105_000,
requestTimeoutSeconds: 60 * 5, // 5 minutes
donFee: s_donFee,
maxSupportedRequestDataVersion: 1,
@@ -111,6 +111,15 @@ contract FunctionsDONSetup is FunctionsRouterSetup {
uint64 internal s_offchainConfigVersion = 1;
bytes internal s_offchainConfig = new bytes(0);
+ bytes s_thresholdKey =
+ vm.parseBytes(
+ "0x7b2247726f7570223a2250323536222c22475f626172223a22424f2f344358424575792f64547a436a612b614e774d666c2b645a77346d325036533246536b4966472f6633527547327337392b494e79642b4639326a346f586e67433657427561556a752b4a637a32377834484251343d222c2248223a224250532f72485065377941467232416c447a79395549466258776d46384666756632596d514177666e3342373844336f474845643247474536466e616f34552b4c6a4d4d5756792b464f7075686e77554f6a75427a64773d222c22484172726179223a5b22424d75546862414473337768316e67764e56792f6e3841316d42674b5a4b4c475259385937796a39695769337242502f316a32347571695869534531437554384c6f51446a386248466d384345477667517158494e62383d222c224248687974716d6e34314373322f4658416f43737548687151486236382f597930524b2b41354c6647654f645a78466f4e386c442b45656e4b587a544943784f6d3231636d535447364864484a6e336342645663714c673d222c22424d794e7a4534616e596258474d72694f52664c52634e7239766c347878654279316432452f4464335a744630546372386267567435582b2b42355967552b4b7875726e512f4d656b6857335845782b79506e4e4f584d3d222c22424d6a753272375a657a4a45545539413938746a6b6d547966796a79493735345742555835505174724a6578346d6766366130787373426d50325a7472412b55576d504e592b6d4664526b46674f7944694c53614e59453d225d7d"
+ );
+ bytes s_donKey =
+ vm.parseBytes(
+ "0xf2f9c47363202d89aa9fa70baf783d70006fe493471ac8cfa82f1426fd09f16a5f6b32b7c4b5d5165cd147a6e513ba4c0efd39d969d6b20a8a21126f0411b9c6"
+ );
+
function setUp() public virtual override {
FunctionsRouterSetup.setUp();
@@ -136,6 +145,22 @@ contract FunctionsDONSetup is FunctionsRouterSetup {
s_offchainConfig
);
}
+
+ function _getTransmitterBalances() internal view returns (uint256[4] memory balances) {
+ return [
+ s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1),
+ s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_2),
+ s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_3),
+ s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_4)
+ ];
+ }
+
+ function _assertTransmittersAllHaveBalance(uint256[4] memory balances, uint256 expectedBalance) internal {
+ assertEq(balances[0], expectedBalance);
+ assertEq(balances[1], expectedBalance);
+ assertEq(balances[2], expectedBalance);
+ assertEq(balances[3], expectedBalance);
+ }
}
/// @notice Set up to add the Coordinator and ToS Allow Contract as routes on the Router contract
@@ -172,12 +197,12 @@ contract FunctionsOwnerAcceptTermsOfServiceSetup is FunctionsRoutesSetup {
/// @notice Set up to deploy a consumer contract
contract FunctionsClientSetup is FunctionsOwnerAcceptTermsOfServiceSetup {
- FunctionsClientUpgradeHelper internal s_functionsClient;
+ FunctionsClientHarness internal s_functionsClient;
function setUp() public virtual override {
FunctionsOwnerAcceptTermsOfServiceSetup.setUp();
- s_functionsClient = new FunctionsClientUpgradeHelper(address(s_functionsRouter));
+ s_functionsClient = new FunctionsClientHarness(address(s_functionsRouter));
}
}
@@ -261,7 +286,7 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
vm.recordLogs();
- bytes32 requestId = FunctionsClientUpgradeHelper(client).sendRequest(
+ bytes32 requestId = FunctionsClientHarness(client).sendRequest(
s_donId,
sourceCode,
secrets,
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol
new file mode 100644
index 0000000000..ec3b5a65fe
--- /dev/null
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.19;
+
+import {FunctionsClientUpgradeHelper} from "./FunctionsClientUpgradeHelper.sol";
+import {FunctionsResponse} from "../../../dev/v1_X/libraries/FunctionsResponse.sol";
+
+/// @title Functions Client Test Harness
+/// @notice Contract to expose internal functions for testing purposes
+contract FunctionsClientHarness is FunctionsClientUpgradeHelper {
+ constructor(address router) FunctionsClientUpgradeHelper(router) {}
+
+ function getRouter_HARNESS() external view returns (address) {
+ return address(i_router);
+ }
+
+ function sendRequest_HARNESS(
+ bytes memory data,
+ uint64 subscriptionId,
+ uint32 callbackGasLimit,
+ bytes32 donId
+ ) external returns (bytes32) {
+ return super._sendRequest(data, subscriptionId, callbackGasLimit, donId);
+ }
+}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol
index bca0f0a3fa..bc73544205 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.6;
+pragma solidity ^0.8.19;
import {ITermsOfServiceAllowList} from "../../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol";
import {IFunctionsSubscriptions} from "../../../dev/v1_X/interfaces/IFunctionsSubscriptions.sol";
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol
index 362b21d89b..e567471773 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.6;
+pragma solidity ^0.8.19;
import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol";
import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol";
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol
new file mode 100644
index 0000000000..bc103fc356
--- /dev/null
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.19;
+
+import {FunctionsCoordinator} from "../../../dev/v1_X/FunctionsCoordinator.sol";
+import {FunctionsBilling} from "../../../dev/v1_X/FunctionsBilling.sol";
+import {FunctionsResponse} from "../../../dev/v1_X/libraries/FunctionsResponse.sol";
+
+/// @title Functions Coordinator Test Harness
+/// @notice Contract to expose internal functions for testing purposes
+contract FunctionsCoordinatorHarness is FunctionsCoordinator {
+ address s_linkToNativeFeed_HARNESS;
+ address s_router_HARNESS;
+
+ constructor(
+ address router,
+ FunctionsBilling.Config memory config,
+ address linkToNativeFeed
+ ) FunctionsCoordinator(router, config, linkToNativeFeed) {
+ s_linkToNativeFeed_HARNESS = linkToNativeFeed;
+ s_router_HARNESS = router;
+ }
+
+ function isTransmitter_HARNESS(address node) external view returns (bool) {
+ return super._isTransmitter(node);
+ }
+
+ function beforeSetConfig_HARNESS(uint8 _f, bytes memory _onchainConfig) external {
+ return super._beforeSetConfig(_f, _onchainConfig);
+ }
+
+ /// @dev Used by FunctionsBilling.sol
+ function getTransmitters_HARNESS() external view returns (address[] memory) {
+ return super._getTransmitters();
+ }
+
+ function report_HARNESS(
+ uint256 initialGas,
+ address transmitter,
+ uint8 signerCount,
+ address[MAX_NUM_ORACLES] memory signers,
+ bytes calldata report
+ ) external {
+ return super._report(initialGas, transmitter, signerCount, signers, report);
+ }
+
+ function onlyOwner_HARNESS() external view {
+ return super._onlyOwner();
+ }
+
+ // ================================================================
+ // | Functions Billing |
+ // ================================================================
+
+ function getLinkToNativeFeed_HARNESS() external view returns (address) {
+ return s_linkToNativeFeed_HARNESS;
+ }
+
+ function getRouter_HARNESS() external view returns (address) {
+ return s_router_HARNESS;
+ }
+
+ function calculateCostEstimate_HARNESS(
+ uint32 callbackGasLimit,
+ uint256 gasPriceWei,
+ uint72 donFee,
+ uint72 adminFee
+ ) external view returns (uint96) {
+ return super._calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee);
+ }
+
+ function startBilling_HARNESS(
+ FunctionsResponse.RequestMeta memory request
+ ) external returns (FunctionsResponse.Commitment memory commitment) {
+ return super._startBilling(request);
+ }
+
+ function fulfillAndBill_HARNESS(
+ bytes32 requestId,
+ bytes memory response,
+ bytes memory err,
+ bytes memory onchainMetadata,
+ bytes memory offchainMetadata
+ ) external returns (FunctionsResponse.FulfillResult) {
+ return super._fulfillAndBill(requestId, response, err, onchainMetadata, offchainMetadata);
+ }
+
+ function disperseFeePool_HARNESS() external {
+ return super._disperseFeePool();
+ }
+
+ // ================================================================
+ // | OCR2 |
+ // ================================================================
+
+ function configDigestFromConfigData_HARNESS(
+ uint256 _chainId,
+ address _contractAddress,
+ uint64 _configCount,
+ address[] memory _signers,
+ address[] memory _transmitters,
+ uint8 _f,
+ bytes memory _onchainConfig,
+ uint64 _encodedConfigVersion,
+ bytes memory _encodedConfig
+ ) internal pure returns (bytes32) {
+ return
+ super._configDigestFromConfigData(
+ _chainId,
+ _contractAddress,
+ _configCount,
+ _signers,
+ _transmitters,
+ _f,
+ _onchainConfig,
+ _encodedConfigVersion,
+ _encodedConfig
+ );
+ }
+}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol
index 1d883b3b29..5e57e62e59 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.6;
+pragma solidity ^0.8.19;
import {FunctionsCoordinator} from "../../../dev/v1_X/FunctionsCoordinator.sol";
import {FunctionsBilling} from "../../../dev/v1_X/FunctionsBilling.sol";
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol
new file mode 100644
index 0000000000..7caeff498a
--- /dev/null
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.19;
+
+import {FunctionsRouter} from "../../../dev/v1_X/FunctionsRouter.sol";
+
+/// @title Functions Router Test Harness
+/// @notice Contract to expose internal functions for testing purposes
+contract FunctionsRouterHarness is FunctionsRouter {
+ constructor(address linkToken, Config memory config) FunctionsRouter(linkToken, config) {}
+
+ function getMaxConsumers_HARNESS() external view returns (uint16) {
+ return super._getMaxConsumers();
+ }
+
+ function getSubscriptionDepositDetails_HARNESS() external view returns (uint16, uint72) {
+ return super._getSubscriptionDepositDetails();
+ }
+
+ function whenNotPaused_HARNESS() external view {
+ return super._whenNotPaused();
+ }
+
+ function onlyRouterOwner_HARNESS() external view {
+ return super._onlyRouterOwner();
+ }
+
+ function onlySenderThatAcceptedToS_HARNESS() external view {
+ return super._onlySenderThatAcceptedToS();
+ }
+}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol
new file mode 100644
index 0000000000..2e2427f6e1
--- /dev/null
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.19;
+
+import {FunctionsSubscriptions} from "../../../dev/v1_X/FunctionsSubscriptions.sol";
+
+/// @title Functions Subscriptions Test Harness
+/// @notice Contract to expose internal functions for testing purposes
+contract FunctionsSubscriptionsHarness is FunctionsSubscriptions {
+ constructor(address link) FunctionsSubscriptions(link) {}
+
+ function markRequestInFlight_HARNESS(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) external {
+ return super._markRequestInFlight(client, subscriptionId, estimatedTotalCostJuels);
+ }
+
+ function pay_HARNESS(
+ uint64 subscriptionId,
+ uint96 estimatedTotalCostJuels,
+ address client,
+ uint96 adminFee,
+ uint96 juelsPerGas,
+ uint96 gasUsed,
+ uint96 costWithoutCallbackJuels
+ ) external returns (Receipt memory) {
+ return
+ super._pay(
+ subscriptionId,
+ estimatedTotalCostJuels,
+ client,
+ adminFee,
+ juelsPerGas,
+ gasUsed,
+ costWithoutCallbackJuels
+ );
+ }
+
+ function isExistingSubscription_HARNESS(uint64 subscriptionId) external view {
+ return super._isExistingSubscription(subscriptionId);
+ }
+
+ function isAllowedConsumer_HARNESS(address client, uint64 subscriptionId) external view {
+ return super._isAllowedConsumer(client, subscriptionId);
+ }
+
+ // Overrides
+ function _getMaxConsumers() internal view override returns (uint16) {}
+
+ function _getSubscriptionDepositDetails() internal override returns (uint16, uint72) {}
+
+ function _onlySenderThatAcceptedToS() internal override {}
+
+ function _onlyRouterOwner() internal override {}
+
+ function _whenNotPaused() internal override {}
+}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol
index e8e74e3ed7..50e90c4495 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.6;
+pragma solidity ^0.8.19;
import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol";
From e9c820632bfd2cf7da0c40ce547af13cd53748de Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Wed, 25 Oct 2023 02:47:50 -0400
Subject: [PATCH 002/327] (chore): Reduce contracts solhint warnings by
ignoring Functions v1.0.0 production code (#11069)
---
contracts/.solhintignore | 4 ++--
contracts/package.json | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/contracts/.solhintignore b/contracts/.solhintignore
index 1a308af94b..53d52657ec 100644
--- a/contracts/.solhintignore
+++ b/contracts/.solhintignore
@@ -1,8 +1,8 @@
# 351 warnings
#./src/v0.8/automation
-# 27 warnings
-#./src/v0.8/functions
+# Ignore Functions v1.0.0 code that was frozen after audit
+./src/v0.8/functions/v1_0_0
# Ignore tests, this should not be the long term plan but is OK in the short term
./src/v0.8/**/*.t.sol
diff --git a/contracts/package.json b/contracts/package.json
index 6c902926c2..75b1ddfa97 100644
--- a/contracts/package.json
+++ b/contracts/package.json
@@ -18,7 +18,7 @@
"prepublishOnly": "pnpm compile && ./scripts/prepublish_generate_abi_folder",
"publish-beta": "pnpm publish --tag beta",
"publish-prod": "npm dist-tag add @chainlink/contracts@0.8.0 latest",
- "solhint": "solhint --max-warnings 442 \"./src/v0.8/**/*.sol\""
+ "solhint": "solhint --max-warnings 351 \"./src/v0.8/**/*.sol\""
},
"files": [
"src/v0.8",
From 5e75873305b79b6a313813a29e604678953c291f Mon Sep 17 00:00:00 2001
From: Mohamed Mehany <7327188+mohamed-mehany@users.noreply.github.com>
Date: Wed, 25 Oct 2023 10:57:56 +0200
Subject: [PATCH 003/327] Fix redundant "replacing abandoned tx" logs (#11019)
This fixes the issue of incorrectly logging the "replacing abandoned tx"
log. The DELETE query doesn't return a sql.ErrNoRows on failing to find
rows to be deleted. Instead we are checking on the count of RowsAffected.
Another minor fix is continuing to execute the function if no attempts
were deleted, instead of throwing an error, since at this point there is
no need to break the execution flow.
Co-authored-by: Simson
---
core/chains/evm/txmgr/evm_tx_store.go | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 7b1ef8948c..96963e78d7 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -1486,14 +1486,20 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx,
// Note: the record of the original abandoned transaction will remain in evm.txes, only the attempt is replaced. (Any receipt
// associated with the abandoned attempt would also be lost, although this shouldn't happen since only unconfirmed transactions
// can be abandoned.)
- _, err := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t
+ result, err := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t
WHERE t.id = a.eth_tx_id AND a.hash = $1 AND t.state = $2 AND t.error = 'abandoned'`,
attempt.Hash, txmgr.TxFatalError,
)
if err == nil {
- o.logger.Debugf("Replacing abandoned tx with tx hash %s with tx_id=%d with identical tx hash", attempt.Hash, attempt.TxID)
- } else if errors.Is(err, sql.ErrNoRows) {
- return err
+ count, err := result.RowsAffected()
+ if err != nil {
+ return pkgerrors.Wrap(err, "UpdateTxUnstartedToInProgress failed to get rows affected")
+ }
+ if count > 0 {
+ o.logger.Debugf("Replacing abandoned tx with tx hash %s with tx_id=%d with identical tx hash", attempt.Hash, attempt.TxID)
+ }
+ } else {
+ return pkgerrors.Wrap(err, "UpdateTxUnstartedToInProgress failed to delete abandoned transactions")
}
var dbAttempt DbEthTxAttempt
From 8743742d827a4717d78ee5c0276b2cf3d88d356e Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Wed, 25 Oct 2023 12:17:04 +0200
Subject: [PATCH 004/327] Bump breaking NPM deps (#11003)
* bump typechain/hardhat
* bump typechain/hardhat
* bump nomiclabs/hardhat-etherscan
* Pin cbor v5.2.0 dependency
* bump hardhat-abi-exporter
* bump hardhat-contract-sizer
* bump typechain/ethers-v5
* Revert "bump typechain/ethers-v5"
This reverts commit ea695e7138115c61ddfd7aa2f6030614e7b16a61.
* solhint wrong issue number
---------
Co-authored-by: Justin Kaseman
---
contracts/.solhintignore | 2 +-
contracts/package.json | 11 ++--
contracts/pnpm-lock.yaml | 105 +++++++++++++++++++++++----------------
3 files changed, 69 insertions(+), 49 deletions(-)
diff --git a/contracts/.solhintignore b/contracts/.solhintignore
index 53d52657ec..bc7be4fbfe 100644
--- a/contracts/.solhintignore
+++ b/contracts/.solhintignore
@@ -1,4 +1,4 @@
-# 351 warnings
+# 377 warnings
#./src/v0.8/automation
# Ignore Functions v1.0.0 code that was frozen after audit
diff --git a/contracts/package.json b/contracts/package.json
index 75b1ddfa97..46b47440a6 100644
--- a/contracts/package.json
+++ b/contracts/package.json
@@ -18,7 +18,7 @@
"prepublishOnly": "pnpm compile && ./scripts/prepublish_generate_abi_folder",
"publish-beta": "pnpm publish --tag beta",
"publish-prod": "npm dist-tag add @chainlink/contracts@0.8.0 latest",
- "solhint": "solhint --max-warnings 351 \"./src/v0.8/**/*.sol\""
+ "solhint": "solhint --max-warnings 377 \"./src/v0.8/**/*.sol\""
},
"files": [
"src/v0.8",
@@ -40,12 +40,12 @@
"@ethersproject/random": "~5.7.0",
"@nomicfoundation/hardhat-network-helpers": "^1.0.9",
"@nomiclabs/hardhat-ethers": "^2.2.3",
- "@nomiclabs/hardhat-etherscan": "^3.1.0",
+ "@nomiclabs/hardhat-etherscan": "^3.1.7",
"@nomiclabs/hardhat-waffle": "2.0.6",
"@openzeppelin/hardhat-upgrades": "1.28.0",
"@openzeppelin/test-helpers": "^0.5.16",
"@typechain/ethers-v5": "^7.2.0",
- "@typechain/hardhat": "^5.0.0",
+ "@typechain/hardhat": "^7.0.0",
"@types/cbor": "5.0.1",
"@types/chai": "^4.3.9",
"@types/debug": "^4.1.10",
@@ -55,6 +55,7 @@
"@typescript-eslint/eslint-plugin": "^6.8.0",
"@typescript-eslint/parser": "^6.8.0",
"abi-to-sol": "^0.6.6",
+ "cbor": "^5.2.0",
"chai": "^4.3.10",
"debug": "^4.3.4",
"eslint": "^8.51.0",
@@ -64,8 +65,8 @@
"ethereum-waffle": "^3.4.4",
"ethers": "~5.7.2",
"hardhat": "~2.18.1",
- "hardhat-abi-exporter": "^2.2.1",
- "hardhat-contract-sizer": "^2.5.1",
+ "hardhat-abi-exporter": "^2.10.1",
+ "hardhat-contract-sizer": "^2.10.0",
"hardhat-gas-reporter": "^1.0.9",
"hardhat-ignore-warnings": "^0.2.6",
"istanbul": "^0.4.5",
diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml
index 9d54cfa774..65865f2adf 100644
--- a/contracts/pnpm-lock.yaml
+++ b/contracts/pnpm-lock.yaml
@@ -44,14 +44,14 @@ devDependencies:
specifier: ^2.2.3
version: 2.2.3(ethers@5.7.2)(hardhat@2.18.1)
'@nomiclabs/hardhat-etherscan':
- specifier: ^3.1.0
- version: 3.1.0(hardhat@2.18.1)
+ specifier: ^3.1.7
+ version: 3.1.7(hardhat@2.18.1)
'@nomiclabs/hardhat-waffle':
specifier: 2.0.6
version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.18.1)
'@openzeppelin/hardhat-upgrades':
specifier: 1.28.0
- version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.0)(ethers@5.7.2)(hardhat@2.18.1)
+ version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.18.1)
'@openzeppelin/test-helpers':
specifier: ^0.5.16
version: 0.5.16(bn.js@4.12.0)
@@ -59,8 +59,8 @@ devDependencies:
specifier: ^7.2.0
version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.2.0)(typescript@5.2.2)
'@typechain/hardhat':
- specifier: ^5.0.0
- version: 5.0.0(hardhat@2.18.1)(lodash@4.17.21)(typechain@8.2.0)
+ specifier: ^7.0.0
+ version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.18.1)(typechain@8.2.0)
'@types/cbor':
specifier: 5.0.1
version: 5.0.1
@@ -88,6 +88,9 @@ devDependencies:
abi-to-sol:
specifier: ^0.6.6
version: 0.6.6
+ cbor:
+ specifier: ^5.2.0
+ version: 5.2.0
chai:
specifier: ^4.3.10
version: 4.3.10
@@ -116,11 +119,11 @@ devDependencies:
specifier: ~2.18.1
version: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
hardhat-abi-exporter:
- specifier: ^2.2.1
- version: 2.2.1(hardhat@2.18.1)
+ specifier: ^2.10.1
+ version: 2.10.1(hardhat@2.18.1)
hardhat-contract-sizer:
- specifier: ^2.5.1
- version: 2.5.1(hardhat@2.18.1)
+ specifier: ^2.10.0
+ version: 2.10.0(hardhat@2.18.1)
hardhat-gas-reporter:
specifier: ^1.0.9
version: 1.0.9(hardhat@2.18.1)
@@ -1159,22 +1162,22 @@ packages:
hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
dev: true
- /@nomiclabs/hardhat-etherscan@3.1.0(hardhat@2.18.1):
- resolution: {integrity: sha512-JroYgfN1AlYFkQTQ3nRwFi4o8NtZF7K/qFR2dxDUgHbCtIagkUseca9L4E/D2ScUm4XT40+8PbCdqZi+XmHyQA==}
+ /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.18.1):
+ resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==}
peerDependencies:
hardhat: ^2.0.4
dependencies:
'@ethersproject/abi': 5.7.0
'@ethersproject/address': 5.7.0
- cbor: 5.2.0
+ cbor: 8.1.0
chalk: 2.4.2
debug: 4.3.4(supports-color@8.1.1)
fs-extra: 7.0.1
hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
lodash: 4.17.21
semver: 6.3.0
- table: 6.8.0
- undici: 5.10.0
+ table: 6.8.1
+ undici: 5.19.1
transitivePeerDependencies:
- supports-color
dev: true
@@ -1223,7 +1226,7 @@ packages:
- encoding
dev: true
- /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.0)(ethers@5.7.2)(hardhat@2.18.1):
+ /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.18.1):
resolution: {integrity: sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==}
hasBin: true
peerDependencies:
@@ -1237,7 +1240,7 @@ packages:
optional: true
dependencies:
'@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.18.1)
- '@nomiclabs/hardhat-etherscan': 3.1.0(hardhat@2.18.1)
+ '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.18.1)
'@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4)
'@openzeppelin/platform-deploy-client': 0.8.0(debug@4.3.4)
'@openzeppelin/upgrades-core': 1.30.1
@@ -1645,16 +1648,22 @@ packages:
typescript: 5.2.2
dev: true
- /@typechain/hardhat@5.0.0(hardhat@2.18.1)(lodash@4.17.21)(typechain@8.2.0):
- resolution: {integrity: sha512-Pqk+KdREbU6Uk3en1Z5caQpWt2bKU+KTOi+6dZwcIXJpF1wKoAwF1cbaYSQEzrG4BSUTM1rHQhW5JHSfeqpsAg==}
+ /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.18.1)(typechain@8.2.0):
+ resolution: {integrity: sha512-XB79i5ewg9Met7gMVGfgVkmypicbnI25T5clJBEooMoW2161p4zvKFpoS2O+lBppQyMrPIZkdvl2M3LMDayVcA==}
peerDependencies:
- hardhat: ^2.0.10
- lodash: ^4.17.15
- typechain: ^7.0.0
+ '@ethersproject/abi': ^5.4.7
+ '@ethersproject/providers': ^5.4.7
+ '@typechain/ethers-v5': ^11.0.0
+ ethers: ^5.4.7
+ hardhat: ^2.9.9
+ typechain: ^8.2.0
dependencies:
+ '@ethersproject/abi': 5.7.0
+ '@ethersproject/providers': 5.7.2
+ '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.2.0)(typescript@5.2.2)
+ ethers: 5.7.2
fs-extra: 9.1.0
hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
- lodash: 4.17.21
typechain: 8.2.0(typescript@5.2.2)
dev: true
@@ -3487,6 +3496,13 @@ packages:
nofilter: 1.0.4
dev: true
+ /cbor@8.1.0:
+ resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==}
+ engines: {node: '>=12.19'}
+ dependencies:
+ nofilter: 3.1.0
+ dev: true
+
/cbor@9.0.1:
resolution: {integrity: sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==}
engines: {node: '>=16'}
@@ -4324,6 +4340,17 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
+ /delete-empty@3.0.0:
+ resolution: {integrity: sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ ansi-colors: 4.1.3
+ minimist: 1.2.8
+ path-starts-with: 2.0.1
+ rimraf: 2.7.1
+ dev: true
+
/depd@1.1.2:
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
engines: {node: '>= 0.6'}
@@ -6273,23 +6300,26 @@ packages:
har-schema: 2.0.0
dev: true
- /hardhat-abi-exporter@2.2.1(hardhat@2.18.1):
- resolution: {integrity: sha512-Um7+RPvJEj+OqWjPoPKlTTkO1Akr10pqpgMk8Pw2jz2wrGv5XQBGNW5aQgGVDUosYktUIWDaEhcwwFKbFsir9A==}
- engines: {node: '>=12.10.0'}
+ /hardhat-abi-exporter@2.10.1(hardhat@2.18.1):
+ resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==}
+ engines: {node: '>=14.14.0'}
peerDependencies:
hardhat: ^2.0.0
dependencies:
+ '@ethersproject/abi': 5.7.0
+ delete-empty: 3.0.0
hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
dev: true
- /hardhat-contract-sizer@2.5.1(hardhat@2.18.1):
- resolution: {integrity: sha512-28yRb73e30aBVaZOOHTlHZFIdIasA/iFunIehrUviIJTubvdQjtSiQUo2wexHFtt71mQeMPP8qjw2sdbgatDnQ==}
+ /hardhat-contract-sizer@2.10.0(hardhat@2.18.1):
+ resolution: {integrity: sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==}
peerDependencies:
hardhat: ^2.0.0
dependencies:
chalk: 4.1.2
cli-table3: 0.6.3
hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ strip-ansi: 6.0.1
dev: true
/hardhat-gas-reporter@1.0.9(hardhat@2.18.1):
@@ -8916,6 +8946,11 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
+ /path-starts-with@2.0.1:
+ resolution: {integrity: sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg==}
+ engines: {node: '>=8'}
+ dev: true
+
/path-to-regexp@0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
requiresBuild: true
@@ -10730,17 +10765,6 @@ packages:
wordwrapjs: 4.0.1
dev: true
- /table@6.8.0:
- resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==}
- engines: {node: '>=10.0.0'}
- dependencies:
- ajv: 8.11.0
- lodash.truncate: 4.4.2
- slice-ansi: 4.0.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
- dev: true
-
/table@6.8.1:
resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==}
engines: {node: '>=10.0.0'}
@@ -11244,11 +11268,6 @@ packages:
dev: true
optional: true
- /undici@5.10.0:
- resolution: {integrity: sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==}
- engines: {node: '>=12.18'}
- dev: true
-
/undici@5.19.1:
resolution: {integrity: sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A==}
engines: {node: '>=12.18'}
From 8dd240f7f69804c5103dbdfc8d5008d86139868b Mon Sep 17 00:00:00 2001
From: Cedric
Date: Wed, 25 Oct 2023 12:52:03 +0100
Subject: [PATCH 005/327] [BCF-2725] Add the repository name to the flakey test
runner output (#11078)
* [BCF-2725] Surface the repo in flakeytestrunner
* Use back-quoted strings
---
.github/workflows/ci-core.yml | 4 ++++
tools/flakeytests/cmd/runner/main.go | 4 +++-
tools/flakeytests/reporter.go | 4 +++-
tools/flakeytests/reporter_test.go | 14 +++++++-------
tools/flakeytests/utils.go | 24 ++++++++++++++----------
5 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml
index d6991bb4e6..74ca1dae9a 100644
--- a/.github/workflows/ci-core.yml
+++ b/.github/workflows/ci-core.yml
@@ -156,12 +156,16 @@ jobs:
GRAFANA_CLOUD_BASIC_AUTH: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
GRAFANA_CLOUD_HOST: ${{ secrets.GRAFANA_CLOUD_HOST }}
GITHUB_EVENT_PATH: ${{ github.event_path }}
+ GITHUB_EVENT_NAME: ${{ github.event_name }}
+ GITHUB_REPO: ${{ github.repository }}
run: |
./runner \
-grafana_auth=$GRAFANA_CLOUD_BASIC_AUTH \
-grafana_host=$GRAFANA_CLOUD_HOST \
-gh_sha=$GITHUB_SHA \
-gh_event_path=$GITHUB_EVENT_PATH \
+ -gh_event_name=$GITHUB_EVENT_NAME \
+ -gh_repo=$GITHUB_REPO \
-command=./tools/bin/go_core_tests \
`ls -R ./artifacts/go_core_tests*/output.txt`
- name: Store logs artifacts
diff --git a/tools/flakeytests/cmd/runner/main.go b/tools/flakeytests/cmd/runner/main.go
index aea69a134b..601832a837 100644
--- a/tools/flakeytests/cmd/runner/main.go
+++ b/tools/flakeytests/cmd/runner/main.go
@@ -18,6 +18,8 @@ func main() {
command := flag.String("command", "", "test command being rerun; used to tag metrics")
ghSHA := flag.String("gh_sha", "", "commit sha for which we're rerunning tests")
ghEventPath := flag.String("gh_event_path", "", "path to associated gh event")
+ ghEventName := flag.String("gh_event_name", "", "type of associated gh event")
+ ghRepo := flag.String("gh_repo", "", "name of gh repository")
flag.Parse()
if *grafanaHost == "" {
@@ -45,7 +47,7 @@ func main() {
readers = append(readers, r)
}
- ctx := flakeytests.GetGithubMetadata(*ghSHA, *ghEventPath)
+ ctx := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath)
rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *command, ctx)
r := flakeytests.NewRunner(readers, rep, numReruns)
err := r.Run()
diff --git a/tools/flakeytests/reporter.go b/tools/flakeytests/reporter.go
index beecd8b3e4..db3890b5c7 100644
--- a/tools/flakeytests/reporter.go
+++ b/tools/flakeytests/reporter.go
@@ -33,8 +33,10 @@ type numFlakes struct {
}
type Context struct {
- CommitSHA string `json:"commit_sha,omitempty"`
+ CommitSHA string `json:"commit_sha"`
PullRequestURL string `json:"pull_request_url,omitempty"`
+ Repository string `json:"repository"`
+ Type string `json:"event_type"`
}
type LokiReporter struct {
diff --git a/tools/flakeytests/reporter_test.go b/tools/flakeytests/reporter_test.go
index f63b89273c..9cb2c8e9f7 100644
--- a/tools/flakeytests/reporter_test.go
+++ b/tools/flakeytests/reporter_test.go
@@ -23,8 +23,8 @@ func TestMakeRequest_SingleTest(t *testing.T) {
assert.Len(t, pr.Streams, 1)
assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"})
assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{
- {ts, "{\"package\":\"core/assets\",\"test_name\":\"TestLink\",\"fq_test_name\":\"core/assets:TestLink\"}"},
- {ts, "{\"num_flakes\":1}"},
+ {ts, `{"package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink","commit_sha":"","repository":"","event_type":""}`},
+ {ts, `{"num_flakes":1,"commit_sha":"","repository":"","event_type":""}`},
})
}
@@ -44,9 +44,9 @@ func TestMakeRequest_MultipleTests(t *testing.T) {
assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"})
assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{
- {ts, "{\"package\":\"core/assets\",\"test_name\":\"TestLink\",\"fq_test_name\":\"core/assets:TestLink\"}"},
- {ts, "{\"package\":\"core/assets\",\"test_name\":\"TestCore\",\"fq_test_name\":\"core/assets:TestCore\"}"},
- {ts, "{\"num_flakes\":2}"},
+ {ts, `{"package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink","commit_sha":"","repository":"","event_type":""}`},
+ {ts, `{"package":"core/assets","test_name":"TestCore","fq_test_name":"core/assets:TestCore","commit_sha":"","repository":"","event_type":""}`},
+ {ts, `{"num_flakes":2,"commit_sha":"","repository":"","event_type":""}`},
})
}
@@ -60,7 +60,7 @@ func TestMakeRequest_NoTests(t *testing.T) {
assert.Len(t, pr.Streams, 1)
assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"})
assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{
- {ts, "{\"num_flakes\":0}"},
+ {ts, `{"num_flakes":0,"commit_sha":"","repository":"","event_type":""}`},
})
}
@@ -74,6 +74,6 @@ func TestMakeRequest_WithContext(t *testing.T) {
assert.Len(t, pr.Streams, 1)
assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"})
assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{
- {ts, "{\"num_flakes\":0,\"commit_sha\":\"42\"}"},
+ {ts, `{"num_flakes":0,"commit_sha":"42","repository":"","event_type":""}`},
})
}
diff --git a/tools/flakeytests/utils.go b/tools/flakeytests/utils.go
index 0b95193b2b..18ab43980b 100644
--- a/tools/flakeytests/utils.go
+++ b/tools/flakeytests/utils.go
@@ -29,7 +29,7 @@ func DigString(mp map[string]interface{}, path []string) (string, error) {
return vs, nil
}
-func GetGithubMetadata(sha string, path string) Context {
+func GetGithubMetadata(repo string, eventName string, sha string, path string) Context {
event := map[string]interface{}{}
if path != "" {
r, err := os.Open(path)
@@ -48,14 +48,18 @@ func GetGithubMetadata(sha string, path string) Context {
}
}
- prURL := ""
- url, err := DigString(event, []string{"pull_request", "_links", "html", "href"})
- if err == nil {
- prURL = url
- }
- ctx := Context{
- CommitSHA: sha,
- PullRequestURL: prURL,
+ basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName}
+ switch eventName {
+ case "pull_request":
+ prURL := ""
+ url, err := DigString(event, []string{"pull_request", "_links", "html", "href"})
+ if err == nil {
+ prURL = url
+ }
+
+ basicCtx.PullRequestURL = prURL
+ return *basicCtx
+ default:
+ return *basicCtx
}
- return ctx
}
From d8463be40baaf4f75113c51d883b355c8541accf Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Wed, 25 Oct 2023 08:07:31 -0500
Subject: [PATCH 006/327] core/internal/testutils/configtest: consolidate v2
and toml packages in to configtest (#11081)
---
core/bridges/orm_test.go | 5 +-
core/chains/evm/chain_test.go | 5 +-
core/chains/evm/config/config_test.go | 2 +-
.../evm/forwarders/forwarder_manager_test.go | 2 +-
.../evm/headtracker/head_broadcaster_test.go | 2 +-
.../evm/headtracker/head_listener_test.go | 2 +-
.../chains/evm/headtracker/head_saver_test.go | 2 +-
.../evm/headtracker/head_tracker_test.go | 2 +-
core/chains/evm/headtracker/orm_test.go | 2 +-
core/chains/evm/log/helpers_test.go | 2 +-
core/chains/evm/log/orm_test.go | 2 +-
core/chains/evm/monitor/balance_test.go | 2 +-
core/chains/evm/txmgr/attempts_test.go | 2 +-
core/chains/evm/txmgr/broadcaster_test.go | 2 +-
core/chains/evm/txmgr/confirmer_test.go | 2 +-
core/chains/evm/txmgr/evm_tx_store_test.go | 2 +-
core/chains/evm/txmgr/nonce_syncer_test.go | 2 +-
core/chains/evm/txmgr/reaper_test.go | 2 +-
core/chains/evm/txmgr/resender_test.go | 2 +-
core/chains/evm/txmgr/strategies_test.go | 2 +-
core/chains/evm/txmgr/txmgr_test.go | 2 +-
core/chains/evm/types/models_test.go | 2 +-
core/cmd/app_test.go | 26 ++--
core/cmd/p2p_keys_commands_test.go | 3 +-
core/cmd/shell_local_test.go | 2 +-
core/cmd/shell_remote_test.go | 4 +-
core/cmd/shell_test.go | 2 +-
core/internal/cltest/cltest.go | 11 +-
core/internal/cltest/factories.go | 2 +-
core/internal/cltest/heavyweight/orm.go | 9 +-
core/internal/cltest/job_factories.go | 5 +-
core/internal/features/features_test.go | 10 +-
.../testutils/configtest/general_config.go | 122 +++++++++++++++++-
.../configtest/{v2/toml => }/toml.go | 2 +-
.../testutils/configtest/v2/general_config.go | 120 -----------------
core/internal/testutils/evmtest/v2/evmtest.go | 2 +-
core/services/blockhashstore/bhs_test.go | 2 +-
core/services/blockhashstore/delegate_test.go | 2 +-
.../relayer_chain_interoperators_test.go | 2 +-
core/services/cron/cron_test.go | 2 +-
core/services/directrequest/delegate_test.go | 2 +-
core/services/feeds/orm_test.go | 2 +-
core/services/feeds/service_test.go | 2 +-
.../fluxmonitorv2/flux_monitor_test.go | 2 +-
core/services/fluxmonitorv2/orm_test.go | 2 +-
core/services/functions/listener_test.go | 2 +-
core/services/job/job_orm_test.go | 2 +-
.../job/job_pipeline_orm_integration_test.go | 9 +-
core/services/job/orm_test.go | 5 +-
core/services/job/runner_integration_test.go | 39 +++---
core/services/job/spawner_test.go | 6 +-
core/services/keeper/orm_test.go | 5 +-
.../keeper/registry1_1_synchronizer_test.go | 2 +-
.../keeper/registry1_2_synchronizer_test.go | 2 +-
.../keeper/registry1_3_synchronizer_test.go | 2 +-
.../registry_synchronizer_helper_test.go | 2 +-
core/services/keeper/upkeep_executer_test.go | 5 +-
core/services/keystore/cosmos_test.go | 2 +-
core/services/keystore/csa_test.go | 2 +-
core/services/keystore/dkgencrypt_test.go | 2 +-
core/services/keystore/dkgsign_test.go | 2 +-
core/services/keystore/eth_test.go | 2 +-
core/services/keystore/master_test.go | 2 +-
core/services/keystore/ocr2_test.go | 2 +-
core/services/keystore/ocr_test.go | 2 +-
core/services/keystore/p2p_test.go | 2 +-
core/services/keystore/solana_test.go | 2 +-
core/services/keystore/starknet_test.go | 2 +-
core/services/keystore/vrf_test.go | 2 +-
core/services/ocr/contract_tracker_test.go | 2 +-
core/services/ocr/database_test.go | 7 +-
core/services/ocr/validate_test.go | 4 +-
core/services/ocr2/database_test.go | 7 +-
core/services/ocr2/delegate_test.go | 2 +-
.../ocr2/plugins/dkg/config/config_test.go | 2 +-
core/services/ocr2/validate/validate_test.go | 4 +-
core/services/ocrcommon/peer_wrapper_test.go | 4 +-
core/services/ocrcommon/peerstore_test.go | 6 +-
.../ocrcommon/transmitter_pipeline_test.go | 2 +-
core/services/ocrcommon/transmitter_test.go | 2 +-
core/services/pg/locked_db_test.go | 2 +-
core/services/pipeline/common_test.go | 4 +-
core/services/pipeline/orm_test.go | 11 +-
core/services/pipeline/runner_test.go | 2 +-
core/services/pipeline/task.bridge_test.go | 9 +-
core/services/pipeline/task.eth_call_test.go | 2 +-
core/services/pipeline/task.eth_tx_test.go | 2 +-
core/services/pipeline/task.http_test.go | 2 +-
.../promreporter/prom_reporter_test.go | 2 +-
core/services/relay/evm/evm_test.go | 5 +-
.../relay/evm/relayer_extender_test.go | 2 +-
.../relay/evm/request_round_tracker_test.go | 7 +-
core/services/vrf/delegate_test.go | 2 +-
.../services/vrf/proof/proof_response_test.go | 2 +-
.../vrf/v2/integration_v2_plus_test.go | 2 +-
core/services/vrf/v2/integration_v2_test.go | 2 +-
core/store/migrate/migrate_test.go | 2 +-
core/web/cors_test.go | 2 +-
core/web/cosmos_chains_controller_test.go | 2 +-
core/web/eth_keys_controller_test.go | 2 +-
core/web/evm_chains_controller_test.go | 2 +-
core/web/evm_forwarders_controller_test.go | 2 +-
core/web/evm_transfer_controller_test.go | 6 +-
.../external_initiators_controller_test.go | 14 +-
core/web/features_controller_test.go | 2 +-
core/web/gui_assets_test.go | 2 +-
core/web/jobs_controller_test.go | 4 +-
core/web/log_controller_test.go | 2 +-
core/web/loop_registry_test.go | 2 +-
core/web/pipeline_runs_controller_test.go | 2 +-
core/web/resolver/eth_key_test.go | 2 +-
core/web/resolver/features_test.go | 4 +-
core/web/solana_chains_controller_test.go | 2 +-
113 files changed, 327 insertions(+), 320 deletions(-)
rename core/internal/testutils/configtest/{v2/toml => }/toml.go (95%)
delete mode 100644 core/internal/testutils/configtest/v2/general_config.go
diff --git a/core/bridges/orm_test.go b/core/bridges/orm_test.go
index db04339335..b110b4f519 100644
--- a/core/bridges/orm_test.go
+++ b/core/bridges/orm_test.go
@@ -5,15 +5,16 @@ import (
"time"
"github.com/google/uuid"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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/pg"
diff --git a/core/chains/evm/chain_test.go b/core/chains/evm/chain_test.go
index 09395ff4c9..ba24598ef7 100644
--- a/core/chains/evm/chain_test.go
+++ b/core/chains/evm/chain_test.go
@@ -4,12 +4,13 @@ import (
"math/big"
"testing"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/mocks"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go
index 10984d45d1..d0f9e846e3 100644
--- a/core/chains/evm/config/config_test.go
+++ b/core/chains/evm/config/config_test.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/chains/evm/forwarders/forwarder_manager_test.go b/core/chains/evm/forwarders/forwarder_manager_test.go
index 0117c2f2c0..082d329e38 100644
--- a/core/chains/evm/forwarders/forwarder_manager_test.go
+++ b/core/chains/evm/forwarders/forwarder_manager_test.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_receiver"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go
index c478920e00..5c2423f328 100644
--- a/core/chains/evm/headtracker/head_broadcaster_test.go
+++ b/core/chains/evm/headtracker/head_broadcaster_test.go
@@ -17,7 +17,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/headtracker/head_listener_test.go b/core/chains/evm/headtracker/head_listener_test.go
index 63d2223383..dff97f5843 100644
--- a/core/chains/evm/headtracker/head_listener_test.go
+++ b/core/chains/evm/headtracker/head_listener_test.go
@@ -17,7 +17,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go
index 5ab43679f4..5ed85adc59 100644
--- a/core/chains/evm/headtracker/head_saver_test.go
+++ b/core/chains/evm/headtracker/head_saver_test.go
@@ -10,7 +10,7 @@ import (
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
)
diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go
index d30571f331..502aa4ae6d 100644
--- a/core/chains/evm/headtracker/head_tracker_test.go
+++ b/core/chains/evm/headtracker/head_tracker_test.go
@@ -29,7 +29,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/headtracker/orm_test.go b/core/chains/evm/headtracker/orm_test.go
index 5b106ac101..123478ff90 100644
--- a/core/chains/evm/headtracker/orm_test.go
+++ b/core/chains/evm/headtracker/orm_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/ethereum/go-ethereum/common"
diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go
index 58e81132b0..688757a3e9 100644
--- a/core/chains/evm/log/helpers_test.go
+++ b/core/chains/evm/log/helpers_test.go
@@ -31,7 +31,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/log/orm_test.go b/core/chains/evm/log/orm_test.go
index 365bb35433..48524896cf 100644
--- a/core/chains/evm/log/orm_test.go
+++ b/core/chains/evm/log/orm_test.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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/pg"
diff --git a/core/chains/evm/monitor/balance_test.go b/core/chains/evm/monitor/balance_test.go
index dbb2003b69..c80d64e7ef 100644
--- a/core/chains/evm/monitor/balance_test.go
+++ b/core/chains/evm/monitor/balance_test.go
@@ -18,7 +18,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/monitor"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
)
diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go
index 099143f0ce..863eae4723 100644
--- a/core/chains/evm/txmgr/attempts_test.go
+++ b/core/chains/evm/txmgr/attempts_test.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 6f9308548b..3901da59ee 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -37,7 +37,7 @@ import (
"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"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index 32246b06ce..8fbdb7696d 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -33,7 +33,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go
index e5b47c457b..ba02f118cf 100644
--- a/core/chains/evm/txmgr/evm_tx_store_test.go
+++ b/core/chains/evm/txmgr/evm_tx_store_test.go
@@ -15,7 +15,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/txmgr/nonce_syncer_test.go b/core/chains/evm/txmgr/nonce_syncer_test.go
index 13e5fd02e8..f6480b4c30 100644
--- a/core/chains/evm/txmgr/nonce_syncer_test.go
+++ b/core/chains/evm/txmgr/nonce_syncer_test.go
@@ -7,7 +7,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/txmgr/reaper_test.go b/core/chains/evm/txmgr/reaper_test.go
index 830ed1ac17..20cc27a675 100644
--- a/core/chains/evm/txmgr/reaper_test.go
+++ b/core/chains/evm/txmgr/reaper_test.go
@@ -12,7 +12,7 @@ import (
txmgrmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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/utils"
diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go
index d17156f452..cc94511e3b 100644
--- a/core/chains/evm/txmgr/resender_test.go
+++ b/core/chains/evm/txmgr/resender_test.go
@@ -17,7 +17,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/txmgr/strategies_test.go b/core/chains/evm/txmgr/strategies_test.go
index 9c5a1be37f..765b43e78f 100644
--- a/core/chains/evm/txmgr/strategies_test.go
+++ b/core/chains/evm/txmgr/strategies_test.go
@@ -11,7 +11,7 @@ import (
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
)
func Test_SendEveryStrategy(t *testing.T) {
diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go
index de8c6ff4ef..6cb43b2771 100644
--- a/core/chains/evm/txmgr/txmgr_test.go
+++ b/core/chains/evm/txmgr/txmgr_test.go
@@ -30,7 +30,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go
index 683a49692b..2f9dc7dd7c 100644
--- a/core/chains/evm/types/models_test.go
+++ b/core/chains/evm/types/models_test.go
@@ -22,7 +22,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/cmd/app_test.go b/core/cmd/app_test.go
index 78331bf706..bbb00bff3e 100644
--- a/core/cmd/app_test.go
+++ b/core/cmd/app_test.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/config/env"
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
- testtomlutils "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2/toml"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
@@ -88,7 +88,7 @@ func Test_initServerConfig(t *testing.T) {
name: "files only",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
},
wantCfg: withDefaults(t, testConfigFileContents, chainlink.Secrets{}),
},
@@ -104,7 +104,7 @@ func Test_initServerConfig(t *testing.T) {
name: "env overlay of file",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
envVar: testEnvContents,
},
wantCfg: withDefaults(t, chainlink.Config{
@@ -124,7 +124,7 @@ func Test_initServerConfig(t *testing.T) {
name: "failed to read secrets",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{"/doesnt-exist"},
},
wantErr: true,
@@ -133,8 +133,8 @@ func Test_initServerConfig(t *testing.T) {
name: "reading secrets",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
- secretsFiles: []string{testtomlutils.WriteTOMLFile(t, testSecretsFileContents, "test_secrets.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ secretsFiles: []string{configtest.WriteTOMLFile(t, testSecretsFileContents, "test_secrets.toml")},
},
wantCfg: withDefaults(t, testConfigFileContents, testSecretsRedactedContents),
},
@@ -142,7 +142,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../services/chainlink/testdata/mergingsecretsdata/secrets-database.toml",
"../services/chainlink/testdata/mergingsecretsdata/secrets-password.toml",
@@ -159,7 +159,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets with overrides: Database",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../testdata/mergingsecretsdata/secrets-database.toml",
"../testdata/mergingsecretsdata/secrets-database.toml",
@@ -171,7 +171,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets with overrides: Password",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../testdata/mergingsecretsdata/secrets-password.toml",
"../testdata/mergingsecretsdata/secrets-password.toml",
@@ -183,7 +183,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets with overrides: Pyroscope",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../testdata/mergingsecretsdata/secrets-pyroscope.toml",
"../testdata/mergingsecretsdata/secrets-pyroscope.toml",
@@ -195,7 +195,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets with overrides: Prometheus",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../testdata/mergingsecretsdata/secrets-prometheus.toml",
"../testdata/mergingsecretsdata/secrets-prometheus.toml",
@@ -207,7 +207,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets with overrides: Mercury",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../testdata/mergingsecretsdata/secrets-mercury-split-one.toml",
"../testdata/mergingsecretsdata/secrets-mercury-split-one.toml",
@@ -219,7 +219,7 @@ func Test_initServerConfig(t *testing.T) {
name: "reading multiple secrets with overrides: Threshold",
args: args{
opts: new(chainlink.GeneralConfigOpts),
- fileNames: []string{testtomlutils.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
+ fileNames: []string{configtest.WriteTOMLFile(t, testConfigFileContents, "test.toml")},
secretsFiles: []string{
"../testdata/mergingsecretsdata/secrets-threshold.toml",
"../testdata/mergingsecretsdata/secrets-threshold.toml",
diff --git a/core/cmd/p2p_keys_commands_test.go b/core/cmd/p2p_keys_commands_test.go
index cf107ba507..0407c92457 100644
--- a/core/cmd/p2p_keys_commands_test.go
+++ b/core/cmd/p2p_keys_commands_test.go
@@ -13,6 +13,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -24,7 +25,7 @@ func TestP2PKeyPresenter_RenderTable(t *testing.T) {
var (
id = "1"
- peerID = "12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X"
+ peerID = configtest.DefaultPeerID
pubKey = "somepubkey"
buffer = bytes.NewBufferString("")
r = cmd.RendererTable{Writer: buffer}
diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go
index be8d5c9405..d70b06f5a9 100644
--- a/core/cmd/shell_local_test.go
+++ b/core/cmd/shell_local_test.go
@@ -16,7 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
"github.com/smartcontractkit/chainlink/v2/core/internal/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go
index c1d15df9ec..7f998225f6 100644
--- a/core/cmd/shell_remote_test.go
+++ b/core/cmd/shell_remote_test.go
@@ -25,7 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
@@ -58,7 +58,7 @@ func startNewApplicationV2(t *testing.T, overrideFn func(c *chainlink.Config, s
fn(sopts)
}
- config := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.HTTPRequest.DefaultTimeout = models.MustNewDuration(30 * time.Millisecond)
f := false
c.EVM[0].Enabled = &f
diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go
index 74768a2192..9b87e8fb1d 100644
--- a/core/cmd/shell_test.go
+++ b/core/cmd/shell_test.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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/logger/audit"
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index a9ff8144b3..3fa0090177 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -61,7 +61,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest"
@@ -108,7 +107,7 @@ const (
// SessionSecret is the hardcoded secret solely used for test
SessionSecret = "clsession_test_secret"
// DefaultPeerID is the peer ID of the default p2p key
- DefaultPeerID = "12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X"
+ DefaultPeerID = configtest.DefaultPeerID
// DefaultOCRKeyBundleID is the ID of the default ocr key bundle
DefaultOCRKeyBundleID = "f5bf259689b26f1374efb3c9a9868796953a0f814bb2d39b968d0e61b58620a5"
// DefaultOCR2KeyBundleID is the ID of the fixture ocr2 key bundle
@@ -240,7 +239,7 @@ func NewWSServer(t *testing.T, chainID *big.Int, callback testutils.JSONRPCHandl
func NewApplicationEVMDisabled(t *testing.T) *TestApplication {
t.Helper()
- c := configtest2.NewGeneralConfig(t, nil)
+ c := configtest.NewGeneralConfig(t, nil)
return NewApplicationWithConfig(t, c)
}
@@ -250,7 +249,7 @@ func NewApplicationEVMDisabled(t *testing.T) *TestApplication {
func NewApplication(t testing.TB, flagsAndDeps ...interface{}) *TestApplication {
t.Helper()
- c := configtest2.NewGeneralConfig(t, nil)
+ c := configtest.NewGeneralConfig(t, nil)
return NewApplicationWithConfig(t, c, flagsAndDeps...)
}
@@ -260,7 +259,7 @@ func NewApplication(t testing.TB, flagsAndDeps ...interface{}) *TestApplication
func NewApplicationWithKey(t *testing.T, flagsAndDeps ...interface{}) *TestApplication {
t.Helper()
- config := configtest2.NewGeneralConfig(t, nil)
+ config := configtest.NewGeneralConfig(t, nil)
return NewApplicationWithConfigAndKey(t, config, flagsAndDeps...)
}
@@ -1617,7 +1616,7 @@ func AssertPipelineTaskRunsErrored(t testing.TB, runs []pipeline.TaskRun) {
}
func NewTestChainScopedConfig(t testing.TB) evmconfig.ChainScopedConfig {
- cfg := configtest2.NewGeneralConfig(t, nil)
+ cfg := configtest.NewGeneralConfig(t, nil)
return evmtest.NewChainScopedConfig(t, cfg)
}
diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go
index a1a5d9db6b..85ffc6b02b 100644
--- a/core/internal/cltest/factories.go
+++ b/core/internal/cltest/factories.go
@@ -34,7 +34,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keeper"
diff --git a/core/internal/cltest/heavyweight/orm.go b/core/internal/cltest/heavyweight/orm.go
index 841901c25a..2f9370f35a 100644
--- a/core/internal/cltest/heavyweight/orm.go
+++ b/core/internal/cltest/heavyweight/orm.go
@@ -14,13 +14,14 @@ import (
"runtime"
"testing"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/store/dialects"
@@ -50,7 +51,7 @@ func prepareFullTestDBV2(t testing.TB, name string, empty bool, loadFixtures boo
t.Fatal("could not load fixtures into an empty DB")
}
- gcfg := configtest2.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ gcfg := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Dialect = dialects.Postgres
if overrideFn != nil {
overrideFn(c, s)
@@ -68,7 +69,7 @@ func prepareFullTestDBV2(t testing.TB, name string, empty bool, loadFixtures boo
os.RemoveAll(gcfg.RootDir())
})
- gcfg = configtest2.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ gcfg = configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Dialect = dialects.Postgres
s.Database.URL = models.MustSecretURL(migrationTestDBURL)
if overrideFn != nil {
diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go
index 910ffe79e3..77fee125e2 100644
--- a/core/internal/cltest/job_factories.go
+++ b/core/internal/cltest/job_factories.go
@@ -5,11 +5,12 @@ import (
"testing"
"github.com/google/uuid"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go
index c5d16590d5..058c8325b9 100644
--- a/core/internal/features/features_test.go
+++ b/core/internal/features/features_test.go
@@ -56,7 +56,7 @@ import (
"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"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -83,7 +83,7 @@ func TestIntegration_ExternalInitiatorV2(t *testing.T) {
ethClient := cltest.NewEthMocksWithStartupAssertions(t)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
c.Database.Listener.FallbackPollInterval = models.MustNewDuration(10 * time.Millisecond)
})
@@ -362,7 +362,7 @@ func TestIntegration_DirectRequest(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
// Simulate a consumer contract calling to obtain ETH quotes in 3 different currencies
// in a single callback.
- config := configtest2.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Listener.FallbackPollInterval = models.MustNewDuration(100 * time.Millisecond)
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
})
@@ -467,7 +467,7 @@ func setupAppForEthTx(t *testing.T, operatorContracts OperatorContracts) (app *c
b := operatorContracts.sim
lggr, o := logger.TestLoggerObserved(t, zapcore.DebugLevel)
- cfg := configtest2.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Listener.FallbackPollInterval = models.MustNewDuration(100 * time.Millisecond)
})
app = cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, b, lggr)
@@ -1320,7 +1320,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) {
var initialDefaultGasPrice int64 = 5_000_000_000
maxGasPrice := assets.NewWeiI(10 * initialDefaultGasPrice)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].BalanceMonitor.Enabled = ptr(false)
c.EVM[0].GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](0)
c.EVM[0].GasEstimator.PriceDefault = assets.NewWeiI(initialDefaultGasPrice)
diff --git a/core/internal/testutils/configtest/general_config.go b/core/internal/testutils/configtest/general_config.go
index 1b652eeecd..93d388b2d3 100644
--- a/core/internal/testutils/configtest/general_config.go
+++ b/core/internal/testutils/configtest/general_config.go
@@ -1,6 +1,122 @@
package configtest
-// TODO move?
-const (
- DefaultPeerID = "12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X"
+import (
+ "net"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
+ evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
+ evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
+ "github.com/smartcontractkit/chainlink/v2/core/store/dialects"
+ "github.com/smartcontractkit/chainlink/v2/core/store/models"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
)
+
+const DefaultPeerID = "12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X"
+
+// NewTestGeneralConfig returns a new chainlink.GeneralConfig with default test overrides and one chain with evmclient.NullClientChainID.
+func NewTestGeneralConfig(t testing.TB) chainlink.GeneralConfig { return NewGeneralConfig(t, nil) }
+
+// NewGeneralConfig returns a new chainlink.GeneralConfig with overrides.
+// The default test overrides are applied before overrideFn, and include one chain with evmclient.NullClientChainID.
+func NewGeneralConfig(t testing.TB, overrideFn func(*chainlink.Config, *chainlink.Secrets)) chainlink.GeneralConfig {
+ tempDir := t.TempDir()
+ g, err := chainlink.GeneralConfigOpts{
+ OverrideFn: func(c *chainlink.Config, s *chainlink.Secrets) {
+ overrides(c, s)
+ c.RootDir = &tempDir
+ if fn := overrideFn; fn != nil {
+ fn(c, s)
+ }
+ },
+ }.New()
+ require.NoError(t, err)
+ return g
+}
+
+// overrides applies some test config settings and adds a default chain with evmclient.NullClientChainID.
+func overrides(c *chainlink.Config, s *chainlink.Secrets) {
+ s.Password.Keystore = models.NewSecret("dummy-to-pass-validation")
+
+ c.Insecure.OCRDevelopmentMode = ptr(true)
+ c.InsecureFastScrypt = ptr(true)
+ c.ShutdownGracePeriod = models.MustNewDuration(testutils.DefaultWaitTimeout)
+
+ c.Database.Dialect = dialects.TransactionWrappedPostgres
+ c.Database.Lock.Enabled = ptr(false)
+ c.Database.MaxIdleConns = ptr[int64](20)
+ c.Database.MaxOpenConns = ptr[int64](20)
+ c.Database.MigrateOnStartup = ptr(false)
+ c.Database.DefaultLockTimeout = models.MustNewDuration(1 * time.Minute)
+
+ c.JobPipeline.ReaperInterval = models.MustNewDuration(0)
+
+ c.P2P.V1.Enabled = ptr(false)
+ c.P2P.V2.Enabled = ptr(false)
+
+ c.WebServer.SessionTimeout = models.MustNewDuration(2 * time.Minute)
+ c.WebServer.BridgeResponseURL = models.MustParseURL("http://localhost:6688")
+ testIP := net.ParseIP("127.0.0.1")
+ c.WebServer.ListenIP = &testIP
+ c.WebServer.TLS.ListenIP = &testIP
+
+ chainID := utils.NewBigI(evmclient.NullClientChainID)
+ c.EVM = append(c.EVM, &evmcfg.EVMConfig{
+ ChainID: chainID,
+ Chain: evmcfg.Defaults(chainID),
+ Nodes: evmcfg.EVMNodes{
+ &evmcfg.Node{
+ Name: ptr("test"),
+ WSURL: &models.URL{},
+ HTTPURL: &models.URL{},
+ SendOnly: new(bool),
+ Order: ptr[int32](100),
+ },
+ },
+ })
+}
+
+// NewGeneralConfigSimulated returns a new chainlink.GeneralConfig with overrides, including the simulated EVM chain.
+// The default test overrides are applied before overrideFn.
+// The simulated chain (testutils.SimulatedChainID) replaces the null chain (evmclient.NullClientChainID).
+func NewGeneralConfigSimulated(t testing.TB, overrideFn func(*chainlink.Config, *chainlink.Secrets)) chainlink.GeneralConfig {
+ return NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ simulated(c, s)
+ if fn := overrideFn; fn != nil {
+ fn(c, s)
+ }
+ })
+}
+
+// simulated is a config override func that appends the simulated EVM chain (testutils.SimulatedChainID),
+// or replaces the null chain (client.NullClientChainID) if that is the only entry.
+func simulated(c *chainlink.Config, s *chainlink.Secrets) {
+ chainID := utils.NewBig(testutils.SimulatedChainID)
+ enabled := true
+ cfg := evmcfg.EVMConfig{
+ ChainID: chainID,
+ Chain: evmcfg.Defaults(chainID),
+ Enabled: &enabled,
+ Nodes: evmcfg.EVMNodes{&validTestNode},
+ }
+ if len(c.EVM) == 1 && c.EVM[0].ChainID.Cmp(utils.NewBigI(client.NullClientChainID)) == 0 {
+ c.EVM[0] = &cfg // replace null, if only entry
+ } else {
+ c.EVM = append(c.EVM, &cfg)
+ }
+}
+
+var validTestNode = evmcfg.Node{
+ Name: ptr("simulated-node"),
+ WSURL: models.MustParseURL("WSS://simulated-wss.com/ws"),
+ HTTPURL: models.MustParseURL("http://simulated.com"),
+ SendOnly: nil,
+ Order: ptr(int32(1)),
+}
+
+func ptr[T any](v T) *T { return &v }
diff --git a/core/internal/testutils/configtest/v2/toml/toml.go b/core/internal/testutils/configtest/toml.go
similarity index 95%
rename from core/internal/testutils/configtest/v2/toml/toml.go
rename to core/internal/testutils/configtest/toml.go
index 0cb89010f2..78db05f9c3 100644
--- a/core/internal/testutils/configtest/v2/toml/toml.go
+++ b/core/internal/testutils/configtest/toml.go
@@ -1,4 +1,4 @@
-package testtomlutils
+package configtest
import (
"os"
diff --git a/core/internal/testutils/configtest/v2/general_config.go b/core/internal/testutils/configtest/v2/general_config.go
deleted file mode 100644
index febbb367bd..0000000000
--- a/core/internal/testutils/configtest/v2/general_config.go
+++ /dev/null
@@ -1,120 +0,0 @@
-package v2
-
-import (
- "net"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
-
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
- evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
- "github.com/smartcontractkit/chainlink/v2/core/store/dialects"
- "github.com/smartcontractkit/chainlink/v2/core/store/models"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-)
-
-// NewTestGeneralConfig returns a new chainlink.GeneralConfig with default test overrides and one chain with evmclient.NullClientChainID.
-func NewTestGeneralConfig(t testing.TB) chainlink.GeneralConfig { return NewGeneralConfig(t, nil) }
-
-// NewGeneralConfig returns a new chainlink.GeneralConfig with overrides.
-// The default test overrides are applied before overrideFn, and include one chain with evmclient.NullClientChainID.
-func NewGeneralConfig(t testing.TB, overrideFn func(*chainlink.Config, *chainlink.Secrets)) chainlink.GeneralConfig {
- tempDir := t.TempDir()
- g, err := chainlink.GeneralConfigOpts{
- OverrideFn: func(c *chainlink.Config, s *chainlink.Secrets) {
- overrides(c, s)
- c.RootDir = &tempDir
- if fn := overrideFn; fn != nil {
- fn(c, s)
- }
- },
- }.New()
- require.NoError(t, err)
- return g
-}
-
-// overrides applies some test config settings and adds a default chain with evmclient.NullClientChainID.
-func overrides(c *chainlink.Config, s *chainlink.Secrets) {
- s.Password.Keystore = models.NewSecret("dummy-to-pass-validation")
-
- c.Insecure.OCRDevelopmentMode = ptr(true)
- c.InsecureFastScrypt = ptr(true)
- c.ShutdownGracePeriod = models.MustNewDuration(testutils.DefaultWaitTimeout)
-
- c.Database.Dialect = dialects.TransactionWrappedPostgres
- c.Database.Lock.Enabled = ptr(false)
- c.Database.MaxIdleConns = ptr[int64](20)
- c.Database.MaxOpenConns = ptr[int64](20)
- c.Database.MigrateOnStartup = ptr(false)
- c.Database.DefaultLockTimeout = models.MustNewDuration(1 * time.Minute)
-
- c.JobPipeline.ReaperInterval = models.MustNewDuration(0)
-
- c.P2P.V1.Enabled = ptr(false)
- c.P2P.V2.Enabled = ptr(false)
-
- c.WebServer.SessionTimeout = models.MustNewDuration(2 * time.Minute)
- c.WebServer.BridgeResponseURL = models.MustParseURL("http://localhost:6688")
- testIP := net.ParseIP("127.0.0.1")
- c.WebServer.ListenIP = &testIP
- c.WebServer.TLS.ListenIP = &testIP
-
- chainID := utils.NewBigI(evmclient.NullClientChainID)
- c.EVM = append(c.EVM, &evmcfg.EVMConfig{
- ChainID: chainID,
- Chain: evmcfg.Defaults(chainID),
- Nodes: evmcfg.EVMNodes{
- &evmcfg.Node{
- Name: ptr("test"),
- WSURL: &models.URL{},
- HTTPURL: &models.URL{},
- SendOnly: new(bool),
- Order: ptr[int32](100),
- },
- },
- })
-}
-
-// NewGeneralConfigSimulated returns a new chainlink.GeneralConfig with overrides, including the simulated EVM chain.
-// The default test overrides are applied before overrideFn.
-// The simulated chain (testutils.SimulatedChainID) replaces the null chain (evmclient.NullClientChainID).
-func NewGeneralConfigSimulated(t testing.TB, overrideFn func(*chainlink.Config, *chainlink.Secrets)) chainlink.GeneralConfig {
- return NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- simulated(c, s)
- if fn := overrideFn; fn != nil {
- fn(c, s)
- }
- })
-}
-
-// simulated is a config override func that appends the simulated EVM chain (testutils.SimulatedChainID),
-// or replaces the null chain (client.NullClientChainID) if that is the only entry.
-func simulated(c *chainlink.Config, s *chainlink.Secrets) {
- chainID := utils.NewBig(testutils.SimulatedChainID)
- enabled := true
- cfg := evmcfg.EVMConfig{
- ChainID: chainID,
- Chain: evmcfg.Defaults(chainID),
- Enabled: &enabled,
- Nodes: evmcfg.EVMNodes{&validTestNode},
- }
- if len(c.EVM) == 1 && c.EVM[0].ChainID.Cmp(utils.NewBigI(client.NullClientChainID)) == 0 {
- c.EVM[0] = &cfg // replace null, if only entry
- } else {
- c.EVM = append(c.EVM, &cfg)
- }
-}
-
-var validTestNode = evmcfg.Node{
- Name: ptr("simulated-node"),
- WSURL: models.MustParseURL("WSS://simulated-wss.com/ws"),
- HTTPURL: models.MustParseURL("http://simulated.com"),
- SendOnly: nil,
- Order: ptr(int32(1)),
-}
-
-func ptr[T any](v T) *T { return &v }
diff --git a/core/internal/testutils/evmtest/v2/evmtest.go b/core/internal/testutils/evmtest/v2/evmtest.go
index 400690480d..fa22588c8f 100644
--- a/core/internal/testutils/evmtest/v2/evmtest.go
+++ b/core/internal/testutils/evmtest/v2/evmtest.go
@@ -5,7 +5,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go
index ed32b3ab49..5c501a62ac 100644
--- a/core/services/blockhashstore/bhs_test.go
+++ b/core/services/blockhashstore/bhs_test.go
@@ -12,7 +12,7 @@ import (
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go
index 582492105e..089e9544af 100644
--- a/core/services/blockhashstore/delegate_test.go
+++ b/core/services/blockhashstore/delegate_test.go
@@ -15,7 +15,7 @@ import (
mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go
index 5b17e2e423..b7291e7dc7 100644
--- a/core/services/chainlink/relayer_chain_interoperators_test.go
+++ b/core/services/chainlink/relayer_chain_interoperators_test.go
@@ -29,7 +29,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/plugins"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/services/cron/cron_test.go b/core/services/cron/cron_test.go
index 174f80586a..19a51a3065 100644
--- a/core/services/cron/cron_test.go
+++ b/core/services/cron/cron_test.go
@@ -11,7 +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"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go
index ffd78443cc..e58dbaeb50 100644
--- a/core/services/directrequest/delegate_test.go
+++ b/core/services/directrequest/delegate_test.go
@@ -20,7 +20,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go
index fab9d39a26..746956bbfc 100644
--- a/core/services/feeds/orm_test.go
+++ b/core/services/feeds/orm_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go
index 744c5d1470..c94a75b3dd 100644
--- a/core/services/feeds/service_test.go
+++ b/core/services/feeds/service_test.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go
index 83ffee8ac5..0d1eb085a8 100644
--- a/core/services/fluxmonitorv2/flux_monitor_test.go
+++ b/core/services/fluxmonitorv2/flux_monitor_test.go
@@ -32,7 +32,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
"github.com/smartcontractkit/chainlink/v2/core/internal/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
corenull "github.com/smartcontractkit/chainlink/v2/core/null"
diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go
index 3bebc150c8..0bb0803261 100644
--- a/core/services/fluxmonitorv2/orm_test.go
+++ b/core/services/fluxmonitorv2/orm_test.go
@@ -16,7 +16,7 @@ import (
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go
index 6f0badd6e1..007a2a9168 100644
--- a/core/services/functions/listener_test.go
+++ b/core/services/functions/listener_test.go
@@ -21,7 +21,7 @@ import (
log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index 20f569a893..74416e68dc 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -23,7 +23,7 @@ import (
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go
index a5d3ee984d..1158fc4626 100644
--- a/core/services/job/job_pipeline_orm_integration_test.go
+++ b/core/services/job/job_pipeline_orm_integration_test.go
@@ -4,14 +4,15 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -44,7 +45,7 @@ func TestPipelineORM_Integration(t *testing.T) {
answer2 [type=bridge name=election_winner index=1];
`
- config := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.HTTPRequest.DefaultTimeout = models.MustNewDuration(30 * time.Millisecond)
})
db := pgtest.NewSqlxDB(t)
@@ -147,7 +148,7 @@ func TestPipelineORM_Integration(t *testing.T) {
t.Run("creates runs", func(t *testing.T) {
lggr := logger.TestLogger(t)
- cfg := configtest2.NewTestGeneralConfig(t)
+ cfg := configtest.NewTestGeneralConfig(t)
clearJobsDb(t, db)
orm := pipeline.NewORM(db, logger.TestLogger(t), cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
btORM := bridges.NewORM(db, logger.TestLogger(t), cfg.Database())
diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go
index 15a2432f9e..a6986d7fb3 100644
--- a/core/services/job/orm_test.go
+++ b/core/services/job/orm_test.go
@@ -3,13 +3,14 @@ package job_test
import (
"testing"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go
index 05782f95ce..c0fff1e560 100644
--- a/core/services/job/runner_integration_test.go
+++ b/core/services/job/runner_integration_test.go
@@ -13,39 +13,38 @@ import (
"testing"
"time"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
- "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate"
- evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
- "github.com/smartcontractkit/chainlink/v2/core/services/srvctest"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
+ "github.com/google/uuid"
+ "github.com/pelletier/go-toml"
+ "github.com/pkg/errors"
+ "github.com/shopspring/decimal"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+ "gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"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/evmtest"
clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest"
"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/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/services/srvctest"
"github.com/smartcontractkit/chainlink/v2/core/services/telemetry"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/web"
-
- "github.com/google/uuid"
- "github.com/pelletier/go-toml"
- "github.com/pkg/errors"
- "github.com/shopspring/decimal"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
- "gopkg.in/guregu/null.v4"
)
var monitoringEndpoint = telemetry.MonitoringEndpointGenerator(&telemetry.NoopAgent{})
@@ -58,7 +57,7 @@ func TestRunner(t *testing.T) {
_, transmitterAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey))
- config := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.P2P.V1.Enabled = ptr(true)
c.P2P.V1.DefaultBootstrapPeers = &[]string{
"/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju",
@@ -759,7 +758,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) {
ethClient := cltest.NewEthMocksWithStartupAssertions(t)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
t := true
c.JobPipeline.ExternalInitiatorsEnabled = &t
c.Database.Listener.FallbackPollInterval = models.MustNewDuration(10 * time.Millisecond)
@@ -941,7 +940,7 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) {
ethClient := cltest.NewEthMocksWithStartupAssertions(t)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
t := true
c.JobPipeline.ExternalInitiatorsEnabled = &t
c.Database.Listener.FallbackPollInterval = models.MustNewDuration(10 * time.Millisecond)
diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go
index 4e28dcdf06..be4a480a6c 100644
--- a/core/services/job/spawner_test.go
+++ b/core/services/job/spawner_test.go
@@ -18,7 +18,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -73,7 +73,7 @@ func (g *relayGetter) Get(id relay.ID) (loop.Relayer, error) {
func TestSpawner_CreateJobDeleteJob(t *testing.T) {
t.Parallel()
- config := configtest2.NewTestGeneralConfig(t)
+ config := configtest.NewTestGeneralConfig(t)
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db, config.Database())
ethKeyStore := keyStore.Eth()
@@ -264,7 +264,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) {
})
t.Run("Unregisters filters on 'DeleteJob()'", func(t *testing.T) {
- config = configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Feature.LogPoller = func(b bool) *bool { return &b }(true)
})
lp := &mocklp.LogPoller{}
diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go
index 972437eda1..d990effa10 100644
--- a/core/services/keeper/orm_test.go
+++ b/core/services/keeper/orm_test.go
@@ -9,13 +9,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/onsi/gomega"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/keeper/registry1_1_synchronizer_test.go b/core/services/keeper/registry1_1_synchronizer_test.go
index 8444aa50dd..031b7a5907 100644
--- a/core/services/keeper/registry1_1_synchronizer_test.go
+++ b/core/services/keeper/registry1_1_synchronizer_test.go
@@ -18,7 +18,7 @@ import (
registry1_1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/keeper/registry1_2_synchronizer_test.go b/core/services/keeper/registry1_2_synchronizer_test.go
index f593a638f9..e7d8d6a48a 100644
--- a/core/services/keeper/registry1_2_synchronizer_test.go
+++ b/core/services/keeper/registry1_2_synchronizer_test.go
@@ -18,7 +18,7 @@ import (
registry1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/keeper/registry1_3_synchronizer_test.go b/core/services/keeper/registry1_3_synchronizer_test.go
index 53b5cbf983..a0522fd717 100644
--- a/core/services/keeper/registry1_3_synchronizer_test.go
+++ b/core/services/keeper/registry1_3_synchronizer_test.go
@@ -14,7 +14,7 @@ import (
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
registry1_3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/utils"
logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go
index 99fb54eba4..63dc634353 100644
--- a/core/services/keeper/registry_synchronizer_helper_test.go
+++ b/core/services/keeper/registry_synchronizer_helper_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go
index 39f85aedcd..7f9698435f 100644
--- a/core/services/keeper/upkeep_executer_test.go
+++ b/core/services/keeper/upkeep_executer_test.go
@@ -9,11 +9,12 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/onsi/gomega"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
@@ -24,7 +25,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/keystore/cosmos_test.go b/core/services/keystore/cosmos_test.go
index ada7c25a2c..3c33f16282 100644
--- a/core/services/keystore/cosmos_test.go
+++ b/core/services/keystore/cosmos_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
diff --git a/core/services/keystore/csa_test.go b/core/services/keystore/csa_test.go
index ef2dd1f689..b6dfb00959 100644
--- a/core/services/keystore/csa_test.go
+++ b/core/services/keystore/csa_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey"
diff --git a/core/services/keystore/dkgencrypt_test.go b/core/services/keystore/dkgencrypt_test.go
index 1edbc2120f..36f48f9c2b 100644
--- a/core/services/keystore/dkgencrypt_test.go
+++ b/core/services/keystore/dkgencrypt_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey"
diff --git a/core/services/keystore/dkgsign_test.go b/core/services/keystore/dkgsign_test.go
index d699800b50..5ea23a516b 100644
--- a/core/services/keystore/dkgsign_test.go
+++ b/core/services/keystore/dkgsign_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey"
diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go
index 0fec509a32..4165350300 100644
--- a/core/services/keystore/eth_test.go
+++ b/core/services/keystore/eth_test.go
@@ -16,7 +16,7 @@ import (
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/services/keystore/master_test.go b/core/services/keystore/master_test.go
index 7a280cc675..73f636c662 100644
--- a/core/services/keystore/master_test.go
+++ b/core/services/keystore/master_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
)
diff --git a/core/services/keystore/ocr2_test.go b/core/services/keystore/ocr2_test.go
index b4feb33b5f..9223538a76 100644
--- a/core/services/keystore/ocr2_test.go
+++ b/core/services/keystore/ocr2_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
diff --git a/core/services/keystore/ocr_test.go b/core/services/keystore/ocr_test.go
index 5698352ec3..200d62415e 100644
--- a/core/services/keystore/ocr_test.go
+++ b/core/services/keystore/ocr_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey"
diff --git a/core/services/keystore/p2p_test.go b/core/services/keystore/p2p_test.go
index 63654786fd..89cab3e162 100644
--- a/core/services/keystore/p2p_test.go
+++ b/core/services/keystore/p2p_test.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
diff --git a/core/services/keystore/solana_test.go b/core/services/keystore/solana_test.go
index 8d7d90a9da..6e895a5611 100644
--- a/core/services/keystore/solana_test.go
+++ b/core/services/keystore/solana_test.go
@@ -8,7 +8,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey"
diff --git a/core/services/keystore/starknet_test.go b/core/services/keystore/starknet_test.go
index 571a809a55..df9516f871 100644
--- a/core/services/keystore/starknet_test.go
+++ b/core/services/keystore/starknet_test.go
@@ -13,7 +13,7 @@ import (
"github.com/smartcontractkit/caigo"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey"
diff --git a/core/services/keystore/vrf_test.go b/core/services/keystore/vrf_test.go
index f0c6949bbe..7a2e91ffec 100644
--- a/core/services/keystore/vrf_test.go
+++ b/core/services/keystore/vrf_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey"
diff --git a/core/services/ocr/contract_tracker_test.go b/core/services/ocr/contract_tracker_test.go
index d8fe45e8b3..5684219cf1 100644
--- a/core/services/ocr/contract_tracker_test.go
+++ b/core/services/ocr/contract_tracker_test.go
@@ -23,7 +23,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/offchain_aggregator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr/database_test.go b/core/services/ocr/database_test.go
index 8b345df859..6a72c27aa6 100644
--- a/core/services/ocr/database_test.go
+++ b/core/services/ocr/database_test.go
@@ -7,14 +7,15 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
+
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/services/ocr/validate_test.go b/core/services/ocr/validate_test.go
index 3efd2d8381..0164fd82c5 100644
--- a/core/services/ocr/validate_test.go
+++ b/core/services/ocr/validate_test.go
@@ -12,7 +12,7 @@ import (
"gopkg.in/guregu/null.v4"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -399,7 +399,7 @@ answer1 [type=median index=0];
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
- c := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ c := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = null.BoolFrom(false).Ptr()
if tc.overrides != nil {
tc.overrides(c, s)
diff --git a/core/services/ocr2/database_test.go b/core/services/ocr2/database_test.go
index 18c0ec8519..aabb2b33a7 100644
--- a/core/services/ocr2/database_test.go
+++ b/core/services/ocr2/database_test.go
@@ -7,14 +7,15 @@ import (
medianconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median/config"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go
index 3973774c56..daffac3f96 100644
--- a/core/services/ocr2/delegate_test.go
+++ b/core/services/ocr2/delegate_test.go
@@ -13,7 +13,7 @@ import (
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/dkg/config/config_test.go b/core/services/ocr2/plugins/dkg/config/config_test.go
index b49a5277d9..fe796a9ad6 100644
--- a/core/services/ocr2/plugins/dkg/config/config_test.go
+++ b/core/services/ocr2/plugins/dkg/config/config_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config"
)
diff --git a/core/services/ocr2/validate/validate_test.go b/core/services/ocr2/validate/validate_test.go
index 98a13ebf8a..4685ed745d 100644
--- a/core/services/ocr2/validate/validate_test.go
+++ b/core/services/ocr2/validate/validate_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
medianconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median/config"
@@ -584,7 +584,7 @@ KeyID = "6f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
- c := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ c := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = testutils.Ptr(false) // tests run with OCRDevelopmentMode by default.
if tc.overrides != nil {
tc.overrides(c, s)
diff --git a/core/services/ocrcommon/peer_wrapper_test.go b/core/services/ocrcommon/peer_wrapper_test.go
index 45edc64e9d..209bc6b969 100644
--- a/core/services/ocrcommon/peer_wrapper_test.go
+++ b/core/services/ocrcommon/peer_wrapper_test.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
@@ -25,7 +25,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- peerID, err := p2ppeer.Decode("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X")
+ peerID, err := p2ppeer.Decode(configtest.DefaultPeerID)
require.NoError(t, err)
t.Run("with no p2p keys returns error", func(t *testing.T) {
diff --git a/core/services/ocrcommon/peerstore_test.go b/core/services/ocrcommon/peerstore_test.go
index ba55e0767a..6e69215356 100644
--- a/core/services/ocrcommon/peerstore_test.go
+++ b/core/services/ocrcommon/peerstore_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/require"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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/keystore/keys/p2pkey"
@@ -21,7 +21,7 @@ import (
func Test_Peerstore_Start(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- peerID, err := p2ppeer.Decode("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X")
+ peerID, err := p2ppeer.Decode(configtest.DefaultPeerID)
require.NoError(t, err)
nonExistentP2PPeerID, err := p2ppeer.Decode("12D3KooWAdCzaesXyezatDzgGvCngqsBqoUqnV9PnVc46jsVt2i9")
@@ -72,7 +72,7 @@ func Test_Peerstore_Start(t *testing.T) {
func Test_Peerstore_WriteToDB(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- peerID, err := p2ppeer.Decode("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X")
+ peerID, err := p2ppeer.Decode(configtest.DefaultPeerID)
require.NoError(t, err)
cfg := configtest.NewTestGeneralConfig(t)
diff --git a/core/services/ocrcommon/transmitter_pipeline_test.go b/core/services/ocrcommon/transmitter_pipeline_test.go
index 8a1f2f2a92..e0114d0aa0 100644
--- a/core/services/ocrcommon/transmitter_pipeline_test.go
+++ b/core/services/ocrcommon/transmitter_pipeline_test.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
diff --git a/core/services/ocrcommon/transmitter_test.go b/core/services/ocrcommon/transmitter_test.go
index ac5d120eb0..d954da869b 100644
--- a/core/services/ocrcommon/transmitter_test.go
+++ b/core/services/ocrcommon/transmitter_test.go
@@ -13,7 +13,7 @@ import (
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
)
diff --git a/core/services/pg/locked_db_test.go b/core/services/pg/locked_db_test.go
index aaf7ebf32c..a2aebcd57f 100644
--- a/core/services/pg/locked_db_test.go
+++ b/core/services/pg/locked_db_test.go
@@ -6,7 +6,7 @@ import (
"time"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/pipeline/common_test.go b/core/services/pipeline/common_test.go
index 37cc60f27e..7da80d3af4 100644
--- a/core/services/pipeline/common_test.go
+++ b/core/services/pipeline/common_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
@@ -323,7 +323,7 @@ func TestTaskRunResult_IsPending(t *testing.T) {
func TestSelectGasLimit(t *testing.T) {
t.Parallel()
- gcfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].GasEstimator.LimitDefault = ptr(uint32(999))
c.EVM[0].GasEstimator.LimitJobType = toml.GasLimitJobType{
DR: ptr(uint32(100)),
diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go
index 4c03ce16ef..a487c231fb 100644
--- a/core/services/pipeline/orm_test.go
+++ b/core/services/pipeline/orm_test.go
@@ -5,17 +5,18 @@ import (
"time"
"github.com/google/uuid"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/sqlx"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"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"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -514,7 +515,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) {
// The test configures single Keeper job with two running tasks.
// GetUnfinishedRuns() expects to catch both running tasks.
- config := configtest2.NewTestGeneralConfig(t)
+ config := configtest.NewTestGeneralConfig(t)
lggr := logger.TestLogger(t)
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db, config.Database())
@@ -616,7 +617,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) {
// The test configures single DR job with two task runs: one is running and one is suspended.
// GetUnfinishedRuns() expects to catch the one that is running.
- config := configtest2.NewTestGeneralConfig(t)
+ config := configtest.NewTestGeneralConfig(t)
lggr := logger.TestLogger(t)
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db, config.Database())
@@ -709,7 +710,7 @@ func Test_Prune(t *testing.T) {
n := uint64(2)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.MaxSuccessfulRuns = &n
})
lggr, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel)
diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go
index 22b70829ba..3abcdbe0ab 100644
--- a/core/services/pipeline/runner_test.go
+++ b/core/services/pipeline/runner_test.go
@@ -26,7 +26,7 @@ import (
bridgesMocks "github.com/smartcontractkit/chainlink/v2/core/bridges/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go
index 6f542d485e..03a804c9c1 100644
--- a/core/services/pipeline/task.bridge_test.go
+++ b/core/services/pipeline/task.bridge_test.go
@@ -24,8 +24,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"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -208,7 +207,7 @@ func TestBridgeTask_HandlesIntermittentFailure(t *testing.T) {
t.Parallel()
db := pgtest.NewSqlxDB(t)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {})
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {})
s1 := httptest.NewServer(fakeIntermittentlyFailingPriceResponder(t, utils.MustUnmarshalToMap(btcUSDPairing), decimal.NewFromInt(9700), "", nil))
defer s1.Close()
@@ -270,7 +269,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- cfg := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.WebServer.BridgeCacheTTL = models.MustNewDuration(30 * time.Second)
})
queryer := pg.NewQ(db, logger.TestLogger(t), cfg.Database())
@@ -336,7 +335,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) {
require.NoError(t, result2.Error)
require.Equal(t, string(big.NewInt(9700).Bytes()), result2.Value)
- cfg2 := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg2 := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.WebServer.BridgeCacheTTL = models.MustNewDuration(0 * time.Second)
})
task.HelperSetDependencies(cfg2.JobPipeline(), cfg2.WebServer(), orm, specID, uuid.UUID{}, c)
diff --git a/core/services/pipeline/task.eth_call_test.go b/core/services/pipeline/task.eth_call_test.go
index 77a10681fb..8fe8bec16c 100644
--- a/core/services/pipeline/task.eth_call_test.go
+++ b/core/services/pipeline/task.eth_call_test.go
@@ -17,7 +17,7 @@ import (
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go
index af09d79385..e5f50bc29e 100644
--- a/core/services/pipeline/task.eth_tx_test.go
+++ b/core/services/pipeline/task.eth_tx_test.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/pipeline/task.http_test.go b/core/services/pipeline/task.http_test.go
index eee3a9aa78..c0dd93df43 100644
--- a/core/services/pipeline/task.http_test.go
+++ b/core/services/pipeline/task.http_test.go
@@ -20,7 +20,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go
index f57cf8f45a..1f15d94418 100644
--- a/core/services/promreporter/prom_reporter_test.go
+++ b/core/services/promreporter/prom_reporter_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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/promreporter"
diff --git a/core/services/relay/evm/evm_test.go b/core/services/relay/evm/evm_test.go
index df7cd8eb81..4e9c44a7b9 100644
--- a/core/services/relay/evm/evm_test.go
+++ b/core/services/relay/evm/evm_test.go
@@ -3,10 +3,11 @@ package evm_test
import (
"testing"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/sqlx"
+
+ "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"
)
diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go
index 361a7468f3..3f4a3749ac 100644
--- a/core/services/relay/evm/relayer_extender_test.go
+++ b/core/services/relay/evm/relayer_extender_test.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/services/relay/evm/request_round_tracker_test.go b/core/services/relay/evm/request_round_tracker_test.go
index b9f38d54ba..cb2ee2a8d7 100644
--- a/core/services/relay/evm/request_round_tracker_test.go
+++ b/core/services/relay/evm/request_round_tracker_test.go
@@ -7,12 +7,13 @@ import (
gethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
@@ -21,7 +22,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go
index 8c522520fa..38b361716b 100644
--- a/core/services/vrf/delegate_test.go
+++ b/core/services/vrf/delegate_test.go
@@ -21,7 +21,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/vrf/proof/proof_response_test.go b/core/services/vrf/proof/proof_response_test.go
index 191c18b60d..24df77d4b3 100644
--- a/core/services/vrf/proof/proof_response_test.go
+++ b/core/services/vrf/proof/proof_response_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_verifier_wrapper"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
proof2 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go
index 33eb9f7483..9adf47f256 100644
--- a/core/services/vrf/v2/integration_v2_plus_test.go
+++ b/core/services/vrf/v2/integration_v2_plus_test.go
@@ -40,7 +40,7 @@ import (
"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"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey"
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index 6dad317307..093adc8eaa 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -57,7 +57,7 @@ import (
"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"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go
index 7a1e38fb03..fe218589d2 100644
--- a/core/store/migrate/migrate_test.go
+++ b/core/store/migrate/migrate_test.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/config/env"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
diff --git a/core/web/cors_test.go b/core/web/cors_test.go
index cfd82dd8b7..fcd5d9b387 100644
--- a/core/web/cors_test.go
+++ b/core/web/cors_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
)
diff --git a/core/web/cosmos_chains_controller_test.go b/core/web/cosmos_chains_controller_test.go
index f3f5909940..475ef41352 100644
--- a/core/web/cosmos_chains_controller_test.go
+++ b/core/web/cosmos_chains_controller_test.go
@@ -16,7 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/web"
diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go
index 9864172173..e3a39d541a 100644
--- a/core/web/eth_keys_controller_test.go
+++ b/core/web/eth_keys_controller_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/web/evm_chains_controller_test.go b/core/web/evm_chains_controller_test.go
index 4ebf06f2b6..3d5a4e3eed 100644
--- a/core/web/evm_chains_controller_test.go
+++ b/core/web/evm_chains_controller_test.go
@@ -14,7 +14,7 @@ import (
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/web/evm_forwarders_controller_test.go b/core/web/evm_forwarders_controller_test.go
index 46820b4233..31e49f20ec 100644
--- a/core/web/evm_forwarders_controller_test.go
+++ b/core/web/evm_forwarders_controller_test.go
@@ -13,7 +13,7 @@ import (
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/web"
diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go
index 0f3cdc8bb6..14259637b4 100644
--- a/core/web/evm_transfer_controller_test.go
+++ b/core/web/evm_transfer_controller_test.go
@@ -15,7 +15,7 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
@@ -125,7 +125,7 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin
ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil)
ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil)
- config := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].BalanceMonitor.Enabled = ptr(false)
})
@@ -285,7 +285,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) {
ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil)
ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil).Maybe()
- config := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
c.EVM[0].GasEstimator.Mode = ptr("FixedPrice")
c.EVM[0].ChainID = (*utils.Big)(testutils.FixtureChainID)
diff --git a/core/web/external_initiators_controller_test.go b/core/web/external_initiators_controller_test.go
index 2229b40b7e..6a1b715b72 100644
--- a/core/web/external_initiators_controller_test.go
+++ b/core/web/external_initiators_controller_test.go
@@ -10,7 +10,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"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "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"
@@ -69,7 +69,7 @@ func TestExternalInitiatorsController_Index(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationWithConfig(t,
- configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
}))
require.NoError(t, app.Start(testutils.Context(t)))
@@ -135,7 +135,7 @@ func TestExternalInitiatorsController_Create_success(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationWithConfig(t,
- configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
}))
require.NoError(t, app.Start(testutils.Context(t)))
@@ -163,7 +163,7 @@ func TestExternalInitiatorsController_Create_without_URL(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationWithConfig(t,
- configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
}))
require.NoError(t, app.Start(testutils.Context(t)))
@@ -191,7 +191,7 @@ func TestExternalInitiatorsController_Create_invalid(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationWithConfig(t,
- configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
}))
require.NoError(t, app.Start(testutils.Context(t)))
@@ -209,7 +209,7 @@ func TestExternalInitiatorsController_Delete(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationWithConfig(t,
- configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
}))
require.NoError(t, app.Start(testutils.Context(t)))
@@ -231,7 +231,7 @@ func TestExternalInitiatorsController_DeleteNotFound(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationWithConfig(t,
- configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.JobPipeline.ExternalInitiatorsEnabled = ptr(true)
}))
require.NoError(t, app.Start(testutils.Context(t)))
diff --git a/core/web/features_controller_test.go b/core/web/features_controller_test.go
index 8ef2e08d39..727d7db547 100644
--- a/core/web/features_controller_test.go
+++ b/core/web/features_controller_test.go
@@ -6,7 +6,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/web"
"github.com/smartcontractkit/chainlink/v2/core/web/presenters"
diff --git a/core/web/gui_assets_test.go b/core/web/gui_assets_test.go
index 784b0958f5..137b123198 100644
--- a/core/web/gui_assets_test.go
+++ b/core/web/gui_assets_test.go
@@ -8,7 +8,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/web"
diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go
index 345662909a..fc2e8d7a30 100644
--- a/core/web/jobs_controller_test.go
+++ b/core/web/jobs_controller_test.go
@@ -25,7 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/directrequest"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -44,7 +44,7 @@ func TestJobsController_Create_ValidationFailure_OffchainReportingSpec(t *testin
contractAddress = cltest.NewEIP55Address()
)
- peerID, err := p2ppeer.Decode("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X")
+ peerID, err := p2ppeer.Decode(configtest.DefaultPeerID)
require.NoError(t, err)
randomBytes := testutils.Random32Byte()
diff --git a/core/web/log_controller_test.go b/core/web/log_controller_test.go
index e4cd1768ce..dbb95361b9 100644
--- a/core/web/log_controller_test.go
+++ b/core/web/log_controller_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/web"
"github.com/smartcontractkit/chainlink/v2/core/web/presenters"
diff --git a/core/web/loop_registry_test.go b/core/web/loop_registry_test.go
index 59a4d0df68..ea76672564 100644
--- a/core/web/loop_registry_test.go
+++ b/core/web/loop_registry_test.go
@@ -17,7 +17,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
)
diff --git a/core/web/pipeline_runs_controller_test.go b/core/web/pipeline_runs_controller_test.go
index 5b17fcb007..c44ee9ae8d 100644
--- a/core/web/pipeline_runs_controller_test.go
+++ b/core/web/pipeline_runs_controller_test.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
diff --git a/core/web/resolver/eth_key_test.go b/core/web/resolver/eth_key_test.go
index 26e061b164..6cac2f4ac4 100644
--- a/core/web/resolver/eth_key_test.go
+++ b/core/web/resolver/eth_key_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
mocks2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
diff --git a/core/web/resolver/features_test.go b/core/web/resolver/features_test.go
index 1d3f5b8dda..f14f71abc9 100644
--- a/core/web/resolver/features_test.go
+++ b/core/web/resolver/features_test.go
@@ -3,7 +3,7 @@ package resolver
import (
"testing"
- configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
)
@@ -24,7 +24,7 @@ func Test_ToFeatures(t *testing.T) {
name: "success",
authenticated: true,
before: func(f *gqlTestFramework) {
- f.App.On("GetConfig").Return(configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ f.App.On("GetConfig").Return(configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
t, f := true, false
c.Feature.UICSAKeys = &f
c.Feature.FeedsManager = &t
diff --git a/core/web/solana_chains_controller_test.go b/core/web/solana_chains_controller_test.go
index 5d6dc7424a..724d5cd2c3 100644
--- a/core/web/solana_chains_controller_test.go
+++ b/core/web/solana_chains_controller_test.go
@@ -18,7 +18,7 @@ import (
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/web"
"github.com/smartcontractkit/chainlink/v2/core/web/presenters"
From a3817b5d5a9a3686dfcfca54d4859ac926bef680 Mon Sep 17 00:00:00 2001
From: Lukasz <120112546+lukaszcl@users.noreply.github.com>
Date: Wed, 25 Oct 2023 15:10:22 +0200
Subject: [PATCH 007/327] Pass docker image and version to ClNode in E2E tests
(#11082)
* Pass docker image and version to ClNode
* Update logging
* Fix
---
integration-tests/docker/test_env/cl_node.go | 46 +++++++++----------
integration-tests/docker/test_env/test_env.go | 2 +-
2 files changed, 22 insertions(+), 26 deletions(-)
diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go
index bf4d3285dc..4c40e64121 100644
--- a/integration-tests/docker/test_env/cl_node.go
+++ b/integration-tests/docker/test_env/cl_node.go
@@ -49,6 +49,8 @@ type ClNode struct {
NodeConfig *chainlink.Config `json:"-"`
NodeSecretsConfigTOML string `json:"-"`
PostgresDb *test_env.PostgresDb `json:"postgresDb"`
+ UserEmail string `json:"userEmail"`
+ UserPassword string `json:"userPassword"`
t *testing.T
l zerolog.Logger
lw *logwatch.LogWatch
@@ -86,18 +88,22 @@ func WithLogWatch(lw *logwatch.LogWatch) ClNodeOption {
}
}
-func NewClNode(networks []string, nodeConfig *chainlink.Config, opts ...ClNodeOption) *ClNode {
+func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, opts ...ClNodeOption) *ClNode {
nodeDefaultCName := fmt.Sprintf("%s-%s", "cl-node", uuid.NewString()[0:8])
pgDefaultCName := fmt.Sprintf("pg-%s", nodeDefaultCName)
pgDb := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName))
n := &ClNode{
EnvComponent: test_env.EnvComponent{
- ContainerName: nodeDefaultCName,
- Networks: networks,
+ ContainerName: nodeDefaultCName,
+ ContainerImage: imageName,
+ ContainerVersion: imageVersion,
+ Networks: networks,
},
- NodeConfig: nodeConfig,
- PostgresDb: pgDb,
- l: log.Logger,
+ UserEmail: "local@local.com",
+ UserPassword: "localdevpassword",
+ NodeConfig: nodeConfig,
+ PostgresDb: pgDb,
+ l: log.Logger,
}
for _, opt := range opts {
opt(n)
@@ -126,7 +132,7 @@ func (n *ClNode) UpgradeVersion(cfg *chainlink.Config, newImage, newVersion stri
return fmt.Errorf("new version is empty")
}
if newImage == "" {
- newImage = os.Getenv("CHAINLINK_IMAGE")
+ return fmt.Errorf("new image name is empty")
}
n.ContainerImage = newImage
n.ContainerVersion = newVersion
@@ -291,14 +297,19 @@ func (n *ClNode) StartContainer() error {
if err != nil {
return err
}
- n.l.Info().Str("containerName", n.ContainerName).
+ n.l.Info().
+ Str("containerName", n.ContainerName).
+ Str("containerImage", n.ContainerImage).
+ Str("containerVersion", n.ContainerVersion).
Str("clEndpoint", clEndpoint).
Str("clInternalIP", ip).
+ Str("userEmail", n.UserEmail).
+ Str("userPassword", n.UserPassword).
Msg("Started Chainlink Node container")
clClient, err := client.NewChainlinkClient(&client.ChainlinkConfig{
URL: clEndpoint,
- Email: "local@local.com",
- Password: "localdevpassword",
+ Email: n.UserEmail,
+ Password: n.UserPassword,
InternalIP: ip,
},
n.l)
@@ -360,21 +371,6 @@ func (n *ClNode) getContainerRequest(secrets string) (
adminCredsPath := "/home/admin-credentials.txt"
apiCredsPath := "/home/api-credentials.txt"
- if n.ContainerImage == "" {
- image, ok := os.LookupEnv("CHAINLINK_IMAGE")
- if !ok {
- return nil, errors.New("CHAINLINK_IMAGE env must be set")
- }
- n.ContainerImage = image
- }
- if n.ContainerVersion == "" {
- version, ok := os.LookupEnv("CHAINLINK_VERSION")
- if !ok {
- return nil, errors.New("CHAINLINK_VERSION env must be set")
- }
- n.ContainerVersion = version
- }
-
return &tc.ContainerRequest{
Name: n.ContainerName,
Image: fmt.Sprintf("%s:%s", n.ContainerImage, n.ContainerVersion),
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index 9eb9ed9f39..07b193f102 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -142,7 +142,7 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i
} else {
te.ClCluster = &ClCluster{}
for i := 0; i < count; i++ {
- ocrNode := NewClNode([]string{te.Network.Name}, nodeConfig,
+ ocrNode := NewClNode([]string{te.Network.Name}, os.Getenv("CHAINLINK_IMAGE"), os.Getenv("CHAINLINK_VERSION"), nodeConfig,
WithSecrets(secretsConfig),
)
te.ClCluster.Nodes = append(te.ClCluster.Nodes, ocrNode)
From 93a4ef9de2046510cb634513e3e97074c89a8386 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Wed, 25 Oct 2023 16:08:53 +0200
Subject: [PATCH 008/327] fix several npm audit issues (#11080)
* fix: json-schema
* bump eth-gas-reporter
* fix shelljs
* fix minimatch & lodash
* run hh on lockfile changes
---
.github/workflows/solidity-hardhat.yml | 1 +
contracts/pnpm-lock.yaml | 457 ++-----------------------
2 files changed, 32 insertions(+), 426 deletions(-)
diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml
index 2e25e52753..334ce4d1ba 100644
--- a/.github/workflows/solidity-hardhat.yml
+++ b/.github/workflows/solidity-hardhat.yml
@@ -28,6 +28,7 @@ jobs:
- 'contracts/src/!(v0.8/(llo-feeds|ccip)/**)/**/*'
- 'contracts/test/**/*'
- 'contracts/package.json'
+ - 'contracts/pnpm-lock.yaml'
- 'contracts/hardhat.config.ts'
- 'contracts/ci.json'
- '.github/workflows/solidity-hardhat.yml'
diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml
index 65865f2adf..2b6082d656 100644
--- a/contracts/pnpm-lock.yaml
+++ b/contracts/pnpm-lock.yaml
@@ -126,7 +126,7 @@ devDependencies:
version: 2.10.0(hardhat@2.18.1)
hardhat-gas-reporter:
specifier: ^1.0.9
- version: 1.0.9(hardhat@2.18.1)
+ version: 1.0.9(debug@4.3.4)(hardhat@2.18.1)
hardhat-ignore-warnings:
specifier: ^0.2.6
version: 0.2.9
@@ -2156,11 +2156,6 @@ packages:
dev: true
optional: true
- /ansi-colors@3.2.3:
- resolution: {integrity: sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==}
- engines: {node: '>=6'}
- dev: true
-
/ansi-colors@3.2.4:
resolution: {integrity: sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==}
engines: {node: '>=6'}
@@ -2193,11 +2188,6 @@ packages:
engines: {node: '>=4'}
dev: true
- /ansi-regex@4.1.1:
- resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
- engines: {node: '>=6'}
- dev: true
-
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -2330,17 +2320,6 @@ packages:
get-intrinsic: 1.2.1
dev: true
- /array.prototype.reduce@1.0.4:
- resolution: {integrity: sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==}
- engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.1.4
- es-abstract: 1.20.3
- es-array-method-boxes-properly: 1.0.0
- is-string: 1.0.7
- dev: true
-
/array.prototype.reduce@1.0.6:
resolution: {integrity: sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==}
engines: {node: '>= 0.4'}
@@ -3460,11 +3439,6 @@ packages:
engines: {node: '>=4'}
dev: true
- /camelcase@5.3.1:
- resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
- engines: {node: '>=6'}
- dev: true
-
/camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
@@ -3622,21 +3596,6 @@ packages:
parse5-htmlparser2-tree-adapter: 7.0.0
dev: true
- /chokidar@3.3.0:
- resolution: {integrity: sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==}
- engines: {node: '>= 8.10.0'}
- dependencies:
- anymatch: 3.1.2
- braces: 3.0.2
- glob-parent: 5.1.2
- is-binary-path: 2.1.0
- is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.2.0
- optionalDependencies:
- fsevents: 2.1.3
- dev: true
-
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@@ -3740,14 +3699,6 @@ packages:
wrap-ansi: 2.1.0
dev: true
- /cliui@5.0.0:
- resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==}
- dependencies:
- string-width: 3.1.0
- strip-ansi: 5.2.0
- wrap-ansi: 5.1.0
- dev: true
-
/cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
dependencies:
@@ -4136,7 +4087,7 @@ packages:
ms: 2.0.0
dev: true
- /debug@3.2.6(supports-color@6.0.0):
+ /debug@3.2.6:
resolution: {integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==}
deprecated: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)
peerDependencies:
@@ -4146,7 +4097,6 @@ packages:
optional: true
dependencies:
ms: 2.1.3
- supports-color: 6.0.0
dev: true
/debug@3.2.7:
@@ -4398,11 +4348,6 @@ packages:
- supports-color
dev: true
- /diff@3.5.0:
- resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==}
- engines: {node: '>=0.3.1'}
- dev: true
-
/diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
@@ -4518,10 +4463,6 @@ packages:
minimalistic-assert: 1.0.1
minimalistic-crypto-utils: 1.0.1
- /emoji-regex@7.0.3:
- resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==}
- dev: true
-
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
dev: true
@@ -4585,36 +4526,6 @@ packages:
is-arrayish: 0.2.1
dev: true
- /es-abstract@1.20.3:
- resolution: {integrity: sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==}
- engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.2
- es-to-primitive: 1.2.1
- function-bind: 1.1.1
- function.prototype.name: 1.1.5
- get-intrinsic: 1.1.3
- get-symbol-description: 1.0.0
- has: 1.0.3
- has-property-descriptors: 1.0.0
- has-symbols: 1.0.3
- internal-slot: 1.0.3
- is-callable: 1.2.7
- is-negative-zero: 2.0.2
- is-regex: 1.1.4
- is-shared-array-buffer: 1.0.2
- is-string: 1.0.7
- is-weakref: 1.0.2
- object-inspect: 1.12.2
- object-keys: 1.1.1
- object.assign: 4.1.4
- regexp.prototype.flags: 1.4.3
- safe-regex-test: 1.0.0
- string.prototype.trimend: 1.0.5
- string.prototype.trimstart: 1.0.5
- unbox-primitive: 1.0.2
- dev: true
-
/es-abstract@1.22.2:
resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==}
engines: {node: '>= 0.4'}
@@ -4916,29 +4827,31 @@ packages:
js-sha3: 0.5.7
dev: true
- /eth-gas-reporter@0.2.25:
- resolution: {integrity: sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ==}
+ /eth-gas-reporter@0.2.27(debug@4.3.4):
+ resolution: {integrity: sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==}
peerDependencies:
'@codechecks/client': ^0.1.0
peerDependenciesMeta:
'@codechecks/client':
optional: true
dependencies:
- '@ethersproject/abi': 5.7.0
'@solidity-parser/parser': 0.14.3
+ axios: 1.5.1(debug@4.3.4)
cli-table3: 0.5.1
colors: 1.4.0
ethereum-cryptography: 1.1.2
- ethers: 4.0.49
+ ethers: 5.7.2
fs-readdir-recursive: 1.1.0
lodash: 4.17.21
markdown-table: 1.1.3
- mocha: 7.2.0
+ mocha: 10.2.0
req-cwd: 2.0.0
- request: 2.88.2
- request-promise-native: 1.0.9(request@2.88.2)
sha1: 1.1.1
sync-request: 6.1.0
+ transitivePeerDependencies:
+ - bufferutil
+ - debug
+ - utf-8-validate
dev: true
/eth-json-rpc-infura@3.2.1:
@@ -5654,13 +5567,6 @@ packages:
locate-path: 2.0.0
dev: true
- /find-up@3.0.0:
- resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
- engines: {node: '>=6'}
- dependencies:
- locate-path: 3.0.0
- dev: true
-
/find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
@@ -5700,13 +5606,6 @@ packages:
rimraf: 3.0.2
dev: true
- /flat@4.1.1:
- resolution: {integrity: sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==}
- hasBin: true
- dependencies:
- is-buffer: 2.0.5
- dev: true
-
/flat@5.0.2:
resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
hasBin: true
@@ -5862,15 +5761,6 @@ packages:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
- /fsevents@2.1.3:
- resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
- deprecated: '"Please update to latest v2.3 or v2.2"'
- requiresBuild: true
- dev: true
- optional: true
-
/fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -5883,16 +5773,6 @@ packages:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
- /function.prototype.name@1.1.5:
- resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
- engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.1.4
- es-abstract: 1.20.3
- functions-have-names: 1.2.3
- dev: true
-
/function.prototype.name@1.1.6:
resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
engines: {node: '>= 0.4'}
@@ -5921,7 +5801,7 @@ packages:
bip39: 2.5.0
cachedown: 1.0.0
clone: 2.1.2
- debug: 3.2.6(supports-color@6.0.0)
+ debug: 3.2.6
encoding-down: 5.0.4
eth-sig-util: 3.0.0
ethereumjs-abi: 0.6.8
@@ -5934,7 +5814,7 @@ packages:
heap: 0.2.6
level-sublevel: 6.6.4
levelup: 3.1.1
- lodash: 4.17.20
+ lodash: 4.17.21
lru-cache: 5.1.1
merkle-patricia-tree: 3.0.0
patch-package: 6.2.2
@@ -6066,17 +5946,6 @@ packages:
path-is-absolute: 1.0.1
dev: true
- /glob@7.1.3:
- resolution: {integrity: sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==}
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 3.1.2
- once: 1.4.0
- path-is-absolute: 1.0.1
- dev: true
-
/glob@7.1.7:
resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==}
dependencies:
@@ -6268,11 +6137,6 @@ packages:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
dev: true
- /growl@1.10.5:
- resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==}
- engines: {node: '>=4.x'}
- dev: true
-
/handlebars@4.7.7:
resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==}
engines: {node: '>=0.4.7'}
@@ -6322,17 +6186,20 @@ packages:
strip-ansi: 6.0.1
dev: true
- /hardhat-gas-reporter@1.0.9(hardhat@2.18.1):
+ /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.18.1):
resolution: {integrity: sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==}
peerDependencies:
hardhat: ^2.0.2
dependencies:
array-uniq: 1.0.3
- eth-gas-reporter: 0.2.25
+ eth-gas-reporter: 0.2.27(debug@4.3.4)
hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
sha1: 1.1.1
transitivePeerDependencies:
- '@codechecks/client'
+ - bufferutil
+ - debug
+ - utf-8-validate
dev: true
/hardhat-ignore-warnings@0.2.9:
@@ -6648,7 +6515,7 @@ packages:
engines: {node: '>=0.8', npm: '>=1.3.7'}
dependencies:
assert-plus: 1.0.0
- jsprim: 1.4.1
+ jsprim: 1.4.2
sshpk: 1.16.1
dev: true
@@ -6759,15 +6626,6 @@ packages:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
dev: true
- /internal-slot@1.0.3:
- resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==}
- engines: {node: '>= 0.4'}
- dependencies:
- get-intrinsic: 1.1.3
- has: 1.0.3
- side-channel: 1.0.4
- dev: true
-
/internal-slot@1.0.5:
resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
engines: {node: '>= 0.4'}
@@ -6878,12 +6736,6 @@ packages:
ci-info: 2.0.0
dev: true
- /is-core-module@2.10.0:
- resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
- dependencies:
- has: 1.0.3
- dev: true
-
/is-core-module@2.13.0:
resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
dependencies:
@@ -7268,14 +7120,6 @@ packages:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
- /js-yaml@3.13.1:
- resolution: {integrity: sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==}
- hasBin: true
- dependencies:
- argparse: 1.0.10
- esprima: 4.0.1
- dev: true
-
/js-yaml@3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
hasBin: true
@@ -7349,8 +7193,8 @@ packages:
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
dev: true
- /json-schema@0.2.3:
- resolution: {integrity: sha512-a3xHnILGMtk+hDOqNwHzF6e2fNbiMrXZvxKQiEv2MlgQP+pjIOzqAmKYD2mDpXYE/44M7g+n9p2bKkYWDUcXCQ==}
+ /json-schema@0.4.0:
+ resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
dev: true
/json-stable-stringify-without-jsonify@1.0.1:
@@ -7413,13 +7257,13 @@ packages:
resolution: {integrity: sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==}
dev: true
- /jsprim@1.4.1:
- resolution: {integrity: sha512-4Dj8Rf+fQ+/Pn7C5qeEX02op1WfOss3PKTE9Nsop3Dx+6UPxlm1dr/og7o2cRa5hNN07CACr4NFzRLtj/rjWog==}
- engines: {'0': node >=0.6.0}
+ /jsprim@1.4.2:
+ resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
+ engines: {node: '>=0.6.0'}
dependencies:
assert-plus: 1.0.0
extsprintf: 1.3.0
- json-schema: 0.2.3
+ json-schema: 0.4.0
verror: 1.10.0
dev: true
@@ -7680,14 +7524,6 @@ packages:
path-exists: 3.0.0
dev: true
- /locate-path@3.0.0:
- resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
- engines: {node: '>=6'}
- dependencies:
- p-locate: 3.0.0
- path-exists: 3.0.0
- dev: true
-
/locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@@ -7734,13 +7570,6 @@ packages:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
dev: true
- /log-symbols@3.0.0:
- resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==}
- engines: {node: '>=8'}
- dependencies:
- chalk: 2.4.2
- dev: true
-
/log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
@@ -8036,12 +7865,6 @@ packages:
/minimalistic-crypto-utils@1.0.1:
resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==}
- /minimatch@3.0.4:
- resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
- dependencies:
- brace-expansion: 1.1.11
- dev: true
-
/minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies:
@@ -8102,13 +7925,6 @@ packages:
mkdirp: 1.0.4
dev: true
- /mkdirp@0.5.5:
- resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==}
- hasBin: true
- dependencies:
- minimist: 1.2.6
- dev: true
-
/mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
@@ -8156,37 +7972,6 @@ packages:
yargs-unparser: 2.0.0
dev: true
- /mocha@7.2.0:
- resolution: {integrity: sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==}
- engines: {node: '>= 8.10.0'}
- hasBin: true
- dependencies:
- ansi-colors: 3.2.3
- browser-stdout: 1.3.1
- chokidar: 3.3.0
- debug: 3.2.6(supports-color@6.0.0)
- diff: 3.5.0
- escape-string-regexp: 1.0.5
- find-up: 3.0.0
- glob: 7.1.3
- growl: 1.10.5
- he: 1.2.0
- js-yaml: 3.13.1
- log-symbols: 3.0.0
- minimatch: 3.0.4
- mkdirp: 0.5.5
- ms: 2.1.1
- node-environment-flags: 1.0.6
- object.assign: 4.1.0
- strip-json-comments: 2.0.1
- supports-color: 6.0.0
- which: 1.3.1
- wide-align: 1.1.3
- yargs: 13.3.2
- yargs-parser: 13.1.2
- yargs-unparser: 1.6.0
- dev: true
-
/mock-fs@4.12.0:
resolution: {integrity: sha512-/P/HtrlvBxY4o/PzXY9cCNBrdylDNxg7gnrv2sMNxj+UJ2m8jSpl0/A6fuJeNAWr99ZvGWH8XCbE0vmnM5KupQ==}
requiresBuild: true
@@ -8355,13 +8140,6 @@ packages:
lodash: 4.17.21
dev: true
- /node-environment-flags@1.0.6:
- resolution: {integrity: sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==}
- dependencies:
- object.getownpropertydescriptors: 2.1.4
- semver: 5.7.1
- dev: true
-
/node-fetch@1.7.3:
resolution: {integrity: sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==}
dependencies:
@@ -8414,7 +8192,7 @@ packages:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
dependencies:
hosted-git-info: 2.8.9
- resolve: 1.22.1
+ resolve: 1.22.8
semver: 5.7.1
validate-npm-package-license: 3.0.4
dev: true
@@ -8522,16 +8300,6 @@ packages:
isobject: 3.0.1
dev: true
- /object.assign@4.1.0:
- resolution: {integrity: sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==}
- engines: {node: '>= 0.4'}
- dependencies:
- define-properties: 1.1.4
- function-bind: 1.1.1
- has-symbols: 1.0.3
- object-keys: 1.1.1
- dev: true
-
/object.assign@4.1.4:
resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
engines: {node: '>= 0.4'}
@@ -8542,16 +8310,6 @@ packages:
object-keys: 1.1.1
dev: true
- /object.getownpropertydescriptors@2.1.4:
- resolution: {integrity: sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==}
- engines: {node: '>= 0.8'}
- dependencies:
- array.prototype.reduce: 1.0.4
- call-bind: 1.0.2
- define-properties: 1.1.4
- es-abstract: 1.20.3
- dev: true
-
/object.getownpropertydescriptors@2.1.7:
resolution: {integrity: sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==}
engines: {node: '>= 0.8'}
@@ -8726,13 +8484,6 @@ packages:
p-limit: 1.3.0
dev: true
- /p-locate@3.0.0:
- resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
- engines: {node: '>=6'}
- dependencies:
- p-limit: 2.3.0
- dev: true
-
/p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@@ -9385,13 +9136,6 @@ packages:
util-deprecate: 1.0.2
dev: true
- /readdirp@3.2.0:
- resolution: {integrity: sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==}
- engines: {node: '>= 8'}
- dependencies:
- picomatch: 2.3.1
- dev: true
-
/readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
@@ -9410,7 +9154,7 @@ packages:
resolution: {integrity: sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==}
engines: {node: '>=0.10.0'}
dependencies:
- minimatch: 3.0.4
+ minimatch: 3.1.2
dev: true
/reduce-flatten@2.0.0:
@@ -9514,29 +9258,6 @@ packages:
resolve-from: 3.0.0
dev: true
- /request-promise-core@1.1.4(request@2.88.2):
- resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==}
- engines: {node: '>=0.10.0'}
- peerDependencies:
- request: ^2.34
- dependencies:
- lodash: 4.17.21
- request: 2.88.2
- dev: true
-
- /request-promise-native@1.0.9(request@2.88.2):
- resolution: {integrity: sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==}
- engines: {node: '>=0.12.0'}
- deprecated: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
- peerDependencies:
- request: ^2.34
- dependencies:
- request: 2.88.2
- request-promise-core: 1.1.4(request@2.88.2)
- stealthy-require: 1.1.1
- tough-cookie: 2.5.0
- dev: true
-
/request@2.88.2:
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
engines: {node: '>= 6'}
@@ -9583,10 +9304,6 @@ packages:
resolution: {integrity: sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==}
dev: true
- /require-main-filename@2.0.0:
- resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
- dev: true
-
/resolve-alpn@1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
dev: true
@@ -9616,15 +9333,6 @@ packages:
path-parse: 1.0.7
dev: true
- /resolve@1.22.1:
- resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
- hasBin: true
- dependencies:
- is-core-module: 2.10.0
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
- dev: true
-
/resolve@1.22.8:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
hasBin: true
@@ -10013,8 +9721,8 @@ packages:
engines: {node: '>=8'}
dev: true
- /shelljs@0.8.3:
- resolution: {integrity: sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==}
+ /shelljs@0.8.5:
+ resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
engines: {node: '>=4'}
hasBin: true
dependencies:
@@ -10332,7 +10040,7 @@ packages:
recursive-readdir: 2.2.2
sc-istanbul: 0.4.6
semver: 7.5.4
- shelljs: 0.8.3
+ shelljs: 0.8.5
web3-utils: 1.8.0
transitivePeerDependencies:
- supports-color
@@ -10474,11 +10182,6 @@ packages:
engines: {node: '>= 0.8'}
dev: true
- /stealthy-require@1.1.1:
- resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==}
- engines: {node: '>=0.10.0'}
- dev: true
-
/stream-to-pull-stream@1.7.3:
resolution: {integrity: sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg==}
dependencies:
@@ -10518,15 +10221,6 @@ packages:
strip-ansi: 4.0.0
dev: true
- /string-width@3.1.0:
- resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==}
- engines: {node: '>=6'}
- dependencies:
- emoji-regex: 7.0.3
- is-fullwidth-code-point: 2.0.0
- strip-ansi: 5.2.0
- dev: true
-
/string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -10545,14 +10239,6 @@ packages:
es-abstract: 1.22.2
dev: true
- /string.prototype.trimend@1.0.5:
- resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.1.4
- es-abstract: 1.20.3
- dev: true
-
/string.prototype.trimend@1.0.7:
resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
dependencies:
@@ -10561,14 +10247,6 @@ packages:
es-abstract: 1.22.2
dev: true
- /string.prototype.trimstart@1.0.5:
- resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.1.4
- es-abstract: 1.20.3
- dev: true
-
/string.prototype.trimstart@1.0.7:
resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
dependencies:
@@ -10607,13 +10285,6 @@ packages:
ansi-regex: 3.0.1
dev: true
- /strip-ansi@5.2.0:
- resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==}
- engines: {node: '>=6'}
- dependencies:
- ansi-regex: 4.1.1
- dev: true
-
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -10650,11 +10321,6 @@ packages:
engines: {node: '>=4'}
dev: true
- /strip-json-comments@2.0.1:
- resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
- engines: {node: '>=0.10.0'}
- dev: true
-
/strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -10679,13 +10345,6 @@ packages:
has-flag: 3.0.0
dev: true
- /supports-color@6.0.0:
- resolution: {integrity: sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==}
- engines: {node: '>=6'}
- dependencies:
- has-flag: 3.0.0
- dev: true
-
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -11006,7 +10665,7 @@ packages:
glob: 7.2.3
mkdirp: 0.5.6
prettier: 2.8.8
- resolve: 1.22.1
+ resolve: 1.22.8
ts-essentials: 1.0.4
dev: true
@@ -12408,10 +12067,6 @@ packages:
resolution: {integrity: sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==}
dev: true
- /which-module@2.0.0:
- resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==}
- dev: true
-
/which-typed-array@1.1.11:
resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==}
engines: {node: '>= 0.4'}
@@ -12438,12 +12093,6 @@ packages:
isexe: 2.0.0
dev: true
- /wide-align@1.1.3:
- resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==}
- dependencies:
- string-width: 2.1.1
- dev: true
-
/window-size@0.2.0:
resolution: {integrity: sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw==}
engines: {node: '>= 0.10.0'}
@@ -12479,15 +12128,6 @@ packages:
strip-ansi: 3.0.1
dev: true
- /wrap-ansi@5.1.0:
- resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==}
- engines: {node: '>=6'}
- dependencies:
- ansi-styles: 3.2.1
- string-width: 3.1.0
- strip-ansi: 5.2.0
- dev: true
-
/wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -12613,10 +12253,6 @@ packages:
resolution: {integrity: sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==}
dev: true
- /y18n@4.0.3:
- resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
- dev: true
-
/y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -12640,13 +12276,6 @@ packages:
engines: {node: '>= 6'}
dev: true
- /yargs-parser@13.1.2:
- resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==}
- dependencies:
- camelcase: 5.3.1
- decamelize: 1.2.0
- dev: true
-
/yargs-parser@2.4.1:
resolution: {integrity: sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA==}
dependencies:
@@ -12659,15 +12288,6 @@ packages:
engines: {node: '>=10'}
dev: true
- /yargs-unparser@1.6.0:
- resolution: {integrity: sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==}
- engines: {node: '>=6'}
- dependencies:
- flat: 4.1.1
- lodash: 4.17.21
- yargs: 13.3.2
- dev: true
-
/yargs-unparser@2.0.0:
resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
engines: {node: '>=10'}
@@ -12678,21 +12298,6 @@ packages:
is-plain-obj: 2.1.0
dev: true
- /yargs@13.3.2:
- resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==}
- dependencies:
- cliui: 5.0.0
- find-up: 3.0.0
- get-caller-file: 2.0.5
- require-directory: 2.1.1
- require-main-filename: 2.0.0
- set-blocking: 2.0.0
- string-width: 3.1.0
- which-module: 2.0.0
- y18n: 4.0.3
- yargs-parser: 13.1.2
- dev: true
-
/yargs@16.2.0:
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
engines: {node: '>=10'}
From d31223c6f9767ef775932d7622dd709f3b7fafdb Mon Sep 17 00:00:00 2001
From: Ilja Pavlovs
Date: Wed, 25 Oct 2023 17:34:02 +0300
Subject: [PATCH 009/327] VRF-664:add Slack notification for VRF v2 Plus WASP
test (#11063)
* VRF-664:add Slack notification for VRF v2 Plus WASP test
* VRF-664:fixing import cycle
* VRF-664:cleanup
* VRF-664:adding slack channel secret
---
... on-demand-vrfv2plus-performance-test.yml} | 23 ++--
.../vrfv2plus/vrfv2plus_config/config.go | 2 +
integration-tests/load/vrfv2plus/config.go | 23 ++--
integration-tests/load/vrfv2plus/config.toml | 8 +-
.../load/vrfv2plus/onchain_monitoring.go | 22 ++--
.../load/vrfv2plus/vrfv2plus_test.go | 117 +++++++++++++-----
integration-tests/testreporters/vrfv2plus.go | 91 ++++++++++++++
7 files changed, 228 insertions(+), 58 deletions(-)
rename .github/workflows/{on-demand-vrfv2plus-load-test.yml => on-demand-vrfv2plus-performance-test.yml} (84%)
create mode 100644 integration-tests/testreporters/vrfv2plus.go
diff --git a/.github/workflows/on-demand-vrfv2plus-load-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
similarity index 84%
rename from .github/workflows/on-demand-vrfv2plus-load-test.yml
rename to .github/workflows/on-demand-vrfv2plus-performance-test.yml
index f4ca096d5c..b33c6f8313 100644
--- a/.github/workflows/on-demand-vrfv2plus-load-test.yml
+++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
@@ -1,4 +1,4 @@
-name: On Demand VRFV2 Plus Load Test
+name: On Demand VRFV2 Plus Performance Test
on:
workflow_dispatch:
inputs:
@@ -49,8 +49,8 @@ on:
- "Spike"
testDuration:
description: Duration of the test (time string)
- required: false
- default: 1m
+ required: true
+ default: 5m
useExistingEnv:
description: Set `true` to use existing environment or `false` to deploy CL node and all contracts
required: false
@@ -59,8 +59,8 @@ on:
description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env)
required: false
jobs:
- vrfv2plus_load_test:
- name: ${{ inputs.network }} VRFV2 Plus Load Test
+ vrfv2plus_performance_test:
+ name: ${{ inputs.network }} VRFV2 Plus Performance Test
environment: integration
runs-on: ubuntu20.04-8cores-32GB
permissions:
@@ -80,6 +80,8 @@ jobs:
REF_NAME: ${{ github.head_ref || github.ref_name }}
CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }}
CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }}
+ SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }}
+ SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }}
WASP_LOG_LEVEL: info
steps:
- name: Collect Metrics
@@ -88,8 +90,15 @@ jobs:
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
- this-job-name: ${{ inputs.network }} VRFV2 Plus Load Test
+ this-job-name: ${{ inputs.network }} VRFV2 Plus Performance Test
continue-on-error: true
+ - name: Setup Push Tag
+ shell: bash
+ run: |
+ echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY
+ echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY
+ echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY
+ echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY
- name: Get Inputs
run: |
EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH)
@@ -111,7 +120,7 @@ jobs:
- name: Run Tests
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
with:
- test_command_to_run: cd ./integration-tests && go test -v -count=1 -timeout 6h -run TestVRFV2PlusLoad/vrfv2plus_soak_test ./load/vrfv2plus
+ test_command_to_run: cd ./integration-tests && go test -v -count=1 -timeout 6h -run TestVRFV2PlusPerformance/vrfv2plus_performance_test ./load/vrfv2plus
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ inputs.chainlinkImage }}
cl_image_tag: ${{ inputs.chainlinkVersion }}
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
index 7a1221eaf8..caee353294 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
@@ -18,6 +18,8 @@ type VRFV2PlusConfig struct {
FulfillmentFlatFeeLinkPPM uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM" default:"500"` // Flat fee in ppm for LINK for the VRF Coordinator config
FulfillmentFlatFeeNativePPM uint32 `envconfig:"FULFILLMENT_FLAT_FEE_NATIVE_PPM" default:"500"` // Flat fee in ppm for native currency for the VRF Coordinator config
+ NumberOfSubToCreate int `envconfig:"NUMBER_OF_SUB_TO_CREATE" default:"1"` // Number of subscriptions to create
+
RandomnessRequestCountPerRequest uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST" default:"1"` // How many randomness requests to send per request
RandomnessRequestCountPerRequestDeviation uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST_DEVIATION" default:"0"` // How many randomness requests to send per request
diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go
index 5f3babfeab..329e4abf13 100644
--- a/integration-tests/load/vrfv2plus/config.go
+++ b/integration-tests/load/vrfv2plus/config.go
@@ -12,6 +12,10 @@ import (
const (
DefaultConfigFilename = "config.toml"
+ SoakTestType = "Soak"
+ LoadTestType = "Load"
+ StressTestType = "Stress"
+ SpikeTestType = "Spike"
ErrReadPerfConfig = "failed to read TOML config for performance tests"
ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests"
@@ -38,7 +42,6 @@ type ExistingEnvConfig struct {
type NewEnvConfig struct {
Funding
- NumberOfSubToCreate int `toml:"number_of_sub_to_create"`
}
type Common struct {
@@ -68,6 +71,8 @@ type Spike struct {
}
type PerformanceTestConfig struct {
+ NumberOfSubToCreate int `toml:"number_of_sub_to_create"`
+
RPS int64 `toml:"rps"`
//Duration *models.Duration `toml:"duration"`
RateLimitUnitDuration *models.Duration `toml:"rate_limit_unit_duration"`
@@ -101,24 +106,28 @@ func ReadConfig() (*PerformanceConfig, error) {
return cfg, nil
}
-func SetPerformanceTestConfig(vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig, cfg *PerformanceConfig) {
- switch os.Getenv("TEST_TYPE") {
- case "Soak":
+func SetPerformanceTestConfig(testType string, vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig, cfg *PerformanceConfig) {
+ switch testType {
+ case SoakTestType:
+ vrfv2PlusConfig.NumberOfSubToCreate = cfg.Soak.NumberOfSubToCreate
vrfv2PlusConfig.RPS = cfg.Soak.RPS
vrfv2PlusConfig.RateLimitUnitDuration = cfg.Soak.RateLimitUnitDuration.Duration()
vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Soak.RandomnessRequestCountPerRequest
vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Soak.RandomnessRequestCountPerRequestDeviation
- case "Load":
+ case LoadTestType:
+ vrfv2PlusConfig.NumberOfSubToCreate = cfg.Load.NumberOfSubToCreate
vrfv2PlusConfig.RPS = cfg.Load.RPS
vrfv2PlusConfig.RateLimitUnitDuration = cfg.Load.RateLimitUnitDuration.Duration()
vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Load.RandomnessRequestCountPerRequest
vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Load.RandomnessRequestCountPerRequestDeviation
- case "Stress":
+ case StressTestType:
+ vrfv2PlusConfig.NumberOfSubToCreate = cfg.Stress.NumberOfSubToCreate
vrfv2PlusConfig.RPS = cfg.Stress.RPS
vrfv2PlusConfig.RateLimitUnitDuration = cfg.Stress.RateLimitUnitDuration.Duration()
vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Stress.RandomnessRequestCountPerRequest
vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Stress.RandomnessRequestCountPerRequestDeviation
- case "Spike":
+ case SpikeTestType:
+ vrfv2PlusConfig.NumberOfSubToCreate = cfg.Spike.NumberOfSubToCreate
vrfv2PlusConfig.RPS = cfg.Spike.RPS
vrfv2PlusConfig.RateLimitUnitDuration = cfg.Spike.RateLimitUnitDuration.Duration()
vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Spike.RandomnessRequestCountPerRequest
diff --git a/integration-tests/load/vrfv2plus/config.toml b/integration-tests/load/vrfv2plus/config.toml
index 1208423dc0..31a0bf5665 100644
--- a/integration-tests/load/vrfv2plus/config.toml
+++ b/integration-tests/load/vrfv2plus/config.toml
@@ -6,7 +6,7 @@ minimum_confirmations = 3
sub_funds_link = 1000
sub_funds_native = 1000
node_funds = 10
-number_of_sub_to_create = 10
+
[ExistingEnvConfig]
coordinator_address = "0x4931Ce2e341398c8eD8A5D0F6ADb920476D6DaBb"
@@ -21,6 +21,7 @@ rate_limit_unit_duration = "6s"
rps = 1
randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting
+number_of_sub_to_create = 1
# approx 60 RPM - 1 tx request with 4 rand requests in each tx every 3 seconds
[Load]
@@ -28,13 +29,15 @@ rate_limit_unit_duration = "3s"
rps = 1
randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting
+number_of_sub_to_create = 10
# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx
[Stress]
-rate_limit_unit_duration = "0"
+rate_limit_unit_duration = "1s"
rps = 3
randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting
+number_of_sub_to_create = 20
# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds
[Spike]
@@ -42,3 +45,4 @@ rate_limit_unit_duration = "1m"
rps = 1
randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting
+number_of_sub_to_create = 1
\ No newline at end of file
diff --git a/integration-tests/load/vrfv2plus/onchain_monitoring.go b/integration-tests/load/vrfv2plus/onchain_monitoring.go
index 0ae27fe6be..c56d835234 100644
--- a/integration-tests/load/vrfv2plus/onchain_monitoring.go
+++ b/integration-tests/load/vrfv2plus/onchain_monitoring.go
@@ -3,7 +3,7 @@ package loadvrfv2plus
import (
"context"
"github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/wasp"
"testing"
"time"
@@ -18,11 +18,12 @@ const (
ErrLokiPush = "failed to push monitoring metrics to Loki"
)
-func MonitorLoadStats(lc *wasp.LokiClient, vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts, labels map[string]string) {
+func MonitorLoadStats(lc *wasp.LokiClient, consumer contracts.VRFv2PlusLoadTestConsumer, labels map[string]string) {
go func() {
for {
time.Sleep(1 * time.Second)
- SendLoadTestMetricsToLoki(vrfv2PlusContracts, lc, labels)
+ metrics := GetLoadTestMetrics(consumer)
+ SendMetricsToLoki(metrics, lc, labels)
}
}()
}
@@ -38,13 +39,16 @@ func UpdateLabels(labels map[string]string, t *testing.T) map[string]string {
return updatedLabels
}
-func SendLoadTestMetricsToLoki(vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts, lc *wasp.LokiClient, updatedLabels map[string]string) {
- //todo - should work with multiple consumers and consumers having different keyhashes and wallets
- metrics, err := vrfv2PlusContracts.LoadTestConsumers[0].GetLoadTestMetrics(context.Background())
- if err != nil {
- log.Error().Err(err).Msg(ErrMetrics)
- }
+func SendMetricsToLoki(metrics *contracts.VRFLoadTestMetrics, lc *wasp.LokiClient, updatedLabels map[string]string) {
if err := lc.HandleStruct(wasp.LabelsMapToModel(updatedLabels), time.Now(), metrics); err != nil {
log.Error().Err(err).Msg(ErrLokiPush)
}
}
+
+func GetLoadTestMetrics(consumer contracts.VRFv2PlusLoadTestConsumer) *contracts.VRFLoadTestMetrics {
+ metrics, err := consumer.GetLoadTestMetrics(context.Background())
+ if err != nil {
+ log.Error().Err(err).Msg(ErrMetrics)
+ }
+ return metrics
+}
diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
index 5c3ea6e8c6..a3cb4d4b7f 100644
--- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go
+++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
@@ -4,7 +4,9 @@ import (
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/kelseyhightower/envconfig"
+ "github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink/integration-tests/testreporters"
"github.com/smartcontractkit/wasp"
"github.com/stretchr/testify/require"
"math/big"
@@ -20,21 +22,46 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
)
-func TestVRFV2PlusLoad(t *testing.T) {
+var (
+ env *test_env.CLClusterTestEnv
+ vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts
+ vrfv2PlusData *vrfv2plus.VRFV2PlusData
+ subIDs []*big.Int
+
+ labels = map[string]string{
+ "branch": "vrfv2Plus_healthcheck",
+ "commit": "vrfv2Plus_healthcheck",
+ }
+
+ testType = os.Getenv("TEST_TYPE")
+)
+
+func TestVRFV2PlusPerformance(t *testing.T) {
cfg, err := ReadConfig()
require.NoError(t, err)
var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig
err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig)
require.NoError(t, err)
- SetPerformanceTestConfig(&vrfv2PlusConfig, cfg)
+ testReporter := &testreporters.VRFV2PlusTestReporter{}
+
+ SetPerformanceTestConfig(testType, &vrfv2PlusConfig, cfg)
l := logging.GetTestLogger(t)
//todo: temporary solution with envconfig and toml config until VRF-662 is implemented
vrfv2PlusConfig.MinimumConfirmations = cfg.Common.MinimumConfirmations
+ lokiConfig := wasp.NewEnvLokiConfig()
+ lc, err := wasp.NewLokiClient(lokiConfig)
+ if err != nil {
+ l.Error().Err(err).Msg(ErrLokiClient)
+ return
+ }
+
+ updatedLabels := UpdateLabels(labels, t)
+
l.Info().
- Str("Test Type", os.Getenv("TEST_TYPE")).
+ Str("Test Type", testType).
Str("Test Duration", vrfv2PlusConfig.TestDuration.Truncate(time.Second).String()).
Int64("RPS", vrfv2PlusConfig.RPS).
Str("RateLimitUnitDuration", vrfv2PlusConfig.RateLimitUnitDuration.String()).
@@ -43,11 +70,6 @@ func TestVRFV2PlusLoad(t *testing.T) {
Bool("UseExistingEnv", vrfv2PlusConfig.UseExistingEnv).
Msg("Performance Test Configuration")
- var env *test_env.CLClusterTestEnv
- var vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts
- var vrfv2PlusData *vrfv2plus.VRFV2PlusData
- var subIDs []*big.Int
-
if vrfv2PlusConfig.UseExistingEnv {
//todo: temporary solution with envconfig and toml config until VRF-662 is implemented
vrfv2PlusConfig.CoordinatorAddress = cfg.ExistingEnvConfig.CoordinatorAddress
@@ -57,7 +79,10 @@ func TestVRFV2PlusLoad(t *testing.T) {
env, err = test_env.NewCLTestEnvBuilder().
WithTestLogger(t).
- WithoutCleanup().
+ WithCustomCleanup(
+ func() {
+ teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig)
+ }).
Build()
require.NoError(t, err, "error creating test env")
@@ -93,13 +118,18 @@ func TestVRFV2PlusLoad(t *testing.T) {
vrfv2PlusConfig.ChainlinkNodeFunding = cfg.NewEnvConfig.NodeFunds
vrfv2PlusConfig.SubscriptionFundingAmountLink = cfg.NewEnvConfig.Funding.SubFundsLink
vrfv2PlusConfig.SubscriptionFundingAmountNative = cfg.NewEnvConfig.Funding.SubFundsNative
- numberOfSubToCreate := cfg.NewEnvConfig.NumberOfSubToCreate
env, err = test_env.NewCLTestEnvBuilder().
WithTestLogger(t).
WithGeth().
WithCLNodes(1).
WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)).
- WithStandardCleanup().
+ WithCustomCleanup(
+ func() {
+ teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig)
+ if err := env.Cleanup(); err != nil {
+ l.Error().Err(err).Msg("Error cleaning up test environment")
+ }
+ }).
WithLogWatcher().
Build()
@@ -113,29 +143,24 @@ func TestVRFV2PlusLoad(t *testing.T) {
linkToken, err := actions.DeployLINKToken(env.ContractDeployer)
require.NoError(t, err, "error deploying LINK contract")
- vrfv2PlusContracts, subIDs, vrfv2PlusData, err = vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkToken, mockETHLinkFeed, 1, numberOfSubToCreate)
+ vrfv2PlusContracts, subIDs, vrfv2PlusData, err = vrfv2plus.SetupVRFV2_5Environment(
+ env,
+ &vrfv2PlusConfig,
+ linkToken,
+ mockETHLinkFeed,
+ 1,
+ vrfv2PlusConfig.NumberOfSubToCreate,
+ )
require.NoError(t, err, "error setting up VRF v2_5 env")
}
- l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs Involved in Load Test")
+ l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test")
for _, subID := range subIDs {
subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
require.NoError(t, err, "error getting subscription information for subscription %s", subID.String())
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
}
- labels := map[string]string{
- "branch": "vrfv2Plus_healthcheck",
- "commit": "vrfv2Plus_healthcheck",
- }
-
- lokiConfig := wasp.NewEnvLokiConfig()
- lc, err := wasp.NewLokiClient(lokiConfig)
- if err != nil {
- l.Error().Err(err).Msg(ErrLokiClient)
- return
- }
-
singleFeedConfig := &wasp.Config{
T: t,
LoadType: wasp.RPS,
@@ -156,11 +181,10 @@ func TestVRFV2PlusLoad(t *testing.T) {
consumer := vrfv2PlusContracts.LoadTestConsumers[0]
err = consumer.ResetMetrics()
require.NoError(t, err)
- updatedLabels := UpdateLabels(labels, t)
- MonitorLoadStats(lc, vrfv2PlusContracts, updatedLabels)
+ MonitorLoadStats(lc, consumer, updatedLabels)
// is our "job" stable at all, no memory leaks, no flaking performance under some RPS?
- t.Run("vrfv2plus soak test", func(t *testing.T) {
+ t.Run("vrfv2plus performance test", func(t *testing.T) {
singleFeedConfig.Schedule = wasp.Plain(
vrfv2PlusConfig.RPS,
@@ -172,17 +196,44 @@ func TestVRFV2PlusLoad(t *testing.T) {
require.NoError(t, err)
var wg sync.WaitGroup
-
wg.Add(1)
+ //todo - timeout should be configurable depending on the perf test type
requestCount, fulfilmentCount, err := vrfv2plus.WaitForRequestCountEqualToFulfilmentCount(consumer, 30*time.Second, &wg)
+ require.NoError(t, err)
+ wg.Wait()
+
l.Info().
Interface("Request Count", requestCount).
Interface("Fulfilment Count", fulfilmentCount).
Msg("Final Request/Fulfilment Stats")
- require.NoError(t, err)
- wg.Wait()
- //send final results
- SendLoadTestMetricsToLoki(vrfv2PlusContracts, lc, updatedLabels)
})
+}
+func teardown(
+ t *testing.T,
+ consumer contracts.VRFv2PlusLoadTestConsumer,
+ lc *wasp.LokiClient, updatedLabels map[string]string,
+ testReporter *testreporters.VRFV2PlusTestReporter,
+ testType string,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
+) {
+ //send final results to Loki
+ metrics := GetLoadTestMetrics(consumer)
+ SendMetricsToLoki(metrics, lc, updatedLabels)
+ //set report data for Slack notification
+ testReporter.SetReportData(
+ testType,
+ metrics.RequestCount,
+ metrics.FulfilmentCount,
+ metrics.AverageFulfillmentInMillions,
+ metrics.SlowestFulfillment,
+ metrics.FastestFulfillment,
+ vrfv2PlusConfig,
+ )
+
+ // send Slack notification
+ err := testReporter.SendSlackNotification(t, nil)
+ if err != nil {
+ log.Warn().Err(err).Msg("Error sending Slack notification")
+ }
}
diff --git a/integration-tests/testreporters/vrfv2plus.go b/integration-tests/testreporters/vrfv2plus.go
new file mode 100644
index 0000000000..83d4678dfd
--- /dev/null
+++ b/integration-tests/testreporters/vrfv2plus.go
@@ -0,0 +1,91 @@
+package testreporters
+
+import (
+ "fmt"
+ "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
+ "math/big"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/slack-go/slack"
+
+ "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
+)
+
+type VRFV2PlusTestReporter struct {
+ TestType string
+ RequestCount *big.Int
+ FulfilmentCount *big.Int
+ AverageFulfillmentInMillions *big.Int
+ SlowestFulfillment *big.Int
+ FastestFulfillment *big.Int
+ Vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig
+}
+
+func (o *VRFV2PlusTestReporter) SetReportData(
+ testType string,
+ RequestCount *big.Int,
+ FulfilmentCount *big.Int,
+ AverageFulfillmentInMillions *big.Int,
+ SlowestFulfillment *big.Int,
+ FastestFulfillment *big.Int,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
+) {
+ o.TestType = testType
+ o.RequestCount = RequestCount
+ o.FulfilmentCount = FulfilmentCount
+ o.AverageFulfillmentInMillions = AverageFulfillmentInMillions
+ o.SlowestFulfillment = SlowestFulfillment
+ o.FastestFulfillment = FastestFulfillment
+ o.Vrfv2PlusConfig = &vrfv2PlusConfig
+}
+
+// SendSlackNotification sends a slack message to a slack webhook
+func (o *VRFV2PlusTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client) error {
+ if slackClient == nil {
+ slackClient = slack.New(testreporters.SlackAPIKey)
+ }
+
+ testFailed := t.Failed()
+ headerText := fmt.Sprintf(":white_check_mark: VRF %s Test PASSED :white_check_mark:", o.TestType)
+ if testFailed {
+ headerText = fmt.Sprintf(":x: VRF %s Test FAILED :x:", o.TestType)
+ }
+
+ messageBlocks := testreporters.SlackNotifyBlocks(headerText, fmt.Sprintf("%s", os.Getenv("SELECTED_NETWORKS")), []string{
+ fmt.Sprintf(
+ "Summary\n"+
+ "Perf Test Type: %s\n"+
+ "Test Duration set in parameters: %s\n"+
+ "Use Existing Env: %t\n"+
+ "Request Count: %s\n"+
+ "Fulfilment Count: %s\n"+
+ "AverageFulfillmentInMillions: %s\n"+
+ "Slowest Fulfillment: %s\n"+
+ "Fastest Fulfillment: %s \n"+
+ "RPS: %d\n"+
+ "RateLimitUnitDuration: %s\n"+
+ "RandomnessRequestCountPerRequest: %d\n"+
+ "RandomnessRequestCountPerRequestDeviation: %d\n",
+ o.TestType,
+ o.Vrfv2PlusConfig.TestDuration.Truncate(time.Second).String(),
+ o.Vrfv2PlusConfig.UseExistingEnv,
+ o.RequestCount.String(),
+ o.FulfilmentCount.String(),
+ o.AverageFulfillmentInMillions.String(),
+ o.SlowestFulfillment.String(),
+ o.FastestFulfillment.String(),
+ o.Vrfv2PlusConfig.RPS,
+ o.Vrfv2PlusConfig.RateLimitUnitDuration.String(),
+ o.Vrfv2PlusConfig.RandomnessRequestCountPerRequest,
+ o.Vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation,
+ ),
+ })
+
+ _, err := testreporters.SendSlackMessage(slackClient, slack.MsgOptionBlocks(messageBlocks...))
+ if err != nil {
+ return err
+ }
+ return nil
+}
From 3e75b262f11603383609e2a5757d5170adb07e88 Mon Sep 17 00:00:00 2001
From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com>
Date: Wed, 25 Oct 2023 08:20:04 -0700
Subject: [PATCH 010/327] Bump version and update CHANGELOG for core v2.7.0
(#11072)
---
VERSION | 2 +-
docs/CHANGELOG.md | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index e70b4523ae..24ba9a38de 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.6.0
+2.7.0
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 469cd0d168..44d018769e 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [dev]
+...
+
+## 2.7.0 - UNRELEASED
+
### Added
- Added new configuration field named `LeaseDuration` for `EVM.NodePool` that will periodically check if internal subscriptions are connected to the "best" (as defined by the `SelectionMode`) node and switch to it if necessary. Setting this value to `0s` will disable this feature.
From 4464dffc90686c05868f26f52d669ae8192aa18e Mon Sep 17 00:00:00 2001
From: Erik Burton
Date: Wed, 25 Oct 2023 11:05:09 -0700
Subject: [PATCH 011/327] [RE-2009] Bump action references (#11067)
* Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...3df4ab11eba7bda6032a0b82a6bb43b11571feac)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
* manual: Bump actions/checkout from 3 to 4
* manual: Bump actions/setup-node from 3 to 4
* manual: Bump aws-actions/amazon-ecr-login from 1 to 2
* manual: Bump aws-actions/configure-aws-credentials from 2 to 4
* fix: Solana Build Artifacts job
---------
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.../build-sign-publish-chainlink/action.yml | 2 +-
.github/actions/delete-deployments/action.yml | 4 +--
.github/actions/golangci-lint/action.yml | 2 +-
.../goreleaser-build-sign-publish/README.md | 4 +--
.github/actions/setup-nodejs/action.yaml | 4 +--
.github/actions/split-tests/action.yaml | 2 +-
.../workflows/automation-benchmark-tests.yml | 2 +-
.../workflows/automation-ondemand-tests.yml | 6 ++--
.github/workflows/build-publish-develop.yml | 2 +-
.github/workflows/build-publish.yml | 4 +--
.github/workflows/build.yml | 2 +-
.github/workflows/ci-chaincli.yml | 2 +-
.github/workflows/ci-core.yml | 14 ++++----
.github/workflows/codeql-analysis.yml | 2 +-
.github/workflows/delete-deployments.yml | 2 +-
.github/workflows/dependency-check.yml | 4 +--
.../goreleaser-build-publish-develop.yml | 8 ++---
.github/workflows/helm-publish.yml | 2 +-
.github/workflows/integration-chaos-tests.yml | 6 ++--
.../workflows/integration-staging-tests.yml | 2 +-
.../workflows/integration-tests-publish.yml | 2 +-
.github/workflows/integration-tests.yml | 32 ++++++++++---------
.github/workflows/lint-gh-workflows.yml | 2 +-
.github/workflows/on-demand-ocr-soak-test.yml | 2 +-
.../on-demand-vrfv2plus-performance-test.yml | 2 +-
.github/workflows/operator-ui-cd.yml | 4 +--
.github/workflows/operator-ui-ci.yml | 2 +-
.github/workflows/performance-tests.yml | 8 ++---
.github/workflows/solidity-foundry.yml | 4 +--
.github/workflows/solidity-hardhat.yml | 10 +++---
.github/workflows/solidity.yml | 12 +++----
...evelop-from-smartcontractkit-chainlink.yml | 2 +-
32 files changed, 80 insertions(+), 78 deletions(-)
diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml
index 853702045e..bd633bced7 100644
--- a/.github/actions/build-sign-publish-chainlink/action.yml
+++ b/.github/actions/build-sign-publish-chainlink/action.yml
@@ -99,7 +99,7 @@ runs:
- if: inputs.publish == 'true'
# Log in to AWS for publish to ECR
name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ inputs.aws-role-to-assume }}
role-duration-seconds: ${{ inputs.aws-role-duration-seconds }}
diff --git a/.github/actions/delete-deployments/action.yml b/.github/actions/delete-deployments/action.yml
index 20b7d0eefe..5fc7ef0287 100644
--- a/.github/actions/delete-deployments/action.yml
+++ b/.github/actions/delete-deployments/action.yml
@@ -29,11 +29,11 @@ inputs:
runs:
using: composite
steps:
- - uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd #v2.2.4
+ - uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd # v2.2.4
with:
version: ^8.0.0
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
with:
node-version: "18"
cache: "pnpm"
diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml
index 5c4882e268..c0aeb529c1 100644
--- a/.github/actions/golangci-lint/action.yml
+++ b/.github/actions/golangci-lint/action.yml
@@ -30,7 +30,7 @@ inputs:
runs:
using: composite
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go
uses: ./.github/actions/setup-go
with:
diff --git a/.github/actions/goreleaser-build-sign-publish/README.md b/.github/actions/goreleaser-build-sign-publish/README.md
index 49edfb25d5..d6bf7e6fd4 100644
--- a/.github/actions/goreleaser-build-sign-publish/README.md
+++ b/.github/actions/goreleaser-build-sign-publish/README.md
@@ -25,9 +25,9 @@ jobs:
MACOS_SDK_VERSION: 12.3
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Configure aws credentials
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ secrets.aws-role-arn }}
role-duration-seconds: ${{ secrets.aws-role-dur-sec }}
diff --git a/.github/actions/setup-nodejs/action.yaml b/.github/actions/setup-nodejs/action.yaml
index 4e1740032b..1bb529b421 100644
--- a/.github/actions/setup-nodejs/action.yaml
+++ b/.github/actions/setup-nodejs/action.yaml
@@ -7,11 +7,11 @@ description: Setup pnpm for contracts
runs:
using: composite
steps:
- - uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd #v2.2.4
+ - uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd # v2.2.4
with:
version: ^7.0.0
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
with:
node-version: "16"
cache: "pnpm"
diff --git a/.github/actions/split-tests/action.yaml b/.github/actions/split-tests/action.yaml
index fc96c4da25..684fd6a2bd 100644
--- a/.github/actions/split-tests/action.yaml
+++ b/.github/actions/split-tests/action.yaml
@@ -15,7 +15,7 @@ runs:
with:
version: ^7.0.0
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
with:
node-version: "16"
cache: "pnpm"
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index 3d7466faed..45491af026 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -97,7 +97,7 @@ jobs:
done
done <<< "$EVM_HTTP_URLS"
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ env.REF_NAME }}
- name: Build Test Image
diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml
index 032670c39a..20415b599e 100644
--- a/.github/workflows/automation-ondemand-tests.yml
+++ b/.github/workflows/automation-ondemand-tests.yml
@@ -53,7 +53,7 @@ jobs:
this-job-name: Build Chainlink Image ${{ matrix.image.name }}
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.head_ref || github.ref_name }}
- name: Check if image exists
@@ -98,7 +98,7 @@ jobs:
this-job-name: Build Test Image
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.head_ref || github.ref_name }}
- name: Build Test Image
@@ -149,7 +149,7 @@ jobs:
name: Automation On Demand ${{ matrix.tests.name }} Test
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.head_ref || github.ref_name }}
- name: Determine build to use
diff --git a/.github/workflows/build-publish-develop.yml b/.github/workflows/build-publish-develop.yml
index cba8edba3e..54ccaad581 100644
--- a/.github/workflows/build-publish-develop.yml
+++ b/.github/workflows/build-publish-develop.yml
@@ -31,7 +31,7 @@ jobs:
name: push-chainlink-develop ${{ matrix.image.name }}
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ env.GIT_REF }}
# When this is ran from manual workflow_dispatch, the github.sha may be
diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml
index 9aa7b9accc..5db70576b3 100644
--- a/.github/workflows/build-publish.yml
+++ b/.github/workflows/build-publish.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Check for VERSION file bump on tags
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
uses: ./.github/actions/version-file-bump
@@ -32,7 +32,7 @@ jobs:
contents: read
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Build, sign and publish chainlink image
uses: ./.github/actions/build-sign-publish-chainlink
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9931137d63..7cdf5e46b9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Build chainlink image
uses: ./.github/actions/build-sign-publish-chainlink
diff --git a/.github/workflows/ci-chaincli.yml b/.github/workflows/ci-chaincli.yml
index 97225e4655..fd58d08005 100644
--- a/.github/workflows/ci-chaincli.yml
+++ b/.github/workflows/ci-chaincli.yml
@@ -14,7 +14,7 @@ jobs:
name: chaincli-lint
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Golang Lint
uses: ./.github/actions/golangci-lint
with:
diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml
index 74ca1dae9a..7bc91da3ab 100644
--- a/.github/workflows/ci-core.yml
+++ b/.github/workflows/ci-core.yml
@@ -22,7 +22,7 @@ jobs:
name: lint
runs-on: ubuntu20.04-8cores-32GB
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Golang Lint
uses: ./.github/actions/golangci-lint
with:
@@ -40,9 +40,9 @@ jobs:
CL_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node
- uses: actions/setup-node@v3
+ uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
with:
@@ -126,9 +126,9 @@ jobs:
CL_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node
- uses: actions/setup-node@v3
+ uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
with:
@@ -183,7 +183,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0 # fetches all history for all tags and branches to provide more metadata for sonar reports
- name: Download all workflow run artifacts
@@ -227,7 +227,7 @@ jobs:
run: |
echo "## \`skip-smoke-tests\` label is active, skipping E2E smoke tests" >>$GITHUB_STEP_SUMMARY
exit 0
- - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
- name: Setup Go
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 86f2515e26..822bf259f9 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Go
if: ${{ matrix.language == 'go' }}
diff --git a/.github/workflows/delete-deployments.yml b/.github/workflows/delete-deployments.yml
index a3d3100516..3ec5fb35c9 100644
--- a/.github/workflows/delete-deployments.yml
+++ b/.github/workflows/delete-deployments.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
- uses: actions/checkout@v4
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Clean up integration environment
uses: ./.github/actions/delete-deployments
diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml
index ebfe1b947a..42729a8cf1 100644
--- a/.github/workflows/dependency-check.yml
+++ b/.github/workflows/dependency-check.yml
@@ -11,7 +11,7 @@ jobs:
changes: ${{ steps.changes.outputs.src }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
@@ -25,7 +25,7 @@ jobs:
needs: [changes]
steps:
- name: Check out code
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Go
if: needs.changes.outputs.src == 'true'
diff --git a/.github/workflows/goreleaser-build-publish-develop.yml b/.github/workflows/goreleaser-build-publish-develop.yml
index 9e9b088033..1edfdedd70 100644
--- a/.github/workflows/goreleaser-build-publish-develop.yml
+++ b/.github/workflows/goreleaser-build-publish-develop.yml
@@ -18,9 +18,9 @@ jobs:
contents: read
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Configure aws credentials
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }}
role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }}
@@ -55,9 +55,9 @@ jobs:
contents: read
steps:
- name: Checkout repository
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Configure aws credentials
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN_GATI }}
role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }}
diff --git a/.github/workflows/helm-publish.yml b/.github/workflows/helm-publish.yml
index e80d758d81..48a7060fc7 100644
--- a/.github/workflows/helm-publish.yml
+++ b/.github/workflows/helm-publish.yml
@@ -12,7 +12,7 @@ jobs:
contents: read
steps:
- name: Checkout repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Configure aws credentials
uses: aws-actions/configure-aws-credentials@50ac8dd1e1b10d09dac7b8727528b91bed831ac0 # v3.0.2
diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml
index a9aa2c35df..503e5ec58a 100644
--- a/.github/workflows/integration-chaos-tests.yml
+++ b/.github/workflows/integration-chaos-tests.yml
@@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Check if image exists
id: check-image
uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
@@ -69,7 +69,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Build Test Image
uses: ./.github/actions/build-test-image
with:
@@ -107,7 +107,7 @@ jobs:
test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run Tests
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
with:
diff --git a/.github/workflows/integration-staging-tests.yml b/.github/workflows/integration-staging-tests.yml
index a6fda178d5..2abb9a3cfa 100644
--- a/.github/workflows/integration-staging-tests.yml
+++ b/.github/workflows/integration-staging-tests.yml
@@ -50,7 +50,7 @@ jobs:
WASP_LOG_LEVEL: info
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
- name: Run E2E soak tests
diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml
index c71b83d1c4..06f7bb1b81 100644
--- a/.github/workflows/integration-tests-publish.yml
+++ b/.github/workflows/integration-tests-publish.yml
@@ -27,7 +27,7 @@ jobs:
this-job-name: Publish Integration Test Image
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Build Image
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index aadb14f128..edd7755e8b 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
@@ -81,7 +81,7 @@ jobs:
this-job-name: Build Chainlink Image ${{ matrix.image.name }}
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Check if image exists
@@ -129,7 +129,7 @@ jobs:
this-job-name: Build Test Image
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Build Test Image
@@ -153,7 +153,7 @@ jobs:
echo "## \`skip-smoke-tests\` label is active, skipping E2E smoke tests" >>$GITHUB_STEP_SUMMARY
exit 0
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Compare Test Lists
run: |
cd ./integration-tests
@@ -190,7 +190,7 @@ jobs:
name: ETH Smoke Tests ${{ matrix.product.name }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Build Go Test Command
@@ -303,7 +303,7 @@ jobs:
name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Build Go Test Command
@@ -484,7 +484,7 @@ jobs:
steps:
- name: Checkout repo
if: ${{ github.event_name == 'pull_request' }}
- uses: actions/checkout@v4
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: 🧼 Clean up Environment
if: ${{ github.event_name == 'pull_request' }}
@@ -513,7 +513,7 @@ jobs:
continue-on-error: true
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Run Setup
@@ -552,7 +552,7 @@ jobs:
TEST_SUITE: migration
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Get Latest Version
@@ -608,7 +608,7 @@ jobs:
sha: ${{ steps.getsha.outputs.sha }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Get the sha from go mod
@@ -619,7 +619,7 @@ jobs:
echo "short sha is: ${short_sha}"
echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT"
- name: Checkout solana
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: smartcontractkit/chainlink-solana
ref: develop
@@ -642,7 +642,7 @@ jobs:
projectserum_version: ${{ steps.psversion.outputs.projectserum_version }}
steps:
- name: Checkout the solana repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: smartcontractkit/chainlink-solana
ref: ${{ needs.get_solana_sha.outputs.sha }}
@@ -704,6 +704,8 @@ jobs:
this-job-name: Solana Build Artifacts
continue-on-error: true
- name: Checkout the solana repo
+ # Use v3.6.0 because the custom runner (container configured above)
+ # doesn't have node20 installed which is required for versions >=4
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
with:
repository: smartcontractkit/chainlink-solana
@@ -744,7 +746,7 @@ jobs:
continue-on-error: true
- name: Checkout the repo
if: needs.changes.outputs.src == 'true' && needs.solana-test-image-exists.outputs.exists == 'false'
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: smartcontractkit/chainlink-solana
ref: 23816fcf7d380a30c87b6d87e4fb0ca94419b259 # swtich back to this after the next solana release${{ needs.get_solana_sha.outputs.sha }}
@@ -802,7 +804,7 @@ jobs:
test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
continue-on-error: true
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: smartcontractkit/chainlink-solana
ref: ${{ needs.get_solana_sha.outputs.sha }}
@@ -915,7 +917,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
## Only run OCR smoke test for now
diff --git a/.github/workflows/lint-gh-workflows.yml b/.github/workflows/lint-gh-workflows.yml
index 1220f3a745..8facdc038c 100644
--- a/.github/workflows/lint-gh-workflows.yml
+++ b/.github/workflows/lint-gh-workflows.yml
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out Code
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run actionlint
uses: reviewdog/action-actionlint@82693e9e3b239f213108d6e412506f8b54003586 # v1.39.1
- name: Collect Metrics
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index cd14114226..7dc144264d 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -110,7 +110,7 @@ jobs:
echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV
echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ env.REF_NAME }}
- name: Setup Push Tag
diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
index b33c6f8313..41b6618ba6 100644
--- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml
+++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
@@ -114,7 +114,7 @@ jobs:
echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
- name: Run Tests
diff --git a/.github/workflows/operator-ui-cd.yml b/.github/workflows/operator-ui-cd.yml
index 4f6e82e07b..36a9d8b715 100644
--- a/.github/workflows/operator-ui-cd.yml
+++ b/.github/workflows/operator-ui-cd.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Update version
id: update
@@ -25,7 +25,7 @@ jobs:
run: ./operator_ui/check.sh
- name: Assume role capable of dispatching action
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ secrets.AWS_OIDC_CHAINLINK_CI_AUTO_PR_TOKEN_ISSUER_ROLE_ARN }}
role-duration-seconds: ${{ secrets.aws-role-duration-seconds }}
diff --git a/.github/workflows/operator-ui-ci.yml b/.github/workflows/operator-ui-ci.yml
index 8ced3b222c..2ce85bc132 100644
--- a/.github/workflows/operator-ui-ci.yml
+++ b/.github/workflows/operator-ui-ci.yml
@@ -23,7 +23,7 @@ jobs:
continue-on-error: true
- name: Assume role capable of dispatching action
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ secrets.AWS_OIDC_CHAINLINK_CI_OPERATOR_UI_ACCESS_TOKEN_ISSUER_ROLE_ARN }}
role-duration-seconds: 3600
diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml
index b79d8dfea2..43ed80cb3f 100644
--- a/.github/workflows/performance-tests.yml
+++ b/.github/workflows/performance-tests.yml
@@ -18,16 +18,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
aws-region: ${{ secrets.QA_AWS_REGION }}
role-to-assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
role-duration-seconds: 3600
- name: Login to Amazon ECR
id: login-ecr
- uses: aws-actions/amazon-ecr-login@v1
+ uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@ecf95283f03858871ff00b787d79c419715afc34 # v2.7.0
- name: Build and Push
@@ -55,7 +55,7 @@ jobs:
needs: build-chainlink
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run Tests
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
with:
diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml
index 590165c8e7..f6c515b5b8 100644
--- a/.github/workflows/solidity-foundry.yml
+++ b/.github/workflows/solidity-foundry.yml
@@ -12,7 +12,7 @@ jobs:
changes: ${{ steps.changes.outputs.src }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
@@ -41,7 +41,7 @@ jobs:
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: recursive
diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml
index 334ce4d1ba..6e7de2eba1 100644
--- a/.github/workflows/solidity-hardhat.yml
+++ b/.github/workflows/solidity-hardhat.yml
@@ -19,7 +19,7 @@ jobs:
changes: ${{ steps.changes.outputs.src }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
@@ -40,7 +40,7 @@ jobs:
splits: ${{ steps.split.outputs.splits }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Generate splits
id: split
uses: ./.github/actions/split-tests
@@ -66,7 +66,7 @@ jobs:
runs-on: ubuntu20.04-4cores-16GB
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
- name: Setup Hardhat
@@ -104,7 +104,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
- name: Make coverage directory
@@ -131,7 +131,7 @@ jobs:
runs-on: ubuntu20.04-4cores-16GB
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
- name: Setup Hardhat
diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml
index b2537a5c9a..f46b13191d 100644
--- a/.github/workflows/solidity.yml
+++ b/.github/workflows/solidity.yml
@@ -16,7 +16,7 @@ jobs:
changes: ${{ steps.changes.outputs.src }}
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
@@ -32,7 +32,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
- name: Run Prepublish test
@@ -54,9 +54,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Checkout diff-so-fancy
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: so-fancy/diff-so-fancy
ref: a673cb4d2707f64d92b86498a2f5f71c8e2643d5 # v1.4.3
@@ -101,7 +101,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
uses: ./.github/actions/setup-nodejs
- name: Run pnpm lint
@@ -126,7 +126,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
if: needs.changes.outputs.changes == 'true'
uses: ./.github/actions/setup-nodejs
diff --git a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml
index 9703765203..7fe9ffd526 100644
--- a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml
+++ b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml
@@ -10,7 +10,7 @@ jobs:
name: Sync
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: develop
if: env.GITHUB_REPOSITORY != 'smartcontractkit/chainlink'
From 45b59578f369f221465dea339d368bd3beec175c Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Thu, 26 Oct 2023 06:11:53 -0500
Subject: [PATCH 012/327] .github/workflows: add slack notification to nightly
golangci-lint (#11088)
---
.github/workflows/ci-core.yml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml
index 7bc91da3ab..4037dc0cd9 100644
--- a/.github/workflows/ci-core.yml
+++ b/.github/workflows/ci-core.yml
@@ -28,6 +28,14 @@ jobs:
with:
gc-basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
gc-host: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ - name: Notify Slack
+ if: ${{ failure() && github.event.schedule != '' }}
+ uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
+ env:
+ SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
+ with:
+ channel-id: "#team-core"
+ slack-message: "golangci-lint failed: ${{ job.html_url }}\n${{ format('https://github.com/smartcontractkit/chainlink/actions/runs/{0}', github.run_id) }}"
core:
strategy:
From b31284ba5a12c7b675bd942cc8f4b2598232f5a7 Mon Sep 17 00:00:00 2001
From: Francisco de Borja Aranda Castillejo
Date: Thu, 26 Oct 2023 15:26:50 +0200
Subject: [PATCH 013/327] make maxCheck and maxPerform configurable (#11083)
* Make maxCheck and maxPerform configurable
- maxCheck and maxPerform can be configured.
- Values for these have to be provided in the constructor.
- Adhere to Solidity Style Guide in imports, varnames, etc.
* add tests
* add custom errors on require methods
* add proposed fixes
* make LINK_TOKEN private
---
.../upkeeps/LinkAvailableBalanceMonitor.sol | 240 ++++----
.../contracts/utils/structs/EnumerableMap.sol | 530 ++++++++++++++++++
.../LinkAvailableBalanceMonitor.test.ts | 15 +-
3 files changed, 659 insertions(+), 126 deletions(-)
create mode 100644 contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol
diff --git a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
index cff09aaebb..028579397a 100644
--- a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
+++ b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
@@ -2,11 +2,11 @@
pragma solidity 0.8.6;
-import "../../shared/access/ConfirmedOwner.sol";
-import "../interfaces/KeeperCompatibleInterface.sol";
-import "../../vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol";
-import "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
-import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol";
+import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol";
+import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
+import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol";
+import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
+import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol";
interface IAggregatorProxy {
function aggregator() external view returns (address);
@@ -16,60 +16,63 @@ interface ILinkAvailable {
function linkAvailableForPayment() external view returns (int256 availableBalance);
}
-/**
- * @title The LinkAvailableBalanceMonitor contract.
- * @notice A keeper-compatible contract that monitors target contracts for balance from a custom
- * function linkAvailableForPayment() and funds them with LINK if it falls below a defined
- * threshold. Also supports aggregator proxy contracts monitoring which require fetching the actual
- * target contract through a predefined interface.
- * @dev with 30 addresses as the MAX_PERFORM, the measured max gas usage of performUpkeep is around 2M
- * therefore, we recommend an upkeep gas limit of 3M (this has a 33% margin of safety). Although, nothing
- * prevents us from using 5M gas and increasing MAX_PERFORM, 30 seems like a reasonable batch size that
- * is probably plenty for most needs.
- * @dev with 130 addresses as the MAX_CHECK, the measured max gas usage of checkUpkeep is around 3.5M,
- * which is 30% below the 5M limit.
- * Note that testing conditions DO NOT match live chain gas usage, hence the margins. Change
- * at your own risk!!!
- * @dev some areas for improvement / acknowledgement of limitations:
- * * validate that all addresses conform to interface when adding them to the watchlist
- * * this is a "trusless" upkeep, meaning it does not trust the caller of performUpkeep;
- we could save a fair amount of gas and re-write this upkeep for use with Automation v2.0+,
- which has significantly different trust assumptions
- */
-contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface {
+/// @title The LinkAvailableBalanceMonitor contract.
+/// @notice A keeper-compatible contract that monitors target contracts for balance from a custom
+/// function linkAvailableForPayment() and funds them with LINK if it falls below a defined
+/// threshold. Also supports aggregator proxy contracts monitoring which require fetching the actual
+/// target contract through a predefined interface.
+/// @dev with 30 addresses as the s_maxPerform, the measured max gas usage of performUpkeep is around 2M
+/// therefore, we recommend an upkeep gas limit of 3M (this has a 33% margin of safety). Although, nothing
+/// prevents us from using 5M gas and increasing s_maxPerform, 30 seems like a reasonable batch size that
+/// is probably plenty for most needs.
+/// @dev with 130 addresses as the s_maxCheck, the measured max gas usage of checkUpkeep is around 3.5M,
+/// which is 30% below the 5M limit.
+/// Note that testing conditions DO NOT match live chain gas usage, hence the margins. Change
+/// at your own risk!!!
+/// @dev some areas for improvement / acknowledgement of limitations:
+/// validate that all addresses conform to interface when adding them to the watchlist
+/// this is a "trusless" upkeep, meaning it does not trust the caller of performUpkeep;
+/// we could save a fair amount of gas and re-write this upkeep for use with Automation v2.0+,
+/// which has significantly different trust assumptions
+contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationCompatibleInterface {
using EnumerableMap for EnumerableMap.AddressToUintMap;
event FundsWithdrawn(uint256 amountWithdrawn, address payee);
event TopUpSucceeded(address indexed topUpAddress);
event TopUpBlocked(address indexed topUpAddress);
event WatchlistUpdated();
+ event MaxPerformUpdated(uint256 oldMaxPerform, uint256 newMaxPerform);
+ event MaxCheckUpdated(uint256 oldMaxCheck, uint256 newMaxCheck);
error InvalidWatchList();
error DuplicateAddress(address duplicate);
- uint256 public constant MAX_PERFORM = 5; // max number to addresses to top up in a single batch
- uint256 public constant MAX_CHECK = 20; // max number of upkeeps to check (need to fit in 5M gas limit)
- IERC20 public immutable LINK_TOKEN;
-
+ IERC20 private immutable LINK_TOKEN;
EnumerableMap.AddressToUintMap private s_watchList;
uint256 private s_topUpAmount;
+ uint32 private s_minWaitPeriodSeconds;
+ uint16 private s_maxPerform;
+ uint16 private s_maxCheck;
- /**
- * @param linkTokenAddress the LINK token address
- * @param topUpAmount the amount of LINK to top up an aggregator with at once
- */
- constructor(address linkTokenAddress, uint256 topUpAmount) ConfirmedOwner(msg.sender) {
- require(linkTokenAddress != address(0));
- require(topUpAmount > 0);
+ /// @param linkTokenAddress the LINK token address
+ /// @param topUpAmount the amount of LINK to top up an aggregator with at once
+ constructor(
+ address linkTokenAddress,
+ uint256 topUpAmount,
+ uint16 maxPerform,
+ uint16 maxCheck
+ ) ConfirmedOwner(msg.sender) {
+ require(linkTokenAddress != address(0), "LinkAvailableBalanceMonitor: invalid linkTokenAddress");
+ require(topUpAmount > 0, "LinkAvailableBalanceMonitor: invalid topUpAmount");
LINK_TOKEN = IERC20(linkTokenAddress);
s_topUpAmount = topUpAmount;
+ s_maxPerform = maxPerform;
+ s_maxCheck = maxCheck;
}
- /**
- * @notice Sets the list of subscriptions to watch and their funding parameters
- * @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy)
- * @param minBalances the list of corresponding minBalance for the target address
- */
+ /// @notice Sets the list of subscriptions to watch and their funding parameters
+ /// @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy)
+ /// @param minBalances the list of corresponding minBalance for the target address
function setWatchList(address[] calldata addresses, uint256[] calldata minBalances) external onlyOwner {
if (addresses.length != minBalances.length) {
revert InvalidWatchList();
@@ -77,7 +80,7 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
// first, remove all existing addresses from list
for (uint256 idx = s_watchList.length(); idx > 0; idx--) {
(address target, ) = s_watchList.at(idx - 1);
- require(s_watchList.remove(target));
+ require(s_watchList.remove(target), "LinkAvailableBalanceMonitor: unable to setWatchlist");
}
// then set new addresses
for (uint256 idx = 0; idx < addresses.length; idx++) {
@@ -92,11 +95,9 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
emit WatchlistUpdated();
}
- /**
- * @notice Adds addresses to the watchlist without overwriting existing members
- * @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy)
- * @param minBalances the list of corresponding minBalance for the target address
- */
+ /// @notice Adds addresses to the watchlist without overwriting existing members
+ /// @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy)
+ /// @param minBalances the list of corresponding minBalance for the target address
function addToWatchList(address[] calldata addresses, uint256[] calldata minBalances) external onlyOwner {
if (addresses.length != minBalances.length) {
revert InvalidWatchList();
@@ -113,10 +114,8 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
emit WatchlistUpdated();
}
- /**
- * @notice Removes addresses from the watchlist
- * @param addresses the list of target addresses to remove from the watchlist
- */
+ /// @notice Removes addresses from the watchlist
+ /// @param addresses the list of target addresses to remove from the watchlist
function removeFromWatchlist(address[] calldata addresses) external onlyOwner {
for (uint256 idx = 0; idx < addresses.length; idx++) {
if (!s_watchList.contains(addresses[idx])) {
@@ -127,33 +126,36 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
emit WatchlistUpdated();
}
- /**
- * @notice Gets a list of proxies that are underfunded, up to the MAX_PERFORM size
- * @dev the function starts at a random index in the list to avoid biasing the first
- * addresses in the list over latter ones.
- * @dev the function will check at most MAX_CHECK proxies in a single call
- * @dev the function returns a list with a max length of MAX_PERFORM
- * @return list of target addresses which are underfunded
- */
+ /// @notice Gets a list of proxies that are underfunded, up to the s_maxPerform size
+ /// @dev the function starts at a random index in the list to avoid biasing the first
+ /// addresses in the list over latter ones.
+ /// @dev the function will check at most s_maxCheck proxies in a single call
+ /// @dev the function returns a list with a max length of s_maxPerform
+ /// @return list of target addresses which are underfunded
function sampleUnderfundedAddresses() public view returns (address[] memory) {
+ uint16 maxPerform = s_maxPerform;
+ uint16 maxCheck = s_maxCheck;
uint256 numTargets = s_watchList.length();
- uint256 numChecked = 0;
uint256 idx = uint256(blockhash(block.number - 1)) % numTargets; // start at random index, to distribute load
- uint256 numToCheck = numTargets < MAX_CHECK ? numTargets : MAX_CHECK;
+ uint256 numToCheck = numTargets < maxCheck ? numTargets : maxCheck;
uint256 numFound = 0;
- address[] memory targetsToFund = new address[](MAX_PERFORM);
- for (; numChecked < numToCheck; (idx, numChecked) = ((idx + 1) % numTargets, numChecked + 1)) {
+ address[] memory targetsToFund = new address[](maxPerform);
+ for (
+ uint256 numChecked = 0;
+ numChecked < numToCheck;
+ (idx, numChecked) = ((idx + 1) % numTargets, numChecked + 1)
+ ) {
(address target, uint256 minBalance) = s_watchList.at(idx);
(bool needsFunding, ) = _needsFunding(target, minBalance);
if (needsFunding) {
targetsToFund[numFound] = target;
numFound++;
- if (numFound == MAX_PERFORM) {
+ if (numFound == maxPerform) {
break; // max number of addresses in batch reached
}
}
}
- if (numFound != MAX_PERFORM) {
+ if (numFound != maxPerform) {
assembly {
mstore(targetsToFund, numFound) // resize array to number of valid targets
}
@@ -161,10 +163,8 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
return targetsToFund;
}
- /**
- * @notice Send funds to the targets provided.
- * @param targetAddresses the list of targets to fund
- */
+ /// @notice Send funds to the targets provided.
+ /// @param targetAddresses the list of targets to fund
function topUp(address[] memory targetAddresses) public whenNotPaused {
uint256 topUpAmount = s_topUpAmount;
uint256 stopIdx = targetAddresses.length;
@@ -186,11 +186,9 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
}
}
- /**
- * @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload.
- * @return upkeepNeeded signals if upkeep is needed
- * @return performData is an abi encoded list of subscription ids that need funds
- */
+ /// @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload.
+ /// @return upkeepNeeded signals if upkeep is needed
+ /// @return performData is an abi encoded list of subscription ids that need funds
function checkUpkeep(
bytes calldata
) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) {
@@ -206,39 +204,31 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
return (upkeepNeeded, performData);
}
- /**
- * @notice Called by the keeper to send funds to underfunded addresses.
- * @param performData the abi encoded list of addresses to fund
- */
+ /// @notice Called by the keeper to send funds to underfunded addresses.
+ /// @param performData the abi encoded list of addresses to fund
function performUpkeep(bytes calldata performData) external override {
address[] memory needsFunding = abi.decode(performData, (address[]));
topUp(needsFunding);
}
- /**
- * @notice Withdraws the contract balance in the LINK token.
- * @param amount the amount of the LINK to withdraw
- * @param payee the address to pay
- */
+ /// @notice Withdraws the contract balance in the LINK token.
+ /// @param amount the amount of the LINK to withdraw
+ /// @param payee the address to pay
function withdraw(uint256 amount, address payable payee) external onlyOwner {
- require(payee != address(0));
+ require(payee != address(0), "LinkAvailableBalanceMonitor: invalid payee address");
LINK_TOKEN.transfer(payee, amount);
emit FundsWithdrawn(amount, payee);
}
- /**
- * @notice Sets the top up amount
- */
+ /// @notice Sets the top up amount
function setTopUpAmount(uint256 topUpAmount) external onlyOwner returns (uint256) {
- require(topUpAmount > 0);
+ require(topUpAmount > 0, "LinkAvailableBalanceMonitor: invalid linkTokenAddress");
return s_topUpAmount = topUpAmount;
}
- /**
- * @notice Sets the minimum balance for the given target address
- */
+ /// @notice Sets the minimum balance for the given target address
function setMinBalance(address target, uint256 minBalance) external onlyOwner returns (uint256) {
- require(minBalance > 0);
+ require(minBalance > 0, "LinkAvailableBalanceMonitor: invalid minBalance");
(bool exists, uint256 prevMinBalance) = s_watchList.tryGet(target);
if (!exists) {
revert InvalidWatchList();
@@ -247,23 +237,29 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
return prevMinBalance;
}
- /**
- * @notice Pause the contract, which prevents executing performUpkeep
- */
- function pause() external onlyOwner {
- _pause();
+ /// @notice Update s_maxPerform
+ function setMaxPerform(uint16 maxPerform) external onlyOwner {
+ emit MaxPerformUpdated(s_maxPerform, maxPerform);
+ s_maxPerform = maxPerform;
}
- /**
- * @notice Unpause the contract
- */
- function unpause() external onlyOwner {
- _unpause();
+ /// @notice Update s_maxCheck
+ function setMaxCheck(uint16 maxCheck) external onlyOwner {
+ emit MaxCheckUpdated(s_maxCheck, maxCheck);
+ s_maxCheck = maxCheck;
+ }
+
+ /// @notice Gets maxPerform
+ function getMaxPerform() external view returns (uint16) {
+ return s_maxPerform;
+ }
+
+ /// @notice Gets maxCheck
+ function getMaxCheck() external view returns (uint16) {
+ return s_maxCheck;
}
- /**
- * @notice Gets the list of subscription ids being watched
- */
+ /// @notice Gets the list of subscription ids being watched
function getWatchList() external view returns (address[] memory, uint256[] memory) {
uint256 len = s_watchList.length();
address[] memory targets = new address[](len);
@@ -276,16 +272,12 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
return (targets, minBalances);
}
- /**
- * @notice Gets the configured top up amount
- */
+ /// @notice Gets the configured top up amount
function getTopUpAmount() external view returns (uint256) {
return s_topUpAmount;
}
- /**
- * @notice Gets the configured minimum balance for the given target
- */
+ /// @notice Gets the configured minimum balance for the given target
function getMinBalance(address target) external view returns (uint256) {
(bool exists, uint256 minBalance) = s_watchList.tryGet(target);
if (!exists) {
@@ -294,14 +286,22 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatib
return minBalance;
}
- /**
- * @notice checks the target (could be direct target or IAggregatorProxy), and determines
- * if it is elligible for funding
- * @param targetAddress the target to check
- * @param minBalance minimum balance required for the target
- * @return bool whether the target needs funding or not
- * @return address the address of the contract needing funding
- */
+ /// @notice Pause the contract, which prevents executing performUpkeep
+ function pause() external onlyOwner {
+ _pause();
+ }
+
+ /// @notice Unpause the contract
+ function unpause() external onlyOwner {
+ _unpause();
+ }
+
+ /// @notice checks the target (could be direct target or IAggregatorProxy), and determines
+ /// if it is elligible for funding
+ /// @param targetAddress the target to check
+ /// @param minBalance minimum balance required for the target
+ /// @return bool whether the target needs funding or not
+ /// @return address the address of the contract needing funding
function _needsFunding(address targetAddress, uint256 minBalance) private view returns (bool, address) {
ILinkAvailable target;
IAggregatorProxy proxy = IAggregatorProxy(targetAddress);
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol
new file mode 100644
index 0000000000..7f4e9115b1
--- /dev/null
+++ b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableMap.sol)
+// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
+
+pragma solidity ^0.8.0;
+
+import "./EnumerableSet.sol";
+
+/**
+ * @dev Library for managing an enumerable variant of Solidity's
+ * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
+ * type.
+ *
+ * Maps have the following properties:
+ *
+ * - Entries are added, removed, and checked for existence in constant time
+ * (O(1)).
+ * - Entries are enumerated in O(n). No guarantees are made on the ordering.
+ *
+ * ```
+ * contract Example {
+ * // Add the library methods
+ * using EnumerableMap for EnumerableMap.UintToAddressMap;
+ *
+ * // Declare a set state variable
+ * EnumerableMap.UintToAddressMap private myMap;
+ * }
+ * ```
+ *
+ * The following map types are supported:
+ *
+ * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
+ * - `address -> uint256` (`AddressToUintMap`) since v4.6.0
+ * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0
+ * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
+ * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
+ *
+ * [WARNING]
+ * ====
+ * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
+ * unusable.
+ * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
+ *
+ * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
+ * array of EnumerableMap.
+ * ====
+ */
+library EnumerableMap {
+ using EnumerableSet for EnumerableSet.Bytes32Set;
+
+ // To implement this library for multiple types with as little code
+ // repetition as possible, we write it in terms of a generic Map type with
+ // bytes32 keys and values.
+ // The Map implementation uses private functions, and user-facing
+ // implementations (such as Uint256ToAddressMap) are just wrappers around
+ // the underlying Map.
+ // This means that we can only create new EnumerableMaps for types that fit
+ // in bytes32.
+
+ struct Bytes32ToBytes32Map {
+ // Storage of keys
+ EnumerableSet.Bytes32Set _keys;
+ mapping(bytes32 => bytes32) _values;
+ }
+
+ /**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+ function set(
+ Bytes32ToBytes32Map storage map,
+ bytes32 key,
+ bytes32 value
+ ) internal returns (bool) {
+ map._values[key] = value;
+ return map._keys.add(key);
+ }
+
+ /**
+ * @dev Removes a key-value pair from a map. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
+ delete map._values[key];
+ return map._keys.remove(key);
+ }
+
+ /**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
+ return map._keys.contains(key);
+ }
+
+ /**
+ * @dev Returns the number of key-value pairs in the map. O(1).
+ */
+ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
+ return map._keys.length();
+ }
+
+ /**
+ * @dev Returns the key-value pair stored at position `index` in the map. O(1).
+ *
+ * Note that there are no guarantees on the ordering of entries inside the
+ * array, and it may change when more entries are added or removed.
+ *
+ * Requirements:
+ *
+ * - `index` must be strictly less than {length}.
+ */
+ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
+ bytes32 key = map._keys.at(index);
+ return (key, map._values[key]);
+ }
+
+ /**
+ * @dev Tries to returns the value associated with `key`. O(1).
+ * Does not revert if `key` is not in the map.
+ */
+ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
+ bytes32 value = map._values[key];
+ if (value == bytes32(0)) {
+ return (contains(map, key), bytes32(0));
+ } else {
+ return (true, value);
+ }
+ }
+
+ /**
+ * @dev Returns the value associated with `key`. O(1).
+ *
+ * Requirements:
+ *
+ * - `key` must be in the map.
+ */
+ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
+ bytes32 value = map._values[key];
+ require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
+ return value;
+ }
+
+ /**
+ * @dev Same as {get}, with a custom error message when `key` is not in the map.
+ *
+ * CAUTION: This function is deprecated because it requires allocating memory for the error
+ * message unnecessarily. For custom revert reasons use {tryGet}.
+ */
+ function get(
+ Bytes32ToBytes32Map storage map,
+ bytes32 key,
+ string memory errorMessage
+ ) internal view returns (bytes32) {
+ bytes32 value = map._values[key];
+ require(value != 0 || contains(map, key), errorMessage);
+ return value;
+ }
+
+ // UintToUintMap
+
+ struct UintToUintMap {
+ Bytes32ToBytes32Map _inner;
+ }
+
+ /**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+ function set(
+ UintToUintMap storage map,
+ uint256 key,
+ uint256 value
+ ) internal returns (bool) {
+ return set(map._inner, bytes32(key), bytes32(value));
+ }
+
+ /**
+ * @dev Removes a value from a set. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
+ return remove(map._inner, bytes32(key));
+ }
+
+ /**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
+ return contains(map._inner, bytes32(key));
+ }
+
+ /**
+ * @dev Returns the number of elements in the map. O(1).
+ */
+ function length(UintToUintMap storage map) internal view returns (uint256) {
+ return length(map._inner);
+ }
+
+ /**
+ * @dev Returns the element stored at position `index` in the set. O(1).
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - `index` must be strictly less than {length}.
+ */
+ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
+ (bytes32 key, bytes32 value) = at(map._inner, index);
+ return (uint256(key), uint256(value));
+ }
+
+ /**
+ * @dev Tries to returns the value associated with `key`. O(1).
+ * Does not revert if `key` is not in the map.
+ */
+ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
+ (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
+ return (success, uint256(value));
+ }
+
+ /**
+ * @dev Returns the value associated with `key`. O(1).
+ *
+ * Requirements:
+ *
+ * - `key` must be in the map.
+ */
+ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
+ return uint256(get(map._inner, bytes32(key)));
+ }
+
+ /**
+ * @dev Same as {get}, with a custom error message when `key` is not in the map.
+ *
+ * CAUTION: This function is deprecated because it requires allocating memory for the error
+ * message unnecessarily. For custom revert reasons use {tryGet}.
+ */
+ function get(
+ UintToUintMap storage map,
+ uint256 key,
+ string memory errorMessage
+ ) internal view returns (uint256) {
+ return uint256(get(map._inner, bytes32(key), errorMessage));
+ }
+
+ // UintToAddressMap
+
+ struct UintToAddressMap {
+ Bytes32ToBytes32Map _inner;
+ }
+
+ /**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+ function set(
+ UintToAddressMap storage map,
+ uint256 key,
+ address value
+ ) internal returns (bool) {
+ return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
+ }
+
+ /**
+ * @dev Removes a value from a set. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
+ return remove(map._inner, bytes32(key));
+ }
+
+ /**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
+ return contains(map._inner, bytes32(key));
+ }
+
+ /**
+ * @dev Returns the number of elements in the map. O(1).
+ */
+ function length(UintToAddressMap storage map) internal view returns (uint256) {
+ return length(map._inner);
+ }
+
+ /**
+ * @dev Returns the element stored at position `index` in the set. O(1).
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - `index` must be strictly less than {length}.
+ */
+ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
+ (bytes32 key, bytes32 value) = at(map._inner, index);
+ return (uint256(key), address(uint160(uint256(value))));
+ }
+
+ /**
+ * @dev Tries to returns the value associated with `key`. O(1).
+ * Does not revert if `key` is not in the map.
+ */
+ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
+ (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
+ return (success, address(uint160(uint256(value))));
+ }
+
+ /**
+ * @dev Returns the value associated with `key`. O(1).
+ *
+ * Requirements:
+ *
+ * - `key` must be in the map.
+ */
+ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
+ return address(uint160(uint256(get(map._inner, bytes32(key)))));
+ }
+
+ /**
+ * @dev Same as {get}, with a custom error message when `key` is not in the map.
+ *
+ * CAUTION: This function is deprecated because it requires allocating memory for the error
+ * message unnecessarily. For custom revert reasons use {tryGet}.
+ */
+ function get(
+ UintToAddressMap storage map,
+ uint256 key,
+ string memory errorMessage
+ ) internal view returns (address) {
+ return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
+ }
+
+ // AddressToUintMap
+
+ struct AddressToUintMap {
+ Bytes32ToBytes32Map _inner;
+ }
+
+ /**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+ function set(
+ AddressToUintMap storage map,
+ address key,
+ uint256 value
+ ) internal returns (bool) {
+ return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
+ }
+
+ /**
+ * @dev Removes a value from a set. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+ function remove(AddressToUintMap storage map, address key) internal returns (bool) {
+ return remove(map._inner, bytes32(uint256(uint160(key))));
+ }
+
+ /**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+ function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
+ return contains(map._inner, bytes32(uint256(uint160(key))));
+ }
+
+ /**
+ * @dev Returns the number of elements in the map. O(1).
+ */
+ function length(AddressToUintMap storage map) internal view returns (uint256) {
+ return length(map._inner);
+ }
+
+ /**
+ * @dev Returns the element stored at position `index` in the set. O(1).
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - `index` must be strictly less than {length}.
+ */
+ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
+ (bytes32 key, bytes32 value) = at(map._inner, index);
+ return (address(uint160(uint256(key))), uint256(value));
+ }
+
+ /**
+ * @dev Tries to returns the value associated with `key`. O(1).
+ * Does not revert if `key` is not in the map.
+ */
+ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
+ (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
+ return (success, uint256(value));
+ }
+
+ /**
+ * @dev Returns the value associated with `key`. O(1).
+ *
+ * Requirements:
+ *
+ * - `key` must be in the map.
+ */
+ function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
+ return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
+ }
+
+ /**
+ * @dev Same as {get}, with a custom error message when `key` is not in the map.
+ *
+ * CAUTION: This function is deprecated because it requires allocating memory for the error
+ * message unnecessarily. For custom revert reasons use {tryGet}.
+ */
+ function get(
+ AddressToUintMap storage map,
+ address key,
+ string memory errorMessage
+ ) internal view returns (uint256) {
+ return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
+ }
+
+ // Bytes32ToUintMap
+
+ struct Bytes32ToUintMap {
+ Bytes32ToBytes32Map _inner;
+ }
+
+ /**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+ function set(
+ Bytes32ToUintMap storage map,
+ bytes32 key,
+ uint256 value
+ ) internal returns (bool) {
+ return set(map._inner, key, bytes32(value));
+ }
+
+ /**
+ * @dev Removes a value from a set. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
+ return remove(map._inner, key);
+ }
+
+ /**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
+ return contains(map._inner, key);
+ }
+
+ /**
+ * @dev Returns the number of elements in the map. O(1).
+ */
+ function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
+ return length(map._inner);
+ }
+
+ /**
+ * @dev Returns the element stored at position `index` in the set. O(1).
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - `index` must be strictly less than {length}.
+ */
+ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
+ (bytes32 key, bytes32 value) = at(map._inner, index);
+ return (key, uint256(value));
+ }
+
+ /**
+ * @dev Tries to returns the value associated with `key`. O(1).
+ * Does not revert if `key` is not in the map.
+ */
+ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
+ (bool success, bytes32 value) = tryGet(map._inner, key);
+ return (success, uint256(value));
+ }
+
+ /**
+ * @dev Returns the value associated with `key`. O(1).
+ *
+ * Requirements:
+ *
+ * - `key` must be in the map.
+ */
+ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
+ return uint256(get(map._inner, key));
+ }
+
+ /**
+ * @dev Same as {get}, with a custom error message when `key` is not in the map.
+ *
+ * CAUTION: This function is deprecated because it requires allocating memory for the error
+ * message unnecessarily. For custom revert reasons use {tryGet}.
+ */
+ function get(
+ Bytes32ToUintMap storage map,
+ bytes32 key,
+ string memory errorMessage
+ ) internal view returns (uint256) {
+ return uint256(get(map._inner, key, errorMessage));
+ }
+}
\ No newline at end of file
diff --git a/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts b/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts
index 4efd98039f..af0063fb50 100644
--- a/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts
+++ b/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts
@@ -35,7 +35,6 @@ const zeroLINK = ethers.utils.parseEther('0')
const oneLINK = ethers.utils.parseEther('1')
const twoLINK = ethers.utils.parseEther('2')
const fiveLINK = ethers.utils.parseEther('5')
-const sixLINK = ethers.utils.parseEther('6')
const tenLINK = ethers.utils.parseEther('10')
const oneHundredLINK = ethers.utils.parseEther('100')
@@ -142,8 +141,12 @@ const setup = async () => {
owner,
)
- lt = await ltFactory.deploy()
- labm = await labmFactory.deploy(lt.address, twoLINK)
+ // New parameters needed by the constructor
+ const maxPerform = 5
+ const maxCheck = 20
+
+ lt = (await ltFactory.deploy()) as LinkToken
+ labm = await labmFactory.deploy(lt.address, twoLINK, maxPerform, maxCheck)
await labm.deployed()
for (let i = 1; i <= 4; i++) {
@@ -471,8 +474,8 @@ describe('LinkAvailableBalanceMonitor', () => {
let aggregators: MockContract[]
beforeEach(async () => {
- MAX_PERFORM = (await labm.MAX_PERFORM()).toNumber()
- MAX_CHECK = (await labm.MAX_CHECK()).toNumber()
+ MAX_PERFORM = await labm.getMaxPerform()
+ MAX_CHECK = await labm.getMaxCheck()
proxyAddresses = []
minBalances = []
aggregators = []
@@ -577,7 +580,7 @@ describe('LinkAvailableBalanceMonitor', () => {
it('Can handle MAX_PERFORM proxies within gas limit', async () => {
// add MAX_PERFORM number of proxies
- const MAX_PERFORM = (await labm.MAX_PERFORM()).toNumber()
+ const MAX_PERFORM = await labm.getMaxPerform()
const proxyAddresses = []
const minBalances = []
for (let idx = 0; idx < MAX_PERFORM; idx++) {
From 09f0afdef4ec46909d6d3cdc2f3a12f4fcec9ca8 Mon Sep 17 00:00:00 2001
From: Jean Arnaud
Date: Thu, 26 Oct 2023 15:58:27 +0200
Subject: [PATCH 014/327] Add missing fields to generated Deploy methods
(#11061)
* Add missing fields to generated Deploy methods
* Regenerate wrappers
* Abigen test
* Error handling
* Test Address method returning the proper address
* Update generated wrappers
* Refactor method and check type assertion
* Format
---
core/gethwrappers/abigen.go | 61 ++++++++++++++++---
core/gethwrappers/abigen_test.go | 29 +++++++++
.../generated/functions/functions.go | 2 +-
.../functions_allow_list.go | 2 +-
.../functions_client_example.go | 2 +-
.../functions_coordinator.go | 2 +-
.../functions_load_test_client.go | 2 +-
.../functions_router/functions_router.go | 2 +-
.../functions_v1_events_mock.go | 2 +-
.../functions/generated/ocr2dr/ocr2dr.go | 2 +-
.../ocr2dr_client_example.go | 2 +-
.../generated/ocr2dr_oracle/ocr2dr_oracle.go | 2 +-
.../ocr2dr_registry/ocr2dr_registry.go | 2 +-
.../authorized_forwarder.go | 2 +-
.../automation_consumer_benchmark.go | 2 +-
.../automation_forwarder_logic.go | 2 +-
.../automation_registrar_wrapper2_1.go | 2 +-
.../automation_utils_2_1.go | 2 +-
.../batch_blockhash_store.go | 2 +-
.../batch_vrf_coordinator_v2.go | 2 +-
.../batch_vrf_coordinator_v2plus.go | 2 +-
.../blockhash_store/blockhash_store.go | 2 +-
.../chain_specific_util_helper.go | 2 +-
.../consumer_wrapper/consumer_wrapper.go | 2 +-
.../dummy_protocol_wrapper.go | 2 +-
.../generated/flags_wrapper/flags_wrapper.go | 2 +-
.../flux_aggregator_wrapper.go | 2 +-
.../functions_billing_registry_events_mock.go | 2 +-
.../functions_oracle_events_mock.go | 2 +-
.../generated/gas_wrapper/gas_wrapper.go | 2 +-
.../gas_wrapper_mock/gas_wrapper_mock.go | 2 +-
.../keeper_consumer_performance_wrapper.go | 2 +-
.../keeper_consumer_wrapper.go | 2 +-
.../keeper_registrar_wrapper1_2.go | 2 +-
.../keeper_registrar_wrapper1_2_mock.go | 2 +-
.../keeper_registrar_wrapper2_0.go | 2 +-
.../keeper_registry_logic1_3.go | 2 +-
.../keeper_registry_logic2_0.go | 2 +-
.../keeper_registry_logic_a_wrapper_2_1.go | 2 +-
.../keeper_registry_logic_b_wrapper_2_1.go | 2 +-
.../keeper_registry_wrapper1_1.go | 2 +-
.../keeper_registry_wrapper1_1_mock.go | 2 +-
.../keeper_registry_wrapper1_2.go | 2 +-
.../keeper_registry_wrapper1_3.go | 2 +-
.../keeper_registry_wrapper2_0.go | 2 +-
.../keeper_registry_wrapper_2_1.go | 2 +-
.../keepers_vrf_consumer.go | 2 +-
.../link_token_interface.go | 2 +-
.../generated/log_emitter/log_emitter.go | 2 +-
.../log_triggered_streams_lookup_wrapper.go | 2 +-
.../log_upkeep_counter_wrapper.go | 2 +-
.../mock_aggregator_proxy.go | 2 +-
.../mock_ethlink_aggregator_wrapper.go | 2 +-
.../mock_gas_aggregator_wrapper.go | 2 +-
.../multiwordconsumer_wrapper.go | 2 +-
.../operator_factory/operator_factory.go | 2 +-
.../operator_wrapper/operator_wrapper.go | 2 +-
.../oracle_wrapper/oracle_wrapper.go | 2 +-
.../perform_data_checker_wrapper.go | 2 +-
.../solidity_vrf_consumer_interface.go | 2 +-
.../solidity_vrf_consumer_interface_v08.go | 2 +-
.../solidity_vrf_coordinator_interface.go | 2 +-
.../solidity_vrf_request_id.go | 2 +-
.../solidity_vrf_request_id_v08.go | 2 +-
.../solidity_vrf_v08_verifier_wrapper.go | 2 +-
.../solidity_vrf_verifier_wrapper.go | 2 +-
.../solidity_vrf_wrapper.go | 2 +-
.../streams_lookup_upkeep_wrapper.go | 2 +-
.../test_api_consumer_wrapper.go | 2 +-
.../trusted_blockhash_store.go | 2 +-
.../upkeep_counter_wrapper.go | 2 +-
...eep_perform_counter_restrictive_wrapper.go | 2 +-
.../upkeep_transcoder/upkeep_transcoder.go | 2 +-
...ifiable_load_log_trigger_upkeep_wrapper.go | 2 +-
...able_load_streams_lookup_upkeep_wrapper.go | 2 +-
.../verifiable_load_upkeep_wrapper.go | 2 +-
.../vrf_consumer_v2/vrf_consumer_v2.go | 2 +-
...rf_consumer_v2_plus_upgradeable_example.go | 2 +-
.../vrf_consumer_v2_upgradeable_example.go | 2 +-
.../vrf_coordinator_mock.go | 2 +-
.../vrf_coordinator_v2/vrf_coordinator_v2.go | 2 +-
.../vrf_coordinator_v2_5.go | 2 +-
.../vrf_coordinator_v2_plus_v2_example.go | 2 +-
.../vrf_external_sub_owner_example.go | 2 +-
.../vrf_load_test_external_sub_owner.go | 2 +-
.../vrf_load_test_ownerless_consumer.go | 2 +-
.../vrf_load_test_with_metrics.go | 2 +-
.../vrf_malicious_consumer_v2.go | 2 +-
.../vrf_malicious_consumer_v2_plus.go | 2 +-
.../generated/vrf_owner/vrf_owner.go | 2 +-
.../vrf_owner_test_consumer.go | 2 +-
.../vrf_ownerless_consumer_example.go | 2 +-
.../vrf_single_consumer_example.go | 2 +-
.../vrf_v2_consumer_wrapper.go | 2 +-
.../vrf_v2plus_load_test_with_metrics.go | 2 +-
.../vrf_v2plus_single_consumer.go | 2 +-
.../vrf_v2plus_sub_owner.go | 2 +-
.../vrf_v2plus_upgraded_version.go | 2 +-
.../vrfv2_proxy_admin/vrfv2_proxy_admin.go | 2 +-
.../vrfv2_reverting_example.go | 2 +-
.../vrfv2_transparent_upgradeable_proxy.go | 2 +-
.../generated/vrfv2_wrapper/vrfv2_wrapper.go | 2 +-
.../vrfv2_wrapper_consumer_example.go | 2 +-
.../vrfv2plus_client/vrfv2plus_client.go | 2 +-
.../vrfv2plus_consumer_example.go | 2 +-
.../vrfv2plus_malicious_migrator.go | 2 +-
.../vrfv2plus_reverting_example.go | 2 +-
.../vrfv2plus_wrapper/vrfv2plus_wrapper.go | 2 +-
.../vrfv2plus_wrapper_consumer_example.go | 2 +-
.../vrfv2plus_wrapper_load_test_consumer.go | 2 +-
core/gethwrappers/go_generate.go | 2 +-
.../errored_verifier/errored_verifier.go | 2 +-
.../exposed_verifier/exposed_verifier.go | 2 +-
.../generated/fee_manager/fee_manager.go | 2 +-
.../reward_manager/reward_manager.go | 2 +-
.../llo-feeds/generated/verifier/verifier.go | 2 +-
.../verifier_proxy/verifier_proxy.go | 2 +-
.../burn_mint_erc677/burn_mint_erc677.go | 2 +-
.../shared/generated/erc20/erc20.go | 2 +-
.../shared/generated/link_token/link_token.go | 2 +-
.../generated/werc20_mock/werc20_mock.go | 2 +-
.../generated/entry_point/entry_point.go | 2 +-
.../greeter_wrapper/greeter_wrapper.go | 2 +-
.../paymaster_wrapper/paymaster_wrapper.go | 2 +-
.../generated/sca_wrapper/sca_wrapper.go | 2 +-
.../smart_contract_account_factory.go | 2 +-
.../smart_contract_account_helper.go | 2 +-
127 files changed, 207 insertions(+), 133 deletions(-)
create mode 100644 core/gethwrappers/abigen_test.go
diff --git a/core/gethwrappers/abigen.go b/core/gethwrappers/abigen.go
index 5affe54657..d96d9f8c30 100644
--- a/core/gethwrappers/abigen.go
+++ b/core/gethwrappers/abigen.go
@@ -159,9 +159,17 @@ func getContractName(fileNode *ast.File) string {
return contractName
}
+// Add the `.address` and `.abi` fields to the contract struct.
func addContractStructFields(contractName string, fileNode *ast.File) *ast.File {
- // Add the `.address` and `.abi` fields to the contract struct
- fileNode = astutil.Apply(fileNode, func(cursor *astutil.Cursor) bool {
+ fileNode = addContractStructFieldsToStruct(contractName, fileNode)
+ fileNode = addContractStructFieldsToConstructor(contractName, fileNode)
+ fileNode = addContractStructFieldsToDeployMethod(contractName, fileNode)
+ return fileNode
+}
+
+// Add the fields to the contract struct.
+func addContractStructFieldsToStruct(contractName string, fileNode *ast.File) *ast.File {
+ return astutil.Apply(fileNode, func(cursor *astutil.Cursor) bool {
x, is := cursor.Node().(*ast.StructType)
if !is {
return true
@@ -188,14 +196,14 @@ func addContractStructFields(contractName string, fileNode *ast.File) *ast.File
Sel: ast.NewIdent("ABI"),
},
}
-
x.Fields.List = append([]*ast.Field{addrField, abiField}, x.Fields.List...)
-
return false
}, nil).(*ast.File)
+}
- // Add the fields to the return value of the constructor
- fileNode = astutil.Apply(fileNode, func(cursor *astutil.Cursor) bool {
+// Add the fields to the return value of the constructor.
+func addContractStructFieldsToConstructor(contractName string, fileNode *ast.File) *ast.File {
+ return astutil.Apply(fileNode, func(cursor *astutil.Cursor) bool {
x, is := cursor.Node().(*ast.FuncDecl)
if !is {
return true
@@ -260,11 +268,48 @@ func addContractStructFields(contractName string, fileNode *ast.File) *ast.File
}
x.Body.List = append([]ast.Stmt{parseABIStmt, checkParseABIErrStmt}, x.Body.List...)
-
return false
}, nil).(*ast.File)
+}
- return fileNode
+// Add the fields to the returned struct in the 'Deploy' method.
+func addContractStructFieldsToDeployMethod(contractName string, fileNode *ast.File) *ast.File {
+ return astutil.Apply(fileNode, func(cursor *astutil.Cursor) bool {
+ x, is := cursor.Node().(*ast.FuncDecl)
+ if !is {
+ return true
+ } else if x.Name.Name != "Deploy"+contractName {
+ return false
+ }
+
+ for _, stmt := range x.Body.List {
+ returnStmt, is := stmt.(*ast.ReturnStmt)
+ if !is {
+ continue
+ }
+ if len(returnStmt.Results) < 3 {
+ continue
+ }
+ rs, is := returnStmt.Results[2].(*ast.UnaryExpr)
+ if !is {
+ return true
+ }
+ lit, is := rs.X.(*ast.CompositeLit)
+ if !is {
+ continue
+ }
+ addressExpr := &ast.KeyValueExpr{
+ Key: ast.NewIdent("address"),
+ Value: ast.NewIdent("address"),
+ }
+ abiExpr := &ast.KeyValueExpr{
+ Key: ast.NewIdent("abi"),
+ Value: ast.NewIdent("*parsed"),
+ }
+ lit.Elts = append([]ast.Expr{addressExpr, abiExpr}, lit.Elts...)
+ }
+ return false
+ }, nil).(*ast.File)
}
func getLogNames(fileNode *ast.File) []string {
diff --git a/core/gethwrappers/abigen_test.go b/core/gethwrappers/abigen_test.go
new file mode 100644
index 0000000000..7c206f59dc
--- /dev/null
+++ b/core/gethwrappers/abigen_test.go
@@ -0,0 +1,29 @@
+package gethwrappers
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+)
+
+// Test that the generated Deploy method fill all the required fields and returns the correct address.
+// We perform this test using the generated LogEmitter wrapper.
+func TestGeneratedDeployMethodAddressField(t *testing.T) {
+ owner := testutils.MustNewSimTransactor(t)
+ ec := backends.NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), map[common.Address]core.GenesisAccount{
+ owner.From: {
+ Balance: big.NewInt(0).Mul(big.NewInt(10), big.NewInt(1e18)),
+ },
+ }, 10e6)
+ emitterAddr, _, emitter, err := log_emitter.DeployLogEmitter(owner, ec)
+ require.NoError(t, err)
+ require.Equal(t, emitterAddr, emitter.Address())
+}
diff --git a/core/gethwrappers/functions/generated/functions/functions.go b/core/gethwrappers/functions/generated/functions/functions.go
index 419c21ca05..0c35806b66 100644
--- a/core/gethwrappers/functions/generated/functions/functions.go
+++ b/core/gethwrappers/functions/generated/functions/functions.go
@@ -50,7 +50,7 @@ func DeployFunctions(auth *bind.TransactOpts, backend bind.ContractBackend) (com
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Functions{FunctionsCaller: FunctionsCaller{contract: contract}, FunctionsTransactor: FunctionsTransactor{contract: contract}, FunctionsFilterer: FunctionsFilterer{contract: contract}}, nil
+ return address, tx, &Functions{address: address, abi: *parsed, FunctionsCaller: FunctionsCaller{contract: contract}, FunctionsTransactor: FunctionsTransactor{contract: contract}, FunctionsFilterer: FunctionsFilterer{contract: contract}}, nil
}
type Functions struct {
diff --git a/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go b/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go
index d86c07f170..0ccb08cdaa 100644
--- a/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go
+++ b/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go
@@ -57,7 +57,7 @@ func DeployTermsOfServiceAllowList(auth *bind.TransactOpts, backend bind.Contrac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &TermsOfServiceAllowList{TermsOfServiceAllowListCaller: TermsOfServiceAllowListCaller{contract: contract}, TermsOfServiceAllowListTransactor: TermsOfServiceAllowListTransactor{contract: contract}, TermsOfServiceAllowListFilterer: TermsOfServiceAllowListFilterer{contract: contract}}, nil
+ return address, tx, &TermsOfServiceAllowList{address: address, abi: *parsed, TermsOfServiceAllowListCaller: TermsOfServiceAllowListCaller{contract: contract}, TermsOfServiceAllowListTransactor: TermsOfServiceAllowListTransactor{contract: contract}, TermsOfServiceAllowListFilterer: TermsOfServiceAllowListFilterer{contract: contract}}, nil
}
type TermsOfServiceAllowList struct {
diff --git a/core/gethwrappers/functions/generated/functions_client_example/functions_client_example.go b/core/gethwrappers/functions/generated/functions_client_example/functions_client_example.go
index 6ae90b45ed..00bf6a438f 100644
--- a/core/gethwrappers/functions/generated/functions_client_example/functions_client_example.go
+++ b/core/gethwrappers/functions/generated/functions_client_example/functions_client_example.go
@@ -52,7 +52,7 @@ func DeployFunctionsClientExample(auth *bind.TransactOpts, backend bind.Contract
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsClientExample{FunctionsClientExampleCaller: FunctionsClientExampleCaller{contract: contract}, FunctionsClientExampleTransactor: FunctionsClientExampleTransactor{contract: contract}, FunctionsClientExampleFilterer: FunctionsClientExampleFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsClientExample{address: address, abi: *parsed, FunctionsClientExampleCaller: FunctionsClientExampleCaller{contract: contract}, FunctionsClientExampleTransactor: FunctionsClientExampleTransactor{contract: contract}, FunctionsClientExampleFilterer: FunctionsClientExampleFilterer{contract: contract}}, nil
}
type FunctionsClientExample struct {
diff --git a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
index 32db52a029..ffe072fc65 100644
--- a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
+++ b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
@@ -92,7 +92,7 @@ func DeployFunctionsCoordinator(auth *bind.TransactOpts, backend bind.ContractBa
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsCoordinator{FunctionsCoordinatorCaller: FunctionsCoordinatorCaller{contract: contract}, FunctionsCoordinatorTransactor: FunctionsCoordinatorTransactor{contract: contract}, FunctionsCoordinatorFilterer: FunctionsCoordinatorFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsCoordinator{address: address, abi: *parsed, FunctionsCoordinatorCaller: FunctionsCoordinatorCaller{contract: contract}, FunctionsCoordinatorTransactor: FunctionsCoordinatorTransactor{contract: contract}, FunctionsCoordinatorFilterer: FunctionsCoordinatorFilterer{contract: contract}}, nil
}
type FunctionsCoordinator struct {
diff --git a/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go b/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go
index 37a895fe8c..a03d6a5b14 100644
--- a/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go
+++ b/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go
@@ -52,7 +52,7 @@ func DeployFunctionsLoadTestClient(auth *bind.TransactOpts, backend bind.Contrac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsLoadTestClient{FunctionsLoadTestClientCaller: FunctionsLoadTestClientCaller{contract: contract}, FunctionsLoadTestClientTransactor: FunctionsLoadTestClientTransactor{contract: contract}, FunctionsLoadTestClientFilterer: FunctionsLoadTestClientFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsLoadTestClient{address: address, abi: *parsed, FunctionsLoadTestClientCaller: FunctionsLoadTestClientCaller{contract: contract}, FunctionsLoadTestClientTransactor: FunctionsLoadTestClientTransactor{contract: contract}, FunctionsLoadTestClientFilterer: FunctionsLoadTestClientFilterer{contract: contract}}, nil
}
type FunctionsLoadTestClient struct {
diff --git a/core/gethwrappers/functions/generated/functions_router/functions_router.go b/core/gethwrappers/functions/generated/functions_router/functions_router.go
index 2c482048c4..592f95b568 100644
--- a/core/gethwrappers/functions/generated/functions_router/functions_router.go
+++ b/core/gethwrappers/functions/generated/functions_router/functions_router.go
@@ -91,7 +91,7 @@ func DeployFunctionsRouter(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsRouter{FunctionsRouterCaller: FunctionsRouterCaller{contract: contract}, FunctionsRouterTransactor: FunctionsRouterTransactor{contract: contract}, FunctionsRouterFilterer: FunctionsRouterFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsRouter{address: address, abi: *parsed, FunctionsRouterCaller: FunctionsRouterCaller{contract: contract}, FunctionsRouterTransactor: FunctionsRouterTransactor{contract: contract}, FunctionsRouterFilterer: FunctionsRouterFilterer{contract: contract}}, nil
}
type FunctionsRouter struct {
diff --git a/core/gethwrappers/functions/generated/functions_v1_events_mock/functions_v1_events_mock.go b/core/gethwrappers/functions/generated/functions_v1_events_mock/functions_v1_events_mock.go
index ae1fe20401..422d2e8b2a 100644
--- a/core/gethwrappers/functions/generated/functions_v1_events_mock/functions_v1_events_mock.go
+++ b/core/gethwrappers/functions/generated/functions_v1_events_mock/functions_v1_events_mock.go
@@ -60,7 +60,7 @@ func DeployFunctionsV1EventsMock(auth *bind.TransactOpts, backend bind.ContractB
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsV1EventsMock{FunctionsV1EventsMockCaller: FunctionsV1EventsMockCaller{contract: contract}, FunctionsV1EventsMockTransactor: FunctionsV1EventsMockTransactor{contract: contract}, FunctionsV1EventsMockFilterer: FunctionsV1EventsMockFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsV1EventsMock{address: address, abi: *parsed, FunctionsV1EventsMockCaller: FunctionsV1EventsMockCaller{contract: contract}, FunctionsV1EventsMockTransactor: FunctionsV1EventsMockTransactor{contract: contract}, FunctionsV1EventsMockFilterer: FunctionsV1EventsMockFilterer{contract: contract}}, nil
}
type FunctionsV1EventsMock struct {
diff --git a/core/gethwrappers/functions/generated/ocr2dr/ocr2dr.go b/core/gethwrappers/functions/generated/ocr2dr/ocr2dr.go
index 8cc6594216..c2b3c3a5e9 100644
--- a/core/gethwrappers/functions/generated/ocr2dr/ocr2dr.go
+++ b/core/gethwrappers/functions/generated/ocr2dr/ocr2dr.go
@@ -50,7 +50,7 @@ func DeployOCR2DR(auth *bind.TransactOpts, backend bind.ContractBackend) (common
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &OCR2DR{OCR2DRCaller: OCR2DRCaller{contract: contract}, OCR2DRTransactor: OCR2DRTransactor{contract: contract}, OCR2DRFilterer: OCR2DRFilterer{contract: contract}}, nil
+ return address, tx, &OCR2DR{address: address, abi: *parsed, OCR2DRCaller: OCR2DRCaller{contract: contract}, OCR2DRTransactor: OCR2DRTransactor{contract: contract}, OCR2DRFilterer: OCR2DRFilterer{contract: contract}}, nil
}
type OCR2DR struct {
diff --git a/core/gethwrappers/functions/generated/ocr2dr_client_example/ocr2dr_client_example.go b/core/gethwrappers/functions/generated/ocr2dr_client_example/ocr2dr_client_example.go
index a4b94f7e92..c37ba64b8d 100644
--- a/core/gethwrappers/functions/generated/ocr2dr_client_example/ocr2dr_client_example.go
+++ b/core/gethwrappers/functions/generated/ocr2dr_client_example/ocr2dr_client_example.go
@@ -61,7 +61,7 @@ func DeployOCR2DRClientExample(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &OCR2DRClientExample{OCR2DRClientExampleCaller: OCR2DRClientExampleCaller{contract: contract}, OCR2DRClientExampleTransactor: OCR2DRClientExampleTransactor{contract: contract}, OCR2DRClientExampleFilterer: OCR2DRClientExampleFilterer{contract: contract}}, nil
+ return address, tx, &OCR2DRClientExample{address: address, abi: *parsed, OCR2DRClientExampleCaller: OCR2DRClientExampleCaller{contract: contract}, OCR2DRClientExampleTransactor: OCR2DRClientExampleTransactor{contract: contract}, OCR2DRClientExampleFilterer: OCR2DRClientExampleFilterer{contract: contract}}, nil
}
type OCR2DRClientExample struct {
diff --git a/core/gethwrappers/functions/generated/ocr2dr_oracle/ocr2dr_oracle.go b/core/gethwrappers/functions/generated/ocr2dr_oracle/ocr2dr_oracle.go
index 509a3c8388..a2f81cfb30 100644
--- a/core/gethwrappers/functions/generated/ocr2dr_oracle/ocr2dr_oracle.go
+++ b/core/gethwrappers/functions/generated/ocr2dr_oracle/ocr2dr_oracle.go
@@ -59,7 +59,7 @@ func DeployOCR2DROracle(auth *bind.TransactOpts, backend bind.ContractBackend) (
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &OCR2DROracle{OCR2DROracleCaller: OCR2DROracleCaller{contract: contract}, OCR2DROracleTransactor: OCR2DROracleTransactor{contract: contract}, OCR2DROracleFilterer: OCR2DROracleFilterer{contract: contract}}, nil
+ return address, tx, &OCR2DROracle{address: address, abi: *parsed, OCR2DROracleCaller: OCR2DROracleCaller{contract: contract}, OCR2DROracleTransactor: OCR2DROracleTransactor{contract: contract}, OCR2DROracleFilterer: OCR2DROracleFilterer{contract: contract}}, nil
}
type OCR2DROracle struct {
diff --git a/core/gethwrappers/functions/generated/ocr2dr_registry/ocr2dr_registry.go b/core/gethwrappers/functions/generated/ocr2dr_registry/ocr2dr_registry.go
index eb825b5eaa..f81a431620 100644
--- a/core/gethwrappers/functions/generated/ocr2dr_registry/ocr2dr_registry.go
+++ b/core/gethwrappers/functions/generated/ocr2dr_registry/ocr2dr_registry.go
@@ -71,7 +71,7 @@ func DeployOCR2DRRegistry(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &OCR2DRRegistry{OCR2DRRegistryCaller: OCR2DRRegistryCaller{contract: contract}, OCR2DRRegistryTransactor: OCR2DRRegistryTransactor{contract: contract}, OCR2DRRegistryFilterer: OCR2DRRegistryFilterer{contract: contract}}, nil
+ return address, tx, &OCR2DRRegistry{address: address, abi: *parsed, OCR2DRRegistryCaller: OCR2DRRegistryCaller{contract: contract}, OCR2DRRegistryTransactor: OCR2DRRegistryTransactor{contract: contract}, OCR2DRRegistryFilterer: OCR2DRRegistryFilterer{contract: contract}}, nil
}
type OCR2DRRegistry struct {
diff --git a/core/gethwrappers/generated/authorized_forwarder/authorized_forwarder.go b/core/gethwrappers/generated/authorized_forwarder/authorized_forwarder.go
index 6417a9c678..03643c9154 100644
--- a/core/gethwrappers/generated/authorized_forwarder/authorized_forwarder.go
+++ b/core/gethwrappers/generated/authorized_forwarder/authorized_forwarder.go
@@ -52,7 +52,7 @@ func DeployAuthorizedForwarder(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &AuthorizedForwarder{AuthorizedForwarderCaller: AuthorizedForwarderCaller{contract: contract}, AuthorizedForwarderTransactor: AuthorizedForwarderTransactor{contract: contract}, AuthorizedForwarderFilterer: AuthorizedForwarderFilterer{contract: contract}}, nil
+ return address, tx, &AuthorizedForwarder{address: address, abi: *parsed, AuthorizedForwarderCaller: AuthorizedForwarderCaller{contract: contract}, AuthorizedForwarderTransactor: AuthorizedForwarderTransactor{contract: contract}, AuthorizedForwarderFilterer: AuthorizedForwarderFilterer{contract: contract}}, nil
}
type AuthorizedForwarder struct {
diff --git a/core/gethwrappers/generated/automation_consumer_benchmark/automation_consumer_benchmark.go b/core/gethwrappers/generated/automation_consumer_benchmark/automation_consumer_benchmark.go
index f4d59e7e7d..3dafe68921 100644
--- a/core/gethwrappers/generated/automation_consumer_benchmark/automation_consumer_benchmark.go
+++ b/core/gethwrappers/generated/automation_consumer_benchmark/automation_consumer_benchmark.go
@@ -52,7 +52,7 @@ func DeployAutomationConsumerBenchmark(auth *bind.TransactOpts, backend bind.Con
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &AutomationConsumerBenchmark{AutomationConsumerBenchmarkCaller: AutomationConsumerBenchmarkCaller{contract: contract}, AutomationConsumerBenchmarkTransactor: AutomationConsumerBenchmarkTransactor{contract: contract}, AutomationConsumerBenchmarkFilterer: AutomationConsumerBenchmarkFilterer{contract: contract}}, nil
+ return address, tx, &AutomationConsumerBenchmark{address: address, abi: *parsed, AutomationConsumerBenchmarkCaller: AutomationConsumerBenchmarkCaller{contract: contract}, AutomationConsumerBenchmarkTransactor: AutomationConsumerBenchmarkTransactor{contract: contract}, AutomationConsumerBenchmarkFilterer: AutomationConsumerBenchmarkFilterer{contract: contract}}, nil
}
type AutomationConsumerBenchmark struct {
diff --git a/core/gethwrappers/generated/automation_forwarder_logic/automation_forwarder_logic.go b/core/gethwrappers/generated/automation_forwarder_logic/automation_forwarder_logic.go
index b26f5e5692..8b35a68c82 100644
--- a/core/gethwrappers/generated/automation_forwarder_logic/automation_forwarder_logic.go
+++ b/core/gethwrappers/generated/automation_forwarder_logic/automation_forwarder_logic.go
@@ -50,7 +50,7 @@ func DeployAutomationForwarderLogic(auth *bind.TransactOpts, backend bind.Contra
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &AutomationForwarderLogic{AutomationForwarderLogicCaller: AutomationForwarderLogicCaller{contract: contract}, AutomationForwarderLogicTransactor: AutomationForwarderLogicTransactor{contract: contract}, AutomationForwarderLogicFilterer: AutomationForwarderLogicFilterer{contract: contract}}, nil
+ return address, tx, &AutomationForwarderLogic{address: address, abi: *parsed, AutomationForwarderLogicCaller: AutomationForwarderLogicCaller{contract: contract}, AutomationForwarderLogicTransactor: AutomationForwarderLogicTransactor{contract: contract}, AutomationForwarderLogicFilterer: AutomationForwarderLogicFilterer{contract: contract}}, nil
}
type AutomationForwarderLogic struct {
diff --git a/core/gethwrappers/generated/automation_registrar_wrapper2_1/automation_registrar_wrapper2_1.go b/core/gethwrappers/generated/automation_registrar_wrapper2_1/automation_registrar_wrapper2_1.go
index d2b8054436..311ce75c10 100644
--- a/core/gethwrappers/generated/automation_registrar_wrapper2_1/automation_registrar_wrapper2_1.go
+++ b/core/gethwrappers/generated/automation_registrar_wrapper2_1/automation_registrar_wrapper2_1.go
@@ -77,7 +77,7 @@ func DeployAutomationRegistrar(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &AutomationRegistrar{AutomationRegistrarCaller: AutomationRegistrarCaller{contract: contract}, AutomationRegistrarTransactor: AutomationRegistrarTransactor{contract: contract}, AutomationRegistrarFilterer: AutomationRegistrarFilterer{contract: contract}}, nil
+ return address, tx, &AutomationRegistrar{address: address, abi: *parsed, AutomationRegistrarCaller: AutomationRegistrarCaller{contract: contract}, AutomationRegistrarTransactor: AutomationRegistrarTransactor{contract: contract}, AutomationRegistrarFilterer: AutomationRegistrarFilterer{contract: contract}}, nil
}
type AutomationRegistrar struct {
diff --git a/core/gethwrappers/generated/automation_utils_2_1/automation_utils_2_1.go b/core/gethwrappers/generated/automation_utils_2_1/automation_utils_2_1.go
index 1eaa4ea03f..5d6dc1e41c 100644
--- a/core/gethwrappers/generated/automation_utils_2_1/automation_utils_2_1.go
+++ b/core/gethwrappers/generated/automation_utils_2_1/automation_utils_2_1.go
@@ -110,7 +110,7 @@ func DeployAutomationUtils(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &AutomationUtils{AutomationUtilsCaller: AutomationUtilsCaller{contract: contract}, AutomationUtilsTransactor: AutomationUtilsTransactor{contract: contract}, AutomationUtilsFilterer: AutomationUtilsFilterer{contract: contract}}, nil
+ return address, tx, &AutomationUtils{address: address, abi: *parsed, AutomationUtilsCaller: AutomationUtilsCaller{contract: contract}, AutomationUtilsTransactor: AutomationUtilsTransactor{contract: contract}, AutomationUtilsFilterer: AutomationUtilsFilterer{contract: contract}}, nil
}
type AutomationUtils struct {
diff --git a/core/gethwrappers/generated/batch_blockhash_store/batch_blockhash_store.go b/core/gethwrappers/generated/batch_blockhash_store/batch_blockhash_store.go
index 426c5a2c79..1a43287d74 100644
--- a/core/gethwrappers/generated/batch_blockhash_store/batch_blockhash_store.go
+++ b/core/gethwrappers/generated/batch_blockhash_store/batch_blockhash_store.go
@@ -50,7 +50,7 @@ func DeployBatchBlockhashStore(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &BatchBlockhashStore{BatchBlockhashStoreCaller: BatchBlockhashStoreCaller{contract: contract}, BatchBlockhashStoreTransactor: BatchBlockhashStoreTransactor{contract: contract}, BatchBlockhashStoreFilterer: BatchBlockhashStoreFilterer{contract: contract}}, nil
+ return address, tx, &BatchBlockhashStore{address: address, abi: *parsed, BatchBlockhashStoreCaller: BatchBlockhashStoreCaller{contract: contract}, BatchBlockhashStoreTransactor: BatchBlockhashStoreTransactor{contract: contract}, BatchBlockhashStoreFilterer: BatchBlockhashStoreFilterer{contract: contract}}, nil
}
type BatchBlockhashStore struct {
diff --git a/core/gethwrappers/generated/batch_vrf_coordinator_v2/batch_vrf_coordinator_v2.go b/core/gethwrappers/generated/batch_vrf_coordinator_v2/batch_vrf_coordinator_v2.go
index 4cb6e76b96..3a1ec957b9 100644
--- a/core/gethwrappers/generated/batch_vrf_coordinator_v2/batch_vrf_coordinator_v2.go
+++ b/core/gethwrappers/generated/batch_vrf_coordinator_v2/batch_vrf_coordinator_v2.go
@@ -72,7 +72,7 @@ func DeployBatchVRFCoordinatorV2(auth *bind.TransactOpts, backend bind.ContractB
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &BatchVRFCoordinatorV2{BatchVRFCoordinatorV2Caller: BatchVRFCoordinatorV2Caller{contract: contract}, BatchVRFCoordinatorV2Transactor: BatchVRFCoordinatorV2Transactor{contract: contract}, BatchVRFCoordinatorV2Filterer: BatchVRFCoordinatorV2Filterer{contract: contract}}, nil
+ return address, tx, &BatchVRFCoordinatorV2{address: address, abi: *parsed, BatchVRFCoordinatorV2Caller: BatchVRFCoordinatorV2Caller{contract: contract}, BatchVRFCoordinatorV2Transactor: BatchVRFCoordinatorV2Transactor{contract: contract}, BatchVRFCoordinatorV2Filterer: BatchVRFCoordinatorV2Filterer{contract: contract}}, nil
}
type BatchVRFCoordinatorV2 struct {
diff --git a/core/gethwrappers/generated/batch_vrf_coordinator_v2plus/batch_vrf_coordinator_v2plus.go b/core/gethwrappers/generated/batch_vrf_coordinator_v2plus/batch_vrf_coordinator_v2plus.go
index 610f3a2700..58f134fe2a 100644
--- a/core/gethwrappers/generated/batch_vrf_coordinator_v2plus/batch_vrf_coordinator_v2plus.go
+++ b/core/gethwrappers/generated/batch_vrf_coordinator_v2plus/batch_vrf_coordinator_v2plus.go
@@ -73,7 +73,7 @@ func DeployBatchVRFCoordinatorV2Plus(auth *bind.TransactOpts, backend bind.Contr
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &BatchVRFCoordinatorV2Plus{BatchVRFCoordinatorV2PlusCaller: BatchVRFCoordinatorV2PlusCaller{contract: contract}, BatchVRFCoordinatorV2PlusTransactor: BatchVRFCoordinatorV2PlusTransactor{contract: contract}, BatchVRFCoordinatorV2PlusFilterer: BatchVRFCoordinatorV2PlusFilterer{contract: contract}}, nil
+ return address, tx, &BatchVRFCoordinatorV2Plus{address: address, abi: *parsed, BatchVRFCoordinatorV2PlusCaller: BatchVRFCoordinatorV2PlusCaller{contract: contract}, BatchVRFCoordinatorV2PlusTransactor: BatchVRFCoordinatorV2PlusTransactor{contract: contract}, BatchVRFCoordinatorV2PlusFilterer: BatchVRFCoordinatorV2PlusFilterer{contract: contract}}, nil
}
type BatchVRFCoordinatorV2Plus struct {
diff --git a/core/gethwrappers/generated/blockhash_store/blockhash_store.go b/core/gethwrappers/generated/blockhash_store/blockhash_store.go
index 8711f13b2d..e43f9f450e 100644
--- a/core/gethwrappers/generated/blockhash_store/blockhash_store.go
+++ b/core/gethwrappers/generated/blockhash_store/blockhash_store.go
@@ -50,7 +50,7 @@ func DeployBlockhashStore(auth *bind.TransactOpts, backend bind.ContractBackend)
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &BlockhashStore{BlockhashStoreCaller: BlockhashStoreCaller{contract: contract}, BlockhashStoreTransactor: BlockhashStoreTransactor{contract: contract}, BlockhashStoreFilterer: BlockhashStoreFilterer{contract: contract}}, nil
+ return address, tx, &BlockhashStore{address: address, abi: *parsed, BlockhashStoreCaller: BlockhashStoreCaller{contract: contract}, BlockhashStoreTransactor: BlockhashStoreTransactor{contract: contract}, BlockhashStoreFilterer: BlockhashStoreFilterer{contract: contract}}, nil
}
type BlockhashStore struct {
diff --git a/core/gethwrappers/generated/chain_specific_util_helper/chain_specific_util_helper.go b/core/gethwrappers/generated/chain_specific_util_helper/chain_specific_util_helper.go
index aa4dc0f88d..b32c3d18d5 100644
--- a/core/gethwrappers/generated/chain_specific_util_helper/chain_specific_util_helper.go
+++ b/core/gethwrappers/generated/chain_specific_util_helper/chain_specific_util_helper.go
@@ -50,7 +50,7 @@ func DeployChainSpecificUtilHelper(auth *bind.TransactOpts, backend bind.Contrac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &ChainSpecificUtilHelper{ChainSpecificUtilHelperCaller: ChainSpecificUtilHelperCaller{contract: contract}, ChainSpecificUtilHelperTransactor: ChainSpecificUtilHelperTransactor{contract: contract}, ChainSpecificUtilHelperFilterer: ChainSpecificUtilHelperFilterer{contract: contract}}, nil
+ return address, tx, &ChainSpecificUtilHelper{address: address, abi: *parsed, ChainSpecificUtilHelperCaller: ChainSpecificUtilHelperCaller{contract: contract}, ChainSpecificUtilHelperTransactor: ChainSpecificUtilHelperTransactor{contract: contract}, ChainSpecificUtilHelperFilterer: ChainSpecificUtilHelperFilterer{contract: contract}}, nil
}
type ChainSpecificUtilHelper struct {
diff --git a/core/gethwrappers/generated/consumer_wrapper/consumer_wrapper.go b/core/gethwrappers/generated/consumer_wrapper/consumer_wrapper.go
index 954f66a08e..0c0386b085 100644
--- a/core/gethwrappers/generated/consumer_wrapper/consumer_wrapper.go
+++ b/core/gethwrappers/generated/consumer_wrapper/consumer_wrapper.go
@@ -52,7 +52,7 @@ func DeployConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, _link
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Consumer{ConsumerCaller: ConsumerCaller{contract: contract}, ConsumerTransactor: ConsumerTransactor{contract: contract}, ConsumerFilterer: ConsumerFilterer{contract: contract}}, nil
+ return address, tx, &Consumer{address: address, abi: *parsed, ConsumerCaller: ConsumerCaller{contract: contract}, ConsumerTransactor: ConsumerTransactor{contract: contract}, ConsumerFilterer: ConsumerFilterer{contract: contract}}, nil
}
type Consumer struct {
diff --git a/core/gethwrappers/generated/dummy_protocol_wrapper/dummy_protocol_wrapper.go b/core/gethwrappers/generated/dummy_protocol_wrapper/dummy_protocol_wrapper.go
index e7a88fdd06..e2838b3f6f 100644
--- a/core/gethwrappers/generated/dummy_protocol_wrapper/dummy_protocol_wrapper.go
+++ b/core/gethwrappers/generated/dummy_protocol_wrapper/dummy_protocol_wrapper.go
@@ -52,7 +52,7 @@ func DeployDummyProtocol(auth *bind.TransactOpts, backend bind.ContractBackend)
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &DummyProtocol{DummyProtocolCaller: DummyProtocolCaller{contract: contract}, DummyProtocolTransactor: DummyProtocolTransactor{contract: contract}, DummyProtocolFilterer: DummyProtocolFilterer{contract: contract}}, nil
+ return address, tx, &DummyProtocol{address: address, abi: *parsed, DummyProtocolCaller: DummyProtocolCaller{contract: contract}, DummyProtocolTransactor: DummyProtocolTransactor{contract: contract}, DummyProtocolFilterer: DummyProtocolFilterer{contract: contract}}, nil
}
type DummyProtocol struct {
diff --git a/core/gethwrappers/generated/flags_wrapper/flags_wrapper.go b/core/gethwrappers/generated/flags_wrapper/flags_wrapper.go
index f8d3c21b54..590f9e2af9 100644
--- a/core/gethwrappers/generated/flags_wrapper/flags_wrapper.go
+++ b/core/gethwrappers/generated/flags_wrapper/flags_wrapper.go
@@ -52,7 +52,7 @@ func DeployFlags(auth *bind.TransactOpts, backend bind.ContractBackend, racAddre
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Flags{FlagsCaller: FlagsCaller{contract: contract}, FlagsTransactor: FlagsTransactor{contract: contract}, FlagsFilterer: FlagsFilterer{contract: contract}}, nil
+ return address, tx, &Flags{address: address, abi: *parsed, FlagsCaller: FlagsCaller{contract: contract}, FlagsTransactor: FlagsTransactor{contract: contract}, FlagsFilterer: FlagsFilterer{contract: contract}}, nil
}
type Flags struct {
diff --git a/core/gethwrappers/generated/flux_aggregator_wrapper/flux_aggregator_wrapper.go b/core/gethwrappers/generated/flux_aggregator_wrapper/flux_aggregator_wrapper.go
index 6c4cb73af7..876ef73487 100644
--- a/core/gethwrappers/generated/flux_aggregator_wrapper/flux_aggregator_wrapper.go
+++ b/core/gethwrappers/generated/flux_aggregator_wrapper/flux_aggregator_wrapper.go
@@ -52,7 +52,7 @@ func DeployFluxAggregator(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FluxAggregator{FluxAggregatorCaller: FluxAggregatorCaller{contract: contract}, FluxAggregatorTransactor: FluxAggregatorTransactor{contract: contract}, FluxAggregatorFilterer: FluxAggregatorFilterer{contract: contract}}, nil
+ return address, tx, &FluxAggregator{address: address, abi: *parsed, FluxAggregatorCaller: FluxAggregatorCaller{contract: contract}, FluxAggregatorTransactor: FluxAggregatorTransactor{contract: contract}, FluxAggregatorFilterer: FluxAggregatorFilterer{contract: contract}}, nil
}
type FluxAggregator struct {
diff --git a/core/gethwrappers/generated/functions_billing_registry_events_mock/functions_billing_registry_events_mock.go b/core/gethwrappers/generated/functions_billing_registry_events_mock/functions_billing_registry_events_mock.go
index ec87fb9e74..c86c4feaa4 100644
--- a/core/gethwrappers/generated/functions_billing_registry_events_mock/functions_billing_registry_events_mock.go
+++ b/core/gethwrappers/generated/functions_billing_registry_events_mock/functions_billing_registry_events_mock.go
@@ -64,7 +64,7 @@ func DeployFunctionsBillingRegistryEventsMock(auth *bind.TransactOpts, backend b
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsBillingRegistryEventsMock{FunctionsBillingRegistryEventsMockCaller: FunctionsBillingRegistryEventsMockCaller{contract: contract}, FunctionsBillingRegistryEventsMockTransactor: FunctionsBillingRegistryEventsMockTransactor{contract: contract}, FunctionsBillingRegistryEventsMockFilterer: FunctionsBillingRegistryEventsMockFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsBillingRegistryEventsMock{address: address, abi: *parsed, FunctionsBillingRegistryEventsMockCaller: FunctionsBillingRegistryEventsMockCaller{contract: contract}, FunctionsBillingRegistryEventsMockTransactor: FunctionsBillingRegistryEventsMockTransactor{contract: contract}, FunctionsBillingRegistryEventsMockFilterer: FunctionsBillingRegistryEventsMockFilterer{contract: contract}}, nil
}
type FunctionsBillingRegistryEventsMock struct {
diff --git a/core/gethwrappers/generated/functions_oracle_events_mock/functions_oracle_events_mock.go b/core/gethwrappers/generated/functions_oracle_events_mock/functions_oracle_events_mock.go
index 3b8238c00e..4e97e08239 100644
--- a/core/gethwrappers/generated/functions_oracle_events_mock/functions_oracle_events_mock.go
+++ b/core/gethwrappers/generated/functions_oracle_events_mock/functions_oracle_events_mock.go
@@ -52,7 +52,7 @@ func DeployFunctionsOracleEventsMock(auth *bind.TransactOpts, backend bind.Contr
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FunctionsOracleEventsMock{FunctionsOracleEventsMockCaller: FunctionsOracleEventsMockCaller{contract: contract}, FunctionsOracleEventsMockTransactor: FunctionsOracleEventsMockTransactor{contract: contract}, FunctionsOracleEventsMockFilterer: FunctionsOracleEventsMockFilterer{contract: contract}}, nil
+ return address, tx, &FunctionsOracleEventsMock{address: address, abi: *parsed, FunctionsOracleEventsMockCaller: FunctionsOracleEventsMockCaller{contract: contract}, FunctionsOracleEventsMockTransactor: FunctionsOracleEventsMockTransactor{contract: contract}, FunctionsOracleEventsMockFilterer: FunctionsOracleEventsMockFilterer{contract: contract}}, nil
}
type FunctionsOracleEventsMock struct {
diff --git a/core/gethwrappers/generated/gas_wrapper/gas_wrapper.go b/core/gethwrappers/generated/gas_wrapper/gas_wrapper.go
index f2e25e36a7..eec0cf855f 100644
--- a/core/gethwrappers/generated/gas_wrapper/gas_wrapper.go
+++ b/core/gethwrappers/generated/gas_wrapper/gas_wrapper.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistryCheckUpkeepGasUsageWrapper(auth *bind.TransactOpts, bac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryCheckUpkeepGasUsageWrapper{KeeperRegistryCheckUpkeepGasUsageWrapperCaller: KeeperRegistryCheckUpkeepGasUsageWrapperCaller{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperTransactor: KeeperRegistryCheckUpkeepGasUsageWrapperTransactor{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperFilterer: KeeperRegistryCheckUpkeepGasUsageWrapperFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryCheckUpkeepGasUsageWrapper{address: address, abi: *parsed, KeeperRegistryCheckUpkeepGasUsageWrapperCaller: KeeperRegistryCheckUpkeepGasUsageWrapperCaller{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperTransactor: KeeperRegistryCheckUpkeepGasUsageWrapperTransactor{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperFilterer: KeeperRegistryCheckUpkeepGasUsageWrapperFilterer{contract: contract}}, nil
}
type KeeperRegistryCheckUpkeepGasUsageWrapper struct {
diff --git a/core/gethwrappers/generated/gas_wrapper_mock/gas_wrapper_mock.go b/core/gethwrappers/generated/gas_wrapper_mock/gas_wrapper_mock.go
index b0420097b4..93803ce993 100644
--- a/core/gethwrappers/generated/gas_wrapper_mock/gas_wrapper_mock.go
+++ b/core/gethwrappers/generated/gas_wrapper_mock/gas_wrapper_mock.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistryCheckUpkeepGasUsageWrapperMock(auth *bind.TransactOpts,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryCheckUpkeepGasUsageWrapperMock{KeeperRegistryCheckUpkeepGasUsageWrapperMockCaller: KeeperRegistryCheckUpkeepGasUsageWrapperMockCaller{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperMockTransactor: KeeperRegistryCheckUpkeepGasUsageWrapperMockTransactor{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperMockFilterer: KeeperRegistryCheckUpkeepGasUsageWrapperMockFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryCheckUpkeepGasUsageWrapperMock{address: address, abi: *parsed, KeeperRegistryCheckUpkeepGasUsageWrapperMockCaller: KeeperRegistryCheckUpkeepGasUsageWrapperMockCaller{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperMockTransactor: KeeperRegistryCheckUpkeepGasUsageWrapperMockTransactor{contract: contract}, KeeperRegistryCheckUpkeepGasUsageWrapperMockFilterer: KeeperRegistryCheckUpkeepGasUsageWrapperMockFilterer{contract: contract}}, nil
}
type KeeperRegistryCheckUpkeepGasUsageWrapperMock struct {
diff --git a/core/gethwrappers/generated/keeper_consumer_performance_wrapper/keeper_consumer_performance_wrapper.go b/core/gethwrappers/generated/keeper_consumer_performance_wrapper/keeper_consumer_performance_wrapper.go
index 0e1876ce0a..08178c9882 100644
--- a/core/gethwrappers/generated/keeper_consumer_performance_wrapper/keeper_consumer_performance_wrapper.go
+++ b/core/gethwrappers/generated/keeper_consumer_performance_wrapper/keeper_consumer_performance_wrapper.go
@@ -52,7 +52,7 @@ func DeployKeeperConsumerPerformance(auth *bind.TransactOpts, backend bind.Contr
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperConsumerPerformance{KeeperConsumerPerformanceCaller: KeeperConsumerPerformanceCaller{contract: contract}, KeeperConsumerPerformanceTransactor: KeeperConsumerPerformanceTransactor{contract: contract}, KeeperConsumerPerformanceFilterer: KeeperConsumerPerformanceFilterer{contract: contract}}, nil
+ return address, tx, &KeeperConsumerPerformance{address: address, abi: *parsed, KeeperConsumerPerformanceCaller: KeeperConsumerPerformanceCaller{contract: contract}, KeeperConsumerPerformanceTransactor: KeeperConsumerPerformanceTransactor{contract: contract}, KeeperConsumerPerformanceFilterer: KeeperConsumerPerformanceFilterer{contract: contract}}, nil
}
type KeeperConsumerPerformance struct {
diff --git a/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go b/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go
index 896927f9e6..8a4ee2c4de 100644
--- a/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go
+++ b/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go
@@ -50,7 +50,7 @@ func DeployKeeperConsumer(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperConsumer{KeeperConsumerCaller: KeeperConsumerCaller{contract: contract}, KeeperConsumerTransactor: KeeperConsumerTransactor{contract: contract}, KeeperConsumerFilterer: KeeperConsumerFilterer{contract: contract}}, nil
+ return address, tx, &KeeperConsumer{address: address, abi: *parsed, KeeperConsumerCaller: KeeperConsumerCaller{contract: contract}, KeeperConsumerTransactor: KeeperConsumerTransactor{contract: contract}, KeeperConsumerFilterer: KeeperConsumerFilterer{contract: contract}}, nil
}
type KeeperConsumer struct {
diff --git a/core/gethwrappers/generated/keeper_registrar_wrapper1_2/keeper_registrar_wrapper1_2.go b/core/gethwrappers/generated/keeper_registrar_wrapper1_2/keeper_registrar_wrapper1_2.go
index 3721238f67..45564b662d 100644
--- a/core/gethwrappers/generated/keeper_registrar_wrapper1_2/keeper_registrar_wrapper1_2.go
+++ b/core/gethwrappers/generated/keeper_registrar_wrapper1_2/keeper_registrar_wrapper1_2.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistrar{KeeperRegistrarCaller: KeeperRegistrarCaller{contract: contract}, KeeperRegistrarTransactor: KeeperRegistrarTransactor{contract: contract}, KeeperRegistrarFilterer: KeeperRegistrarFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistrar{address: address, abi: *parsed, KeeperRegistrarCaller: KeeperRegistrarCaller{contract: contract}, KeeperRegistrarTransactor: KeeperRegistrarTransactor{contract: contract}, KeeperRegistrarFilterer: KeeperRegistrarFilterer{contract: contract}}, nil
}
type KeeperRegistrar struct {
diff --git a/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock/keeper_registrar_wrapper1_2_mock.go b/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock/keeper_registrar_wrapper1_2_mock.go
index ea4c49f7c8..d83fd9a431 100644
--- a/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock/keeper_registrar_wrapper1_2_mock.go
+++ b/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock/keeper_registrar_wrapper1_2_mock.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistrarMock(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistrarMock{KeeperRegistrarMockCaller: KeeperRegistrarMockCaller{contract: contract}, KeeperRegistrarMockTransactor: KeeperRegistrarMockTransactor{contract: contract}, KeeperRegistrarMockFilterer: KeeperRegistrarMockFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistrarMock{address: address, abi: *parsed, KeeperRegistrarMockCaller: KeeperRegistrarMockCaller{contract: contract}, KeeperRegistrarMockTransactor: KeeperRegistrarMockTransactor{contract: contract}, KeeperRegistrarMockFilterer: KeeperRegistrarMockFilterer{contract: contract}}, nil
}
type KeeperRegistrarMock struct {
diff --git a/core/gethwrappers/generated/keeper_registrar_wrapper2_0/keeper_registrar_wrapper2_0.go b/core/gethwrappers/generated/keeper_registrar_wrapper2_0/keeper_registrar_wrapper2_0.go
index c8a7016df4..56d78f9f0d 100644
--- a/core/gethwrappers/generated/keeper_registrar_wrapper2_0/keeper_registrar_wrapper2_0.go
+++ b/core/gethwrappers/generated/keeper_registrar_wrapper2_0/keeper_registrar_wrapper2_0.go
@@ -63,7 +63,7 @@ func DeployKeeperRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistrar{KeeperRegistrarCaller: KeeperRegistrarCaller{contract: contract}, KeeperRegistrarTransactor: KeeperRegistrarTransactor{contract: contract}, KeeperRegistrarFilterer: KeeperRegistrarFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistrar{address: address, abi: *parsed, KeeperRegistrarCaller: KeeperRegistrarCaller{contract: contract}, KeeperRegistrarTransactor: KeeperRegistrarTransactor{contract: contract}, KeeperRegistrarFilterer: KeeperRegistrarFilterer{contract: contract}}, nil
}
type KeeperRegistrar struct {
diff --git a/core/gethwrappers/generated/keeper_registry_logic1_3/keeper_registry_logic1_3.go b/core/gethwrappers/generated/keeper_registry_logic1_3/keeper_registry_logic1_3.go
index 6049536df6..11856a0c8f 100644
--- a/core/gethwrappers/generated/keeper_registry_logic1_3/keeper_registry_logic1_3.go
+++ b/core/gethwrappers/generated/keeper_registry_logic1_3/keeper_registry_logic1_3.go
@@ -67,7 +67,7 @@ func DeployKeeperRegistryLogic(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryLogic{KeeperRegistryLogicCaller: KeeperRegistryLogicCaller{contract: contract}, KeeperRegistryLogicTransactor: KeeperRegistryLogicTransactor{contract: contract}, KeeperRegistryLogicFilterer: KeeperRegistryLogicFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryLogic{address: address, abi: *parsed, KeeperRegistryLogicCaller: KeeperRegistryLogicCaller{contract: contract}, KeeperRegistryLogicTransactor: KeeperRegistryLogicTransactor{contract: contract}, KeeperRegistryLogicFilterer: KeeperRegistryLogicFilterer{contract: contract}}, nil
}
type KeeperRegistryLogic struct {
diff --git a/core/gethwrappers/generated/keeper_registry_logic2_0/keeper_registry_logic2_0.go b/core/gethwrappers/generated/keeper_registry_logic2_0/keeper_registry_logic2_0.go
index e4e24a0463..819e7e094b 100644
--- a/core/gethwrappers/generated/keeper_registry_logic2_0/keeper_registry_logic2_0.go
+++ b/core/gethwrappers/generated/keeper_registry_logic2_0/keeper_registry_logic2_0.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistryLogic(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryLogic{KeeperRegistryLogicCaller: KeeperRegistryLogicCaller{contract: contract}, KeeperRegistryLogicTransactor: KeeperRegistryLogicTransactor{contract: contract}, KeeperRegistryLogicFilterer: KeeperRegistryLogicFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryLogic{address: address, abi: *parsed, KeeperRegistryLogicCaller: KeeperRegistryLogicCaller{contract: contract}, KeeperRegistryLogicTransactor: KeeperRegistryLogicTransactor{contract: contract}, KeeperRegistryLogicFilterer: KeeperRegistryLogicFilterer{contract: contract}}, nil
}
type KeeperRegistryLogic struct {
diff --git a/core/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1/keeper_registry_logic_a_wrapper_2_1.go b/core/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1/keeper_registry_logic_a_wrapper_2_1.go
index 48c4d75e8b..69d9adbc68 100644
--- a/core/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1/keeper_registry_logic_a_wrapper_2_1.go
+++ b/core/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1/keeper_registry_logic_a_wrapper_2_1.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistryLogicA(auth *bind.TransactOpts, backend bind.ContractBa
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryLogicA{KeeperRegistryLogicACaller: KeeperRegistryLogicACaller{contract: contract}, KeeperRegistryLogicATransactor: KeeperRegistryLogicATransactor{contract: contract}, KeeperRegistryLogicAFilterer: KeeperRegistryLogicAFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryLogicA{address: address, abi: *parsed, KeeperRegistryLogicACaller: KeeperRegistryLogicACaller{contract: contract}, KeeperRegistryLogicATransactor: KeeperRegistryLogicATransactor{contract: contract}, KeeperRegistryLogicAFilterer: KeeperRegistryLogicAFilterer{contract: contract}}, nil
}
type KeeperRegistryLogicA struct {
diff --git a/core/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1/keeper_registry_logic_b_wrapper_2_1.go b/core/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1/keeper_registry_logic_b_wrapper_2_1.go
index 15330fb821..984d9221eb 100644
--- a/core/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1/keeper_registry_logic_b_wrapper_2_1.go
+++ b/core/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1/keeper_registry_logic_b_wrapper_2_1.go
@@ -96,7 +96,7 @@ func DeployKeeperRegistryLogicB(auth *bind.TransactOpts, backend bind.ContractBa
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryLogicB{KeeperRegistryLogicBCaller: KeeperRegistryLogicBCaller{contract: contract}, KeeperRegistryLogicBTransactor: KeeperRegistryLogicBTransactor{contract: contract}, KeeperRegistryLogicBFilterer: KeeperRegistryLogicBFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryLogicB{address: address, abi: *parsed, KeeperRegistryLogicBCaller: KeeperRegistryLogicBCaller{contract: contract}, KeeperRegistryLogicBTransactor: KeeperRegistryLogicBTransactor{contract: contract}, KeeperRegistryLogicBFilterer: KeeperRegistryLogicBFilterer{contract: contract}}, nil
}
type KeeperRegistryLogicB struct {
diff --git a/core/gethwrappers/generated/keeper_registry_wrapper1_1/keeper_registry_wrapper1_1.go b/core/gethwrappers/generated/keeper_registry_wrapper1_1/keeper_registry_wrapper1_1.go
index 896de7f088..196b2f36f5 100644
--- a/core/gethwrappers/generated/keeper_registry_wrapper1_1/keeper_registry_wrapper1_1.go
+++ b/core/gethwrappers/generated/keeper_registry_wrapper1_1/keeper_registry_wrapper1_1.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistry(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistry{KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistry{address: address, abi: *parsed, KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
}
type KeeperRegistry struct {
diff --git a/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock/keeper_registry_wrapper1_1_mock.go b/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock/keeper_registry_wrapper1_1_mock.go
index d7bfc132eb..14457f91ef 100644
--- a/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock/keeper_registry_wrapper1_1_mock.go
+++ b/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock/keeper_registry_wrapper1_1_mock.go
@@ -52,7 +52,7 @@ func DeployKeeperRegistryMock(auth *bind.TransactOpts, backend bind.ContractBack
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistryMock{KeeperRegistryMockCaller: KeeperRegistryMockCaller{contract: contract}, KeeperRegistryMockTransactor: KeeperRegistryMockTransactor{contract: contract}, KeeperRegistryMockFilterer: KeeperRegistryMockFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistryMock{address: address, abi: *parsed, KeeperRegistryMockCaller: KeeperRegistryMockCaller{contract: contract}, KeeperRegistryMockTransactor: KeeperRegistryMockTransactor{contract: contract}, KeeperRegistryMockFilterer: KeeperRegistryMockFilterer{contract: contract}}, nil
}
type KeeperRegistryMock struct {
diff --git a/core/gethwrappers/generated/keeper_registry_wrapper1_2/keeper_registry_wrapper1_2.go b/core/gethwrappers/generated/keeper_registry_wrapper1_2/keeper_registry_wrapper1_2.go
index cbfd589abf..6fa0d55b78 100644
--- a/core/gethwrappers/generated/keeper_registry_wrapper1_2/keeper_registry_wrapper1_2.go
+++ b/core/gethwrappers/generated/keeper_registry_wrapper1_2/keeper_registry_wrapper1_2.go
@@ -74,7 +74,7 @@ func DeployKeeperRegistry(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistry{KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistry{address: address, abi: *parsed, KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
}
type KeeperRegistry struct {
diff --git a/core/gethwrappers/generated/keeper_registry_wrapper1_3/keeper_registry_wrapper1_3.go b/core/gethwrappers/generated/keeper_registry_wrapper1_3/keeper_registry_wrapper1_3.go
index 73ff800e12..bea6e458a0 100644
--- a/core/gethwrappers/generated/keeper_registry_wrapper1_3/keeper_registry_wrapper1_3.go
+++ b/core/gethwrappers/generated/keeper_registry_wrapper1_3/keeper_registry_wrapper1_3.go
@@ -74,7 +74,7 @@ func DeployKeeperRegistry(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistry{KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistry{address: address, abi: *parsed, KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
}
type KeeperRegistry struct {
diff --git a/core/gethwrappers/generated/keeper_registry_wrapper2_0/keeper_registry_wrapper2_0.go b/core/gethwrappers/generated/keeper_registry_wrapper2_0/keeper_registry_wrapper2_0.go
index 2aaf8085aa..bd000995e3 100644
--- a/core/gethwrappers/generated/keeper_registry_wrapper2_0/keeper_registry_wrapper2_0.go
+++ b/core/gethwrappers/generated/keeper_registry_wrapper2_0/keeper_registry_wrapper2_0.go
@@ -94,7 +94,7 @@ func DeployKeeperRegistry(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistry{KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistry{address: address, abi: *parsed, KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
}
type KeeperRegistry struct {
diff --git a/core/gethwrappers/generated/keeper_registry_wrapper_2_1/keeper_registry_wrapper_2_1.go b/core/gethwrappers/generated/keeper_registry_wrapper_2_1/keeper_registry_wrapper_2_1.go
index 1db34ca395..fc9d120c5e 100644
--- a/core/gethwrappers/generated/keeper_registry_wrapper_2_1/keeper_registry_wrapper_2_1.go
+++ b/core/gethwrappers/generated/keeper_registry_wrapper_2_1/keeper_registry_wrapper_2_1.go
@@ -70,7 +70,7 @@ func DeployKeeperRegistry(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeeperRegistry{KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
+ return address, tx, &KeeperRegistry{address: address, abi: *parsed, KeeperRegistryCaller: KeeperRegistryCaller{contract: contract}, KeeperRegistryTransactor: KeeperRegistryTransactor{contract: contract}, KeeperRegistryFilterer: KeeperRegistryFilterer{contract: contract}}, nil
}
type KeeperRegistry struct {
diff --git a/core/gethwrappers/generated/keepers_vrf_consumer/keepers_vrf_consumer.go b/core/gethwrappers/generated/keepers_vrf_consumer/keepers_vrf_consumer.go
index 99e0fece52..57e0aced8a 100644
--- a/core/gethwrappers/generated/keepers_vrf_consumer/keepers_vrf_consumer.go
+++ b/core/gethwrappers/generated/keepers_vrf_consumer/keepers_vrf_consumer.go
@@ -50,7 +50,7 @@ func DeployKeepersVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBack
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &KeepersVRFConsumer{KeepersVRFConsumerCaller: KeepersVRFConsumerCaller{contract: contract}, KeepersVRFConsumerTransactor: KeepersVRFConsumerTransactor{contract: contract}, KeepersVRFConsumerFilterer: KeepersVRFConsumerFilterer{contract: contract}}, nil
+ return address, tx, &KeepersVRFConsumer{address: address, abi: *parsed, KeepersVRFConsumerCaller: KeepersVRFConsumerCaller{contract: contract}, KeepersVRFConsumerTransactor: KeepersVRFConsumerTransactor{contract: contract}, KeepersVRFConsumerFilterer: KeepersVRFConsumerFilterer{contract: contract}}, nil
}
type KeepersVRFConsumer struct {
diff --git a/core/gethwrappers/generated/link_token_interface/link_token_interface.go b/core/gethwrappers/generated/link_token_interface/link_token_interface.go
index d0a6b92c1e..53fbb56dce 100644
--- a/core/gethwrappers/generated/link_token_interface/link_token_interface.go
+++ b/core/gethwrappers/generated/link_token_interface/link_token_interface.go
@@ -52,7 +52,7 @@ func DeployLinkToken(auth *bind.TransactOpts, backend bind.ContractBackend) (com
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &LinkToken{LinkTokenCaller: LinkTokenCaller{contract: contract}, LinkTokenTransactor: LinkTokenTransactor{contract: contract}, LinkTokenFilterer: LinkTokenFilterer{contract: contract}}, nil
+ return address, tx, &LinkToken{address: address, abi: *parsed, LinkTokenCaller: LinkTokenCaller{contract: contract}, LinkTokenTransactor: LinkTokenTransactor{contract: contract}, LinkTokenFilterer: LinkTokenFilterer{contract: contract}}, nil
}
type LinkToken struct {
diff --git a/core/gethwrappers/generated/log_emitter/log_emitter.go b/core/gethwrappers/generated/log_emitter/log_emitter.go
index 4f0189dfde..3cb11da512 100644
--- a/core/gethwrappers/generated/log_emitter/log_emitter.go
+++ b/core/gethwrappers/generated/log_emitter/log_emitter.go
@@ -52,7 +52,7 @@ func DeployLogEmitter(auth *bind.TransactOpts, backend bind.ContractBackend) (co
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &LogEmitter{LogEmitterCaller: LogEmitterCaller{contract: contract}, LogEmitterTransactor: LogEmitterTransactor{contract: contract}, LogEmitterFilterer: LogEmitterFilterer{contract: contract}}, nil
+ return address, tx, &LogEmitter{address: address, abi: *parsed, LogEmitterCaller: LogEmitterCaller{contract: contract}, LogEmitterTransactor: LogEmitterTransactor{contract: contract}, LogEmitterFilterer: LogEmitterFilterer{contract: contract}}, nil
}
type LogEmitter struct {
diff --git a/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper/log_triggered_streams_lookup_wrapper.go b/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper/log_triggered_streams_lookup_wrapper.go
index 18b61baed7..ccd5aea2c3 100644
--- a/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper/log_triggered_streams_lookup_wrapper.go
+++ b/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper/log_triggered_streams_lookup_wrapper.go
@@ -63,7 +63,7 @@ func DeployLogTriggeredStreamsLookup(auth *bind.TransactOpts, backend bind.Contr
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &LogTriggeredStreamsLookup{LogTriggeredStreamsLookupCaller: LogTriggeredStreamsLookupCaller{contract: contract}, LogTriggeredStreamsLookupTransactor: LogTriggeredStreamsLookupTransactor{contract: contract}, LogTriggeredStreamsLookupFilterer: LogTriggeredStreamsLookupFilterer{contract: contract}}, nil
+ return address, tx, &LogTriggeredStreamsLookup{address: address, abi: *parsed, LogTriggeredStreamsLookupCaller: LogTriggeredStreamsLookupCaller{contract: contract}, LogTriggeredStreamsLookupTransactor: LogTriggeredStreamsLookupTransactor{contract: contract}, LogTriggeredStreamsLookupFilterer: LogTriggeredStreamsLookupFilterer{contract: contract}}, nil
}
type LogTriggeredStreamsLookup struct {
diff --git a/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go b/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go
index fd55349b12..51b7b753cc 100644
--- a/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go
+++ b/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go
@@ -63,7 +63,7 @@ func DeployLogUpkeepCounter(auth *bind.TransactOpts, backend bind.ContractBacken
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &LogUpkeepCounter{LogUpkeepCounterCaller: LogUpkeepCounterCaller{contract: contract}, LogUpkeepCounterTransactor: LogUpkeepCounterTransactor{contract: contract}, LogUpkeepCounterFilterer: LogUpkeepCounterFilterer{contract: contract}}, nil
+ return address, tx, &LogUpkeepCounter{address: address, abi: *parsed, LogUpkeepCounterCaller: LogUpkeepCounterCaller{contract: contract}, LogUpkeepCounterTransactor: LogUpkeepCounterTransactor{contract: contract}, LogUpkeepCounterFilterer: LogUpkeepCounterFilterer{contract: contract}}, nil
}
type LogUpkeepCounter struct {
diff --git a/core/gethwrappers/generated/mock_aggregator_proxy/mock_aggregator_proxy.go b/core/gethwrappers/generated/mock_aggregator_proxy/mock_aggregator_proxy.go
index 1694ebd11f..a9c972e8be 100644
--- a/core/gethwrappers/generated/mock_aggregator_proxy/mock_aggregator_proxy.go
+++ b/core/gethwrappers/generated/mock_aggregator_proxy/mock_aggregator_proxy.go
@@ -50,7 +50,7 @@ func DeployMockAggregatorProxy(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &MockAggregatorProxy{MockAggregatorProxyCaller: MockAggregatorProxyCaller{contract: contract}, MockAggregatorProxyTransactor: MockAggregatorProxyTransactor{contract: contract}, MockAggregatorProxyFilterer: MockAggregatorProxyFilterer{contract: contract}}, nil
+ return address, tx, &MockAggregatorProxy{address: address, abi: *parsed, MockAggregatorProxyCaller: MockAggregatorProxyCaller{contract: contract}, MockAggregatorProxyTransactor: MockAggregatorProxyTransactor{contract: contract}, MockAggregatorProxyFilterer: MockAggregatorProxyFilterer{contract: contract}}, nil
}
type MockAggregatorProxy struct {
diff --git a/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper/mock_ethlink_aggregator_wrapper.go b/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper/mock_ethlink_aggregator_wrapper.go
index bcf34a0c47..bc92e3f32b 100644
--- a/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper/mock_ethlink_aggregator_wrapper.go
+++ b/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper/mock_ethlink_aggregator_wrapper.go
@@ -50,7 +50,7 @@ func DeployMockETHLINKAggregator(auth *bind.TransactOpts, backend bind.ContractB
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &MockETHLINKAggregator{MockETHLINKAggregatorCaller: MockETHLINKAggregatorCaller{contract: contract}, MockETHLINKAggregatorTransactor: MockETHLINKAggregatorTransactor{contract: contract}, MockETHLINKAggregatorFilterer: MockETHLINKAggregatorFilterer{contract: contract}}, nil
+ return address, tx, &MockETHLINKAggregator{address: address, abi: *parsed, MockETHLINKAggregatorCaller: MockETHLINKAggregatorCaller{contract: contract}, MockETHLINKAggregatorTransactor: MockETHLINKAggregatorTransactor{contract: contract}, MockETHLINKAggregatorFilterer: MockETHLINKAggregatorFilterer{contract: contract}}, nil
}
type MockETHLINKAggregator struct {
diff --git a/core/gethwrappers/generated/mock_gas_aggregator_wrapper/mock_gas_aggregator_wrapper.go b/core/gethwrappers/generated/mock_gas_aggregator_wrapper/mock_gas_aggregator_wrapper.go
index edc0adc5b7..148417f3fc 100644
--- a/core/gethwrappers/generated/mock_gas_aggregator_wrapper/mock_gas_aggregator_wrapper.go
+++ b/core/gethwrappers/generated/mock_gas_aggregator_wrapper/mock_gas_aggregator_wrapper.go
@@ -50,7 +50,7 @@ func DeployMockGASAggregator(auth *bind.TransactOpts, backend bind.ContractBacke
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &MockGASAggregator{MockGASAggregatorCaller: MockGASAggregatorCaller{contract: contract}, MockGASAggregatorTransactor: MockGASAggregatorTransactor{contract: contract}, MockGASAggregatorFilterer: MockGASAggregatorFilterer{contract: contract}}, nil
+ return address, tx, &MockGASAggregator{address: address, abi: *parsed, MockGASAggregatorCaller: MockGASAggregatorCaller{contract: contract}, MockGASAggregatorTransactor: MockGASAggregatorTransactor{contract: contract}, MockGASAggregatorFilterer: MockGASAggregatorFilterer{contract: contract}}, nil
}
type MockGASAggregator struct {
diff --git a/core/gethwrappers/generated/multiwordconsumer_wrapper/multiwordconsumer_wrapper.go b/core/gethwrappers/generated/multiwordconsumer_wrapper/multiwordconsumer_wrapper.go
index c939418e57..9a1fc55b6c 100644
--- a/core/gethwrappers/generated/multiwordconsumer_wrapper/multiwordconsumer_wrapper.go
+++ b/core/gethwrappers/generated/multiwordconsumer_wrapper/multiwordconsumer_wrapper.go
@@ -52,7 +52,7 @@ func DeployMultiWordConsumer(auth *bind.TransactOpts, backend bind.ContractBacke
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &MultiWordConsumer{MultiWordConsumerCaller: MultiWordConsumerCaller{contract: contract}, MultiWordConsumerTransactor: MultiWordConsumerTransactor{contract: contract}, MultiWordConsumerFilterer: MultiWordConsumerFilterer{contract: contract}}, nil
+ return address, tx, &MultiWordConsumer{address: address, abi: *parsed, MultiWordConsumerCaller: MultiWordConsumerCaller{contract: contract}, MultiWordConsumerTransactor: MultiWordConsumerTransactor{contract: contract}, MultiWordConsumerFilterer: MultiWordConsumerFilterer{contract: contract}}, nil
}
type MultiWordConsumer struct {
diff --git a/core/gethwrappers/generated/operator_factory/operator_factory.go b/core/gethwrappers/generated/operator_factory/operator_factory.go
index b062f6b01a..c9a6c57ce2 100644
--- a/core/gethwrappers/generated/operator_factory/operator_factory.go
+++ b/core/gethwrappers/generated/operator_factory/operator_factory.go
@@ -52,7 +52,7 @@ func DeployOperatorFactory(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &OperatorFactory{OperatorFactoryCaller: OperatorFactoryCaller{contract: contract}, OperatorFactoryTransactor: OperatorFactoryTransactor{contract: contract}, OperatorFactoryFilterer: OperatorFactoryFilterer{contract: contract}}, nil
+ return address, tx, &OperatorFactory{address: address, abi: *parsed, OperatorFactoryCaller: OperatorFactoryCaller{contract: contract}, OperatorFactoryTransactor: OperatorFactoryTransactor{contract: contract}, OperatorFactoryFilterer: OperatorFactoryFilterer{contract: contract}}, nil
}
type OperatorFactory struct {
diff --git a/core/gethwrappers/generated/operator_wrapper/operator_wrapper.go b/core/gethwrappers/generated/operator_wrapper/operator_wrapper.go
index 69541858f3..4b7f634763 100644
--- a/core/gethwrappers/generated/operator_wrapper/operator_wrapper.go
+++ b/core/gethwrappers/generated/operator_wrapper/operator_wrapper.go
@@ -52,7 +52,7 @@ func DeployOperator(auth *bind.TransactOpts, backend bind.ContractBackend, link
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Operator{OperatorCaller: OperatorCaller{contract: contract}, OperatorTransactor: OperatorTransactor{contract: contract}, OperatorFilterer: OperatorFilterer{contract: contract}}, nil
+ return address, tx, &Operator{address: address, abi: *parsed, OperatorCaller: OperatorCaller{contract: contract}, OperatorTransactor: OperatorTransactor{contract: contract}, OperatorFilterer: OperatorFilterer{contract: contract}}, nil
}
type Operator struct {
diff --git a/core/gethwrappers/generated/oracle_wrapper/oracle_wrapper.go b/core/gethwrappers/generated/oracle_wrapper/oracle_wrapper.go
index 98c7b37338..e22e6cd303 100644
--- a/core/gethwrappers/generated/oracle_wrapper/oracle_wrapper.go
+++ b/core/gethwrappers/generated/oracle_wrapper/oracle_wrapper.go
@@ -52,7 +52,7 @@ func DeployOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _link c
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Oracle{OracleCaller: OracleCaller{contract: contract}, OracleTransactor: OracleTransactor{contract: contract}, OracleFilterer: OracleFilterer{contract: contract}}, nil
+ return address, tx, &Oracle{address: address, abi: *parsed, OracleCaller: OracleCaller{contract: contract}, OracleTransactor: OracleTransactor{contract: contract}, OracleFilterer: OracleFilterer{contract: contract}}, nil
}
type Oracle struct {
diff --git a/core/gethwrappers/generated/perform_data_checker_wrapper/perform_data_checker_wrapper.go b/core/gethwrappers/generated/perform_data_checker_wrapper/perform_data_checker_wrapper.go
index aa639deb9c..a678ad0a8d 100644
--- a/core/gethwrappers/generated/perform_data_checker_wrapper/perform_data_checker_wrapper.go
+++ b/core/gethwrappers/generated/perform_data_checker_wrapper/perform_data_checker_wrapper.go
@@ -50,7 +50,7 @@ func DeployPerformDataChecker(auth *bind.TransactOpts, backend bind.ContractBack
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &PerformDataChecker{PerformDataCheckerCaller: PerformDataCheckerCaller{contract: contract}, PerformDataCheckerTransactor: PerformDataCheckerTransactor{contract: contract}, PerformDataCheckerFilterer: PerformDataCheckerFilterer{contract: contract}}, nil
+ return address, tx, &PerformDataChecker{address: address, abi: *parsed, PerformDataCheckerCaller: PerformDataCheckerCaller{contract: contract}, PerformDataCheckerTransactor: PerformDataCheckerTransactor{contract: contract}, PerformDataCheckerFilterer: PerformDataCheckerFilterer{contract: contract}}, nil
}
type PerformDataChecker struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_consumer_interface/solidity_vrf_consumer_interface.go b/core/gethwrappers/generated/solidity_vrf_consumer_interface/solidity_vrf_consumer_interface.go
index de123d5ec7..8c815be3a5 100644
--- a/core/gethwrappers/generated/solidity_vrf_consumer_interface/solidity_vrf_consumer_interface.go
+++ b/core/gethwrappers/generated/solidity_vrf_consumer_interface/solidity_vrf_consumer_interface.go
@@ -50,7 +50,7 @@ func DeployVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, _v
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFConsumer{VRFConsumerCaller: VRFConsumerCaller{contract: contract}, VRFConsumerTransactor: VRFConsumerTransactor{contract: contract}, VRFConsumerFilterer: VRFConsumerFilterer{contract: contract}}, nil
+ return address, tx, &VRFConsumer{address: address, abi: *parsed, VRFConsumerCaller: VRFConsumerCaller{contract: contract}, VRFConsumerTransactor: VRFConsumerTransactor{contract: contract}, VRFConsumerFilterer: VRFConsumerFilterer{contract: contract}}, nil
}
type VRFConsumer struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08/solidity_vrf_consumer_interface_v08.go b/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08/solidity_vrf_consumer_interface_v08.go
index e122d3e07f..b3267a17ce 100644
--- a/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08/solidity_vrf_consumer_interface_v08.go
+++ b/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08/solidity_vrf_consumer_interface_v08.go
@@ -50,7 +50,7 @@ func DeployVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, vr
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFConsumer{VRFConsumerCaller: VRFConsumerCaller{contract: contract}, VRFConsumerTransactor: VRFConsumerTransactor{contract: contract}, VRFConsumerFilterer: VRFConsumerFilterer{contract: contract}}, nil
+ return address, tx, &VRFConsumer{address: address, abi: *parsed, VRFConsumerCaller: VRFConsumerCaller{contract: contract}, VRFConsumerTransactor: VRFConsumerTransactor{contract: contract}, VRFConsumerFilterer: VRFConsumerFilterer{contract: contract}}, nil
}
type VRFConsumer struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_coordinator_interface/solidity_vrf_coordinator_interface.go b/core/gethwrappers/generated/solidity_vrf_coordinator_interface/solidity_vrf_coordinator_interface.go
index 36c715a2c0..7ac2210dc7 100644
--- a/core/gethwrappers/generated/solidity_vrf_coordinator_interface/solidity_vrf_coordinator_interface.go
+++ b/core/gethwrappers/generated/solidity_vrf_coordinator_interface/solidity_vrf_coordinator_interface.go
@@ -52,7 +52,7 @@ func DeployVRFCoordinator(auth *bind.TransactOpts, backend bind.ContractBackend,
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
+ return address, tx, &VRFCoordinator{address: address, abi: *parsed, VRFCoordinatorCaller: VRFCoordinatorCaller{contract: contract}, VRFCoordinatorTransactor: VRFCoordinatorTransactor{contract: contract}, VRFCoordinatorFilterer: VRFCoordinatorFilterer{contract: contract}}, nil
}
type VRFCoordinator struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_request_id/solidity_vrf_request_id.go b/core/gethwrappers/generated/solidity_vrf_request_id/solidity_vrf_request_id.go
index fd35e245e4..b0d101a96c 100644
--- a/core/gethwrappers/generated/solidity_vrf_request_id/solidity_vrf_request_id.go
+++ b/core/gethwrappers/generated/solidity_vrf_request_id/solidity_vrf_request_id.go
@@ -50,7 +50,7 @@ func DeployVRFRequestIDBaseTestHelper(auth *bind.TransactOpts, backend bind.Cont
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFRequestIDBaseTestHelper{VRFRequestIDBaseTestHelperCaller: VRFRequestIDBaseTestHelperCaller{contract: contract}, VRFRequestIDBaseTestHelperTransactor: VRFRequestIDBaseTestHelperTransactor{contract: contract}, VRFRequestIDBaseTestHelperFilterer: VRFRequestIDBaseTestHelperFilterer{contract: contract}}, nil
+ return address, tx, &VRFRequestIDBaseTestHelper{address: address, abi: *parsed, VRFRequestIDBaseTestHelperCaller: VRFRequestIDBaseTestHelperCaller{contract: contract}, VRFRequestIDBaseTestHelperTransactor: VRFRequestIDBaseTestHelperTransactor{contract: contract}, VRFRequestIDBaseTestHelperFilterer: VRFRequestIDBaseTestHelperFilterer{contract: contract}}, nil
}
type VRFRequestIDBaseTestHelper struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_request_id_v08/solidity_vrf_request_id_v08.go b/core/gethwrappers/generated/solidity_vrf_request_id_v08/solidity_vrf_request_id_v08.go
index 181226bfa3..5d931e3d90 100644
--- a/core/gethwrappers/generated/solidity_vrf_request_id_v08/solidity_vrf_request_id_v08.go
+++ b/core/gethwrappers/generated/solidity_vrf_request_id_v08/solidity_vrf_request_id_v08.go
@@ -50,7 +50,7 @@ func DeployVRFRequestIDBaseTestHelper(auth *bind.TransactOpts, backend bind.Cont
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFRequestIDBaseTestHelper{VRFRequestIDBaseTestHelperCaller: VRFRequestIDBaseTestHelperCaller{contract: contract}, VRFRequestIDBaseTestHelperTransactor: VRFRequestIDBaseTestHelperTransactor{contract: contract}, VRFRequestIDBaseTestHelperFilterer: VRFRequestIDBaseTestHelperFilterer{contract: contract}}, nil
+ return address, tx, &VRFRequestIDBaseTestHelper{address: address, abi: *parsed, VRFRequestIDBaseTestHelperCaller: VRFRequestIDBaseTestHelperCaller{contract: contract}, VRFRequestIDBaseTestHelperTransactor: VRFRequestIDBaseTestHelperTransactor{contract: contract}, VRFRequestIDBaseTestHelperFilterer: VRFRequestIDBaseTestHelperFilterer{contract: contract}}, nil
}
type VRFRequestIDBaseTestHelper struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_v08_verifier_wrapper/solidity_vrf_v08_verifier_wrapper.go b/core/gethwrappers/generated/solidity_vrf_v08_verifier_wrapper/solidity_vrf_v08_verifier_wrapper.go
index 045c30e935..6eaf2b996f 100644
--- a/core/gethwrappers/generated/solidity_vrf_v08_verifier_wrapper/solidity_vrf_v08_verifier_wrapper.go
+++ b/core/gethwrappers/generated/solidity_vrf_v08_verifier_wrapper/solidity_vrf_v08_verifier_wrapper.go
@@ -62,7 +62,7 @@ func DeployVRFV08TestHelper(auth *bind.TransactOpts, backend bind.ContractBacken
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV08TestHelper{VRFV08TestHelperCaller: VRFV08TestHelperCaller{contract: contract}, VRFV08TestHelperTransactor: VRFV08TestHelperTransactor{contract: contract}, VRFV08TestHelperFilterer: VRFV08TestHelperFilterer{contract: contract}}, nil
+ return address, tx, &VRFV08TestHelper{address: address, abi: *parsed, VRFV08TestHelperCaller: VRFV08TestHelperCaller{contract: contract}, VRFV08TestHelperTransactor: VRFV08TestHelperTransactor{contract: contract}, VRFV08TestHelperFilterer: VRFV08TestHelperFilterer{contract: contract}}, nil
}
type VRFV08TestHelper struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_verifier_wrapper/solidity_vrf_verifier_wrapper.go b/core/gethwrappers/generated/solidity_vrf_verifier_wrapper/solidity_vrf_verifier_wrapper.go
index a00768ee1b..b46cc3de08 100644
--- a/core/gethwrappers/generated/solidity_vrf_verifier_wrapper/solidity_vrf_verifier_wrapper.go
+++ b/core/gethwrappers/generated/solidity_vrf_verifier_wrapper/solidity_vrf_verifier_wrapper.go
@@ -50,7 +50,7 @@ func DeployVRFTestHelper(auth *bind.TransactOpts, backend bind.ContractBackend)
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFTestHelper{VRFTestHelperCaller: VRFTestHelperCaller{contract: contract}, VRFTestHelperTransactor: VRFTestHelperTransactor{contract: contract}, VRFTestHelperFilterer: VRFTestHelperFilterer{contract: contract}}, nil
+ return address, tx, &VRFTestHelper{address: address, abi: *parsed, VRFTestHelperCaller: VRFTestHelperCaller{contract: contract}, VRFTestHelperTransactor: VRFTestHelperTransactor{contract: contract}, VRFTestHelperFilterer: VRFTestHelperFilterer{contract: contract}}, nil
}
type VRFTestHelper struct {
diff --git a/core/gethwrappers/generated/solidity_vrf_wrapper/solidity_vrf_wrapper.go b/core/gethwrappers/generated/solidity_vrf_wrapper/solidity_vrf_wrapper.go
index fb16ff3a8b..82199d4538 100644
--- a/core/gethwrappers/generated/solidity_vrf_wrapper/solidity_vrf_wrapper.go
+++ b/core/gethwrappers/generated/solidity_vrf_wrapper/solidity_vrf_wrapper.go
@@ -50,7 +50,7 @@ func DeployVRF(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Ad
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRF{VRFCaller: VRFCaller{contract: contract}, VRFTransactor: VRFTransactor{contract: contract}, VRFFilterer: VRFFilterer{contract: contract}}, nil
+ return address, tx, &VRF{address: address, abi: *parsed, VRFCaller: VRFCaller{contract: contract}, VRFTransactor: VRFTransactor{contract: contract}, VRFFilterer: VRFFilterer{contract: contract}}, nil
}
type VRF struct {
diff --git a/core/gethwrappers/generated/streams_lookup_upkeep_wrapper/streams_lookup_upkeep_wrapper.go b/core/gethwrappers/generated/streams_lookup_upkeep_wrapper/streams_lookup_upkeep_wrapper.go
index 3332ac8215..d54ee36f8f 100644
--- a/core/gethwrappers/generated/streams_lookup_upkeep_wrapper/streams_lookup_upkeep_wrapper.go
+++ b/core/gethwrappers/generated/streams_lookup_upkeep_wrapper/streams_lookup_upkeep_wrapper.go
@@ -52,7 +52,7 @@ func DeployStreamsLookupUpkeep(auth *bind.TransactOpts, backend bind.ContractBac
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &StreamsLookupUpkeep{StreamsLookupUpkeepCaller: StreamsLookupUpkeepCaller{contract: contract}, StreamsLookupUpkeepTransactor: StreamsLookupUpkeepTransactor{contract: contract}, StreamsLookupUpkeepFilterer: StreamsLookupUpkeepFilterer{contract: contract}}, nil
+ return address, tx, &StreamsLookupUpkeep{address: address, abi: *parsed, StreamsLookupUpkeepCaller: StreamsLookupUpkeepCaller{contract: contract}, StreamsLookupUpkeepTransactor: StreamsLookupUpkeepTransactor{contract: contract}, StreamsLookupUpkeepFilterer: StreamsLookupUpkeepFilterer{contract: contract}}, nil
}
type StreamsLookupUpkeep struct {
diff --git a/core/gethwrappers/generated/test_api_consumer_wrapper/test_api_consumer_wrapper.go b/core/gethwrappers/generated/test_api_consumer_wrapper/test_api_consumer_wrapper.go
index 8503d6f75e..71b26af95d 100644
--- a/core/gethwrappers/generated/test_api_consumer_wrapper/test_api_consumer_wrapper.go
+++ b/core/gethwrappers/generated/test_api_consumer_wrapper/test_api_consumer_wrapper.go
@@ -52,7 +52,7 @@ func DeployTestAPIConsumer(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &TestAPIConsumer{TestAPIConsumerCaller: TestAPIConsumerCaller{contract: contract}, TestAPIConsumerTransactor: TestAPIConsumerTransactor{contract: contract}, TestAPIConsumerFilterer: TestAPIConsumerFilterer{contract: contract}}, nil
+ return address, tx, &TestAPIConsumer{address: address, abi: *parsed, TestAPIConsumerCaller: TestAPIConsumerCaller{contract: contract}, TestAPIConsumerTransactor: TestAPIConsumerTransactor{contract: contract}, TestAPIConsumerFilterer: TestAPIConsumerFilterer{contract: contract}}, nil
}
type TestAPIConsumer struct {
diff --git a/core/gethwrappers/generated/trusted_blockhash_store/trusted_blockhash_store.go b/core/gethwrappers/generated/trusted_blockhash_store/trusted_blockhash_store.go
index 43ae1a3f5b..c571b0a700 100644
--- a/core/gethwrappers/generated/trusted_blockhash_store/trusted_blockhash_store.go
+++ b/core/gethwrappers/generated/trusted_blockhash_store/trusted_blockhash_store.go
@@ -52,7 +52,7 @@ func DeployTrustedBlockhashStore(auth *bind.TransactOpts, backend bind.ContractB
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &TrustedBlockhashStore{TrustedBlockhashStoreCaller: TrustedBlockhashStoreCaller{contract: contract}, TrustedBlockhashStoreTransactor: TrustedBlockhashStoreTransactor{contract: contract}, TrustedBlockhashStoreFilterer: TrustedBlockhashStoreFilterer{contract: contract}}, nil
+ return address, tx, &TrustedBlockhashStore{address: address, abi: *parsed, TrustedBlockhashStoreCaller: TrustedBlockhashStoreCaller{contract: contract}, TrustedBlockhashStoreTransactor: TrustedBlockhashStoreTransactor{contract: contract}, TrustedBlockhashStoreFilterer: TrustedBlockhashStoreFilterer{contract: contract}}, nil
}
type TrustedBlockhashStore struct {
diff --git a/core/gethwrappers/generated/upkeep_counter_wrapper/upkeep_counter_wrapper.go b/core/gethwrappers/generated/upkeep_counter_wrapper/upkeep_counter_wrapper.go
index 4f9fe79d77..13db591730 100644
--- a/core/gethwrappers/generated/upkeep_counter_wrapper/upkeep_counter_wrapper.go
+++ b/core/gethwrappers/generated/upkeep_counter_wrapper/upkeep_counter_wrapper.go
@@ -52,7 +52,7 @@ func DeployUpkeepCounter(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &UpkeepCounter{UpkeepCounterCaller: UpkeepCounterCaller{contract: contract}, UpkeepCounterTransactor: UpkeepCounterTransactor{contract: contract}, UpkeepCounterFilterer: UpkeepCounterFilterer{contract: contract}}, nil
+ return address, tx, &UpkeepCounter{address: address, abi: *parsed, UpkeepCounterCaller: UpkeepCounterCaller{contract: contract}, UpkeepCounterTransactor: UpkeepCounterTransactor{contract: contract}, UpkeepCounterFilterer: UpkeepCounterFilterer{contract: contract}}, nil
}
type UpkeepCounter struct {
diff --git a/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper/upkeep_perform_counter_restrictive_wrapper.go b/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper/upkeep_perform_counter_restrictive_wrapper.go
index e6770fd074..e004ab6143 100644
--- a/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper/upkeep_perform_counter_restrictive_wrapper.go
+++ b/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper/upkeep_perform_counter_restrictive_wrapper.go
@@ -52,7 +52,7 @@ func DeployUpkeepPerformCounterRestrictive(auth *bind.TransactOpts, backend bind
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &UpkeepPerformCounterRestrictive{UpkeepPerformCounterRestrictiveCaller: UpkeepPerformCounterRestrictiveCaller{contract: contract}, UpkeepPerformCounterRestrictiveTransactor: UpkeepPerformCounterRestrictiveTransactor{contract: contract}, UpkeepPerformCounterRestrictiveFilterer: UpkeepPerformCounterRestrictiveFilterer{contract: contract}}, nil
+ return address, tx, &UpkeepPerformCounterRestrictive{address: address, abi: *parsed, UpkeepPerformCounterRestrictiveCaller: UpkeepPerformCounterRestrictiveCaller{contract: contract}, UpkeepPerformCounterRestrictiveTransactor: UpkeepPerformCounterRestrictiveTransactor{contract: contract}, UpkeepPerformCounterRestrictiveFilterer: UpkeepPerformCounterRestrictiveFilterer{contract: contract}}, nil
}
type UpkeepPerformCounterRestrictive struct {
diff --git a/core/gethwrappers/generated/upkeep_transcoder/upkeep_transcoder.go b/core/gethwrappers/generated/upkeep_transcoder/upkeep_transcoder.go
index a439dddd40..53d557d79a 100644
--- a/core/gethwrappers/generated/upkeep_transcoder/upkeep_transcoder.go
+++ b/core/gethwrappers/generated/upkeep_transcoder/upkeep_transcoder.go
@@ -50,7 +50,7 @@ func DeployUpkeepTranscoder(auth *bind.TransactOpts, backend bind.ContractBacken
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &UpkeepTranscoder{UpkeepTranscoderCaller: UpkeepTranscoderCaller{contract: contract}, UpkeepTranscoderTransactor: UpkeepTranscoderTransactor{contract: contract}, UpkeepTranscoderFilterer: UpkeepTranscoderFilterer{contract: contract}}, nil
+ return address, tx, &UpkeepTranscoder{address: address, abi: *parsed, UpkeepTranscoderCaller: UpkeepTranscoderCaller{contract: contract}, UpkeepTranscoderTransactor: UpkeepTranscoderTransactor{contract: contract}, UpkeepTranscoderFilterer: UpkeepTranscoderFilterer{contract: contract}}, nil
}
type UpkeepTranscoder struct {
diff --git a/core/gethwrappers/generated/verifiable_load_log_trigger_upkeep_wrapper/verifiable_load_log_trigger_upkeep_wrapper.go b/core/gethwrappers/generated/verifiable_load_log_trigger_upkeep_wrapper/verifiable_load_log_trigger_upkeep_wrapper.go
index 52e241965f..9648c4bd71 100644
--- a/core/gethwrappers/generated/verifiable_load_log_trigger_upkeep_wrapper/verifiable_load_log_trigger_upkeep_wrapper.go
+++ b/core/gethwrappers/generated/verifiable_load_log_trigger_upkeep_wrapper/verifiable_load_log_trigger_upkeep_wrapper.go
@@ -76,7 +76,7 @@ func DeployVerifiableLoadLogTriggerUpkeep(auth *bind.TransactOpts, backend bind.
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VerifiableLoadLogTriggerUpkeep{VerifiableLoadLogTriggerUpkeepCaller: VerifiableLoadLogTriggerUpkeepCaller{contract: contract}, VerifiableLoadLogTriggerUpkeepTransactor: VerifiableLoadLogTriggerUpkeepTransactor{contract: contract}, VerifiableLoadLogTriggerUpkeepFilterer: VerifiableLoadLogTriggerUpkeepFilterer{contract: contract}}, nil
+ return address, tx, &VerifiableLoadLogTriggerUpkeep{address: address, abi: *parsed, VerifiableLoadLogTriggerUpkeepCaller: VerifiableLoadLogTriggerUpkeepCaller{contract: contract}, VerifiableLoadLogTriggerUpkeepTransactor: VerifiableLoadLogTriggerUpkeepTransactor{contract: contract}, VerifiableLoadLogTriggerUpkeepFilterer: VerifiableLoadLogTriggerUpkeepFilterer{contract: contract}}, nil
}
type VerifiableLoadLogTriggerUpkeep struct {
diff --git a/core/gethwrappers/generated/verifiable_load_streams_lookup_upkeep_wrapper/verifiable_load_streams_lookup_upkeep_wrapper.go b/core/gethwrappers/generated/verifiable_load_streams_lookup_upkeep_wrapper/verifiable_load_streams_lookup_upkeep_wrapper.go
index e8a10d85dd..fc39ffb366 100644
--- a/core/gethwrappers/generated/verifiable_load_streams_lookup_upkeep_wrapper/verifiable_load_streams_lookup_upkeep_wrapper.go
+++ b/core/gethwrappers/generated/verifiable_load_streams_lookup_upkeep_wrapper/verifiable_load_streams_lookup_upkeep_wrapper.go
@@ -65,7 +65,7 @@ func DeployVerifiableLoadStreamsLookupUpkeep(auth *bind.TransactOpts, backend bi
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VerifiableLoadStreamsLookupUpkeep{VerifiableLoadStreamsLookupUpkeepCaller: VerifiableLoadStreamsLookupUpkeepCaller{contract: contract}, VerifiableLoadStreamsLookupUpkeepTransactor: VerifiableLoadStreamsLookupUpkeepTransactor{contract: contract}, VerifiableLoadStreamsLookupUpkeepFilterer: VerifiableLoadStreamsLookupUpkeepFilterer{contract: contract}}, nil
+ return address, tx, &VerifiableLoadStreamsLookupUpkeep{address: address, abi: *parsed, VerifiableLoadStreamsLookupUpkeepCaller: VerifiableLoadStreamsLookupUpkeepCaller{contract: contract}, VerifiableLoadStreamsLookupUpkeepTransactor: VerifiableLoadStreamsLookupUpkeepTransactor{contract: contract}, VerifiableLoadStreamsLookupUpkeepFilterer: VerifiableLoadStreamsLookupUpkeepFilterer{contract: contract}}, nil
}
type VerifiableLoadStreamsLookupUpkeep struct {
diff --git a/core/gethwrappers/generated/verifiable_load_upkeep_wrapper/verifiable_load_upkeep_wrapper.go b/core/gethwrappers/generated/verifiable_load_upkeep_wrapper/verifiable_load_upkeep_wrapper.go
index 6dc8e73f1f..b95f311f1c 100644
--- a/core/gethwrappers/generated/verifiable_load_upkeep_wrapper/verifiable_load_upkeep_wrapper.go
+++ b/core/gethwrappers/generated/verifiable_load_upkeep_wrapper/verifiable_load_upkeep_wrapper.go
@@ -65,7 +65,7 @@ func DeployVerifiableLoadUpkeep(auth *bind.TransactOpts, backend bind.ContractBa
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VerifiableLoadUpkeep{VerifiableLoadUpkeepCaller: VerifiableLoadUpkeepCaller{contract: contract}, VerifiableLoadUpkeepTransactor: VerifiableLoadUpkeepTransactor{contract: contract}, VerifiableLoadUpkeepFilterer: VerifiableLoadUpkeepFilterer{contract: contract}}, nil
+ return address, tx, &VerifiableLoadUpkeep{address: address, abi: *parsed, VerifiableLoadUpkeepCaller: VerifiableLoadUpkeepCaller{contract: contract}, VerifiableLoadUpkeepTransactor: VerifiableLoadUpkeepTransactor{contract: contract}, VerifiableLoadUpkeepFilterer: VerifiableLoadUpkeepFilterer{contract: contract}}, nil
}
type VerifiableLoadUpkeep struct {
diff --git a/core/gethwrappers/generated/vrf_consumer_v2/vrf_consumer_v2.go b/core/gethwrappers/generated/vrf_consumer_v2/vrf_consumer_v2.go
index 8317e4c5b3..16090150fc 100644
--- a/core/gethwrappers/generated/vrf_consumer_v2/vrf_consumer_v2.go
+++ b/core/gethwrappers/generated/vrf_consumer_v2/vrf_consumer_v2.go
@@ -50,7 +50,7 @@ func DeployVRFConsumerV2(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFConsumerV2{VRFConsumerV2Caller: VRFConsumerV2Caller{contract: contract}, VRFConsumerV2Transactor: VRFConsumerV2Transactor{contract: contract}, VRFConsumerV2Filterer: VRFConsumerV2Filterer{contract: contract}}, nil
+ return address, tx, &VRFConsumerV2{address: address, abi: *parsed, VRFConsumerV2Caller: VRFConsumerV2Caller{contract: contract}, VRFConsumerV2Transactor: VRFConsumerV2Transactor{contract: contract}, VRFConsumerV2Filterer: VRFConsumerV2Filterer{contract: contract}}, nil
}
type VRFConsumerV2 struct {
diff --git a/core/gethwrappers/generated/vrf_consumer_v2_plus_upgradeable_example/vrf_consumer_v2_plus_upgradeable_example.go b/core/gethwrappers/generated/vrf_consumer_v2_plus_upgradeable_example/vrf_consumer_v2_plus_upgradeable_example.go
index fce0876ba3..deb678c4eb 100644
--- a/core/gethwrappers/generated/vrf_consumer_v2_plus_upgradeable_example/vrf_consumer_v2_plus_upgradeable_example.go
+++ b/core/gethwrappers/generated/vrf_consumer_v2_plus_upgradeable_example/vrf_consumer_v2_plus_upgradeable_example.go
@@ -52,7 +52,7 @@ func DeployVRFConsumerV2PlusUpgradeableExample(auth *bind.TransactOpts, backend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFConsumerV2PlusUpgradeableExample{VRFConsumerV2PlusUpgradeableExampleCaller: VRFConsumerV2PlusUpgradeableExampleCaller{contract: contract}, VRFConsumerV2PlusUpgradeableExampleTransactor: VRFConsumerV2PlusUpgradeableExampleTransactor{contract: contract}, VRFConsumerV2PlusUpgradeableExampleFilterer: VRFConsumerV2PlusUpgradeableExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFConsumerV2PlusUpgradeableExample{address: address, abi: *parsed, VRFConsumerV2PlusUpgradeableExampleCaller: VRFConsumerV2PlusUpgradeableExampleCaller{contract: contract}, VRFConsumerV2PlusUpgradeableExampleTransactor: VRFConsumerV2PlusUpgradeableExampleTransactor{contract: contract}, VRFConsumerV2PlusUpgradeableExampleFilterer: VRFConsumerV2PlusUpgradeableExampleFilterer{contract: contract}}, nil
}
type VRFConsumerV2PlusUpgradeableExample struct {
diff --git a/core/gethwrappers/generated/vrf_consumer_v2_upgradeable_example/vrf_consumer_v2_upgradeable_example.go b/core/gethwrappers/generated/vrf_consumer_v2_upgradeable_example/vrf_consumer_v2_upgradeable_example.go
index 72bdbce58a..5499868e32 100644
--- a/core/gethwrappers/generated/vrf_consumer_v2_upgradeable_example/vrf_consumer_v2_upgradeable_example.go
+++ b/core/gethwrappers/generated/vrf_consumer_v2_upgradeable_example/vrf_consumer_v2_upgradeable_example.go
@@ -52,7 +52,7 @@ func DeployVRFConsumerV2UpgradeableExample(auth *bind.TransactOpts, backend bind
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFConsumerV2UpgradeableExample{VRFConsumerV2UpgradeableExampleCaller: VRFConsumerV2UpgradeableExampleCaller{contract: contract}, VRFConsumerV2UpgradeableExampleTransactor: VRFConsumerV2UpgradeableExampleTransactor{contract: contract}, VRFConsumerV2UpgradeableExampleFilterer: VRFConsumerV2UpgradeableExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFConsumerV2UpgradeableExample{address: address, abi: *parsed, VRFConsumerV2UpgradeableExampleCaller: VRFConsumerV2UpgradeableExampleCaller{contract: contract}, VRFConsumerV2UpgradeableExampleTransactor: VRFConsumerV2UpgradeableExampleTransactor{contract: contract}, VRFConsumerV2UpgradeableExampleFilterer: VRFConsumerV2UpgradeableExampleFilterer{contract: contract}}, nil
}
type VRFConsumerV2UpgradeableExample struct {
diff --git a/core/gethwrappers/generated/vrf_coordinator_mock/vrf_coordinator_mock.go b/core/gethwrappers/generated/vrf_coordinator_mock/vrf_coordinator_mock.go
index 35fbabc8e2..961aa7b30c 100644
--- a/core/gethwrappers/generated/vrf_coordinator_mock/vrf_coordinator_mock.go
+++ b/core/gethwrappers/generated/vrf_coordinator_mock/vrf_coordinator_mock.go
@@ -52,7 +52,7 @@ func DeployVRFCoordinatorMock(auth *bind.TransactOpts, backend bind.ContractBack
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFCoordinatorMock{VRFCoordinatorMockCaller: VRFCoordinatorMockCaller{contract: contract}, VRFCoordinatorMockTransactor: VRFCoordinatorMockTransactor{contract: contract}, VRFCoordinatorMockFilterer: VRFCoordinatorMockFilterer{contract: contract}}, nil
+ return address, tx, &VRFCoordinatorMock{address: address, abi: *parsed, VRFCoordinatorMockCaller: VRFCoordinatorMockCaller{contract: contract}, VRFCoordinatorMockTransactor: VRFCoordinatorMockTransactor{contract: contract}, VRFCoordinatorMockFilterer: VRFCoordinatorMockFilterer{contract: contract}}, nil
}
type VRFCoordinatorMock struct {
diff --git a/core/gethwrappers/generated/vrf_coordinator_v2/vrf_coordinator_v2.go b/core/gethwrappers/generated/vrf_coordinator_v2/vrf_coordinator_v2.go
index 1f9ef1eda2..ffe32f7810 100644
--- a/core/gethwrappers/generated/vrf_coordinator_v2/vrf_coordinator_v2.go
+++ b/core/gethwrappers/generated/vrf_coordinator_v2/vrf_coordinator_v2.go
@@ -84,7 +84,7 @@ func DeployVRFCoordinatorV2(auth *bind.TransactOpts, backend bind.ContractBacken
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFCoordinatorV2{VRFCoordinatorV2Caller: VRFCoordinatorV2Caller{contract: contract}, VRFCoordinatorV2Transactor: VRFCoordinatorV2Transactor{contract: contract}, VRFCoordinatorV2Filterer: VRFCoordinatorV2Filterer{contract: contract}}, nil
+ return address, tx, &VRFCoordinatorV2{address: address, abi: *parsed, VRFCoordinatorV2Caller: VRFCoordinatorV2Caller{contract: contract}, VRFCoordinatorV2Transactor: VRFCoordinatorV2Transactor{contract: contract}, VRFCoordinatorV2Filterer: VRFCoordinatorV2Filterer{contract: contract}}, nil
}
type VRFCoordinatorV2 struct {
diff --git a/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go b/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go
index e09c7c46e2..62e8b9f0de 100644
--- a/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go
+++ b/core/gethwrappers/generated/vrf_coordinator_v2_5/vrf_coordinator_v2_5.go
@@ -87,7 +87,7 @@ func DeployVRFCoordinatorV25(auth *bind.TransactOpts, backend bind.ContractBacke
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFCoordinatorV25{VRFCoordinatorV25Caller: VRFCoordinatorV25Caller{contract: contract}, VRFCoordinatorV25Transactor: VRFCoordinatorV25Transactor{contract: contract}, VRFCoordinatorV25Filterer: VRFCoordinatorV25Filterer{contract: contract}}, nil
+ return address, tx, &VRFCoordinatorV25{address: address, abi: *parsed, VRFCoordinatorV25Caller: VRFCoordinatorV25Caller{contract: contract}, VRFCoordinatorV25Transactor: VRFCoordinatorV25Transactor{contract: contract}, VRFCoordinatorV25Filterer: VRFCoordinatorV25Filterer{contract: contract}}, nil
}
type VRFCoordinatorV25 struct {
diff --git a/core/gethwrappers/generated/vrf_coordinator_v2_plus_v2_example/vrf_coordinator_v2_plus_v2_example.go b/core/gethwrappers/generated/vrf_coordinator_v2_plus_v2_example/vrf_coordinator_v2_plus_v2_example.go
index dd7865fe8a..3d9efea9f7 100644
--- a/core/gethwrappers/generated/vrf_coordinator_v2_plus_v2_example/vrf_coordinator_v2_plus_v2_example.go
+++ b/core/gethwrappers/generated/vrf_coordinator_v2_plus_v2_example/vrf_coordinator_v2_plus_v2_example.go
@@ -59,7 +59,7 @@ func DeployVRFCoordinatorV2PlusV2Example(auth *bind.TransactOpts, backend bind.C
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFCoordinatorV2PlusV2Example{VRFCoordinatorV2PlusV2ExampleCaller: VRFCoordinatorV2PlusV2ExampleCaller{contract: contract}, VRFCoordinatorV2PlusV2ExampleTransactor: VRFCoordinatorV2PlusV2ExampleTransactor{contract: contract}, VRFCoordinatorV2PlusV2ExampleFilterer: VRFCoordinatorV2PlusV2ExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFCoordinatorV2PlusV2Example{address: address, abi: *parsed, VRFCoordinatorV2PlusV2ExampleCaller: VRFCoordinatorV2PlusV2ExampleCaller{contract: contract}, VRFCoordinatorV2PlusV2ExampleTransactor: VRFCoordinatorV2PlusV2ExampleTransactor{contract: contract}, VRFCoordinatorV2PlusV2ExampleFilterer: VRFCoordinatorV2PlusV2ExampleFilterer{contract: contract}}, nil
}
type VRFCoordinatorV2PlusV2Example struct {
diff --git a/core/gethwrappers/generated/vrf_external_sub_owner_example/vrf_external_sub_owner_example.go b/core/gethwrappers/generated/vrf_external_sub_owner_example/vrf_external_sub_owner_example.go
index 8752e2f39c..4ab3cdf591 100644
--- a/core/gethwrappers/generated/vrf_external_sub_owner_example/vrf_external_sub_owner_example.go
+++ b/core/gethwrappers/generated/vrf_external_sub_owner_example/vrf_external_sub_owner_example.go
@@ -50,7 +50,7 @@ func DeployVRFExternalSubOwnerExample(auth *bind.TransactOpts, backend bind.Cont
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFExternalSubOwnerExample{VRFExternalSubOwnerExampleCaller: VRFExternalSubOwnerExampleCaller{contract: contract}, VRFExternalSubOwnerExampleTransactor: VRFExternalSubOwnerExampleTransactor{contract: contract}, VRFExternalSubOwnerExampleFilterer: VRFExternalSubOwnerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFExternalSubOwnerExample{address: address, abi: *parsed, VRFExternalSubOwnerExampleCaller: VRFExternalSubOwnerExampleCaller{contract: contract}, VRFExternalSubOwnerExampleTransactor: VRFExternalSubOwnerExampleTransactor{contract: contract}, VRFExternalSubOwnerExampleFilterer: VRFExternalSubOwnerExampleFilterer{contract: contract}}, nil
}
type VRFExternalSubOwnerExample struct {
diff --git a/core/gethwrappers/generated/vrf_load_test_external_sub_owner/vrf_load_test_external_sub_owner.go b/core/gethwrappers/generated/vrf_load_test_external_sub_owner/vrf_load_test_external_sub_owner.go
index ea3302d2e7..e98239eb4e 100644
--- a/core/gethwrappers/generated/vrf_load_test_external_sub_owner/vrf_load_test_external_sub_owner.go
+++ b/core/gethwrappers/generated/vrf_load_test_external_sub_owner/vrf_load_test_external_sub_owner.go
@@ -52,7 +52,7 @@ func DeployVRFLoadTestExternalSubOwner(auth *bind.TransactOpts, backend bind.Con
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFLoadTestExternalSubOwner{VRFLoadTestExternalSubOwnerCaller: VRFLoadTestExternalSubOwnerCaller{contract: contract}, VRFLoadTestExternalSubOwnerTransactor: VRFLoadTestExternalSubOwnerTransactor{contract: contract}, VRFLoadTestExternalSubOwnerFilterer: VRFLoadTestExternalSubOwnerFilterer{contract: contract}}, nil
+ return address, tx, &VRFLoadTestExternalSubOwner{address: address, abi: *parsed, VRFLoadTestExternalSubOwnerCaller: VRFLoadTestExternalSubOwnerCaller{contract: contract}, VRFLoadTestExternalSubOwnerTransactor: VRFLoadTestExternalSubOwnerTransactor{contract: contract}, VRFLoadTestExternalSubOwnerFilterer: VRFLoadTestExternalSubOwnerFilterer{contract: contract}}, nil
}
type VRFLoadTestExternalSubOwner struct {
diff --git a/core/gethwrappers/generated/vrf_load_test_ownerless_consumer/vrf_load_test_ownerless_consumer.go b/core/gethwrappers/generated/vrf_load_test_ownerless_consumer/vrf_load_test_ownerless_consumer.go
index 6beadf5ad5..fea4360e50 100644
--- a/core/gethwrappers/generated/vrf_load_test_ownerless_consumer/vrf_load_test_ownerless_consumer.go
+++ b/core/gethwrappers/generated/vrf_load_test_ownerless_consumer/vrf_load_test_ownerless_consumer.go
@@ -50,7 +50,7 @@ func DeployVRFLoadTestOwnerlessConsumer(auth *bind.TransactOpts, backend bind.Co
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFLoadTestOwnerlessConsumer{VRFLoadTestOwnerlessConsumerCaller: VRFLoadTestOwnerlessConsumerCaller{contract: contract}, VRFLoadTestOwnerlessConsumerTransactor: VRFLoadTestOwnerlessConsumerTransactor{contract: contract}, VRFLoadTestOwnerlessConsumerFilterer: VRFLoadTestOwnerlessConsumerFilterer{contract: contract}}, nil
+ return address, tx, &VRFLoadTestOwnerlessConsumer{address: address, abi: *parsed, VRFLoadTestOwnerlessConsumerCaller: VRFLoadTestOwnerlessConsumerCaller{contract: contract}, VRFLoadTestOwnerlessConsumerTransactor: VRFLoadTestOwnerlessConsumerTransactor{contract: contract}, VRFLoadTestOwnerlessConsumerFilterer: VRFLoadTestOwnerlessConsumerFilterer{contract: contract}}, nil
}
type VRFLoadTestOwnerlessConsumer struct {
diff --git a/core/gethwrappers/generated/vrf_load_test_with_metrics/vrf_load_test_with_metrics.go b/core/gethwrappers/generated/vrf_load_test_with_metrics/vrf_load_test_with_metrics.go
index 93d50b72dd..76b5e267d3 100644
--- a/core/gethwrappers/generated/vrf_load_test_with_metrics/vrf_load_test_with_metrics.go
+++ b/core/gethwrappers/generated/vrf_load_test_with_metrics/vrf_load_test_with_metrics.go
@@ -52,7 +52,7 @@ func DeployVRFV2LoadTestWithMetrics(auth *bind.TransactOpts, backend bind.Contra
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2LoadTestWithMetrics{VRFV2LoadTestWithMetricsCaller: VRFV2LoadTestWithMetricsCaller{contract: contract}, VRFV2LoadTestWithMetricsTransactor: VRFV2LoadTestWithMetricsTransactor{contract: contract}, VRFV2LoadTestWithMetricsFilterer: VRFV2LoadTestWithMetricsFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2LoadTestWithMetrics{address: address, abi: *parsed, VRFV2LoadTestWithMetricsCaller: VRFV2LoadTestWithMetricsCaller{contract: contract}, VRFV2LoadTestWithMetricsTransactor: VRFV2LoadTestWithMetricsTransactor{contract: contract}, VRFV2LoadTestWithMetricsFilterer: VRFV2LoadTestWithMetricsFilterer{contract: contract}}, nil
}
type VRFV2LoadTestWithMetrics struct {
diff --git a/core/gethwrappers/generated/vrf_malicious_consumer_v2/vrf_malicious_consumer_v2.go b/core/gethwrappers/generated/vrf_malicious_consumer_v2/vrf_malicious_consumer_v2.go
index 5fb16e00e8..1fe5e61f3a 100644
--- a/core/gethwrappers/generated/vrf_malicious_consumer_v2/vrf_malicious_consumer_v2.go
+++ b/core/gethwrappers/generated/vrf_malicious_consumer_v2/vrf_malicious_consumer_v2.go
@@ -50,7 +50,7 @@ func DeployVRFMaliciousConsumerV2(auth *bind.TransactOpts, backend bind.Contract
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFMaliciousConsumerV2{VRFMaliciousConsumerV2Caller: VRFMaliciousConsumerV2Caller{contract: contract}, VRFMaliciousConsumerV2Transactor: VRFMaliciousConsumerV2Transactor{contract: contract}, VRFMaliciousConsumerV2Filterer: VRFMaliciousConsumerV2Filterer{contract: contract}}, nil
+ return address, tx, &VRFMaliciousConsumerV2{address: address, abi: *parsed, VRFMaliciousConsumerV2Caller: VRFMaliciousConsumerV2Caller{contract: contract}, VRFMaliciousConsumerV2Transactor: VRFMaliciousConsumerV2Transactor{contract: contract}, VRFMaliciousConsumerV2Filterer: VRFMaliciousConsumerV2Filterer{contract: contract}}, nil
}
type VRFMaliciousConsumerV2 struct {
diff --git a/core/gethwrappers/generated/vrf_malicious_consumer_v2_plus/vrf_malicious_consumer_v2_plus.go b/core/gethwrappers/generated/vrf_malicious_consumer_v2_plus/vrf_malicious_consumer_v2_plus.go
index 64a5cace7f..df5a49a8de 100644
--- a/core/gethwrappers/generated/vrf_malicious_consumer_v2_plus/vrf_malicious_consumer_v2_plus.go
+++ b/core/gethwrappers/generated/vrf_malicious_consumer_v2_plus/vrf_malicious_consumer_v2_plus.go
@@ -52,7 +52,7 @@ func DeployVRFMaliciousConsumerV2Plus(auth *bind.TransactOpts, backend bind.Cont
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFMaliciousConsumerV2Plus{VRFMaliciousConsumerV2PlusCaller: VRFMaliciousConsumerV2PlusCaller{contract: contract}, VRFMaliciousConsumerV2PlusTransactor: VRFMaliciousConsumerV2PlusTransactor{contract: contract}, VRFMaliciousConsumerV2PlusFilterer: VRFMaliciousConsumerV2PlusFilterer{contract: contract}}, nil
+ return address, tx, &VRFMaliciousConsumerV2Plus{address: address, abi: *parsed, VRFMaliciousConsumerV2PlusCaller: VRFMaliciousConsumerV2PlusCaller{contract: contract}, VRFMaliciousConsumerV2PlusTransactor: VRFMaliciousConsumerV2PlusTransactor{contract: contract}, VRFMaliciousConsumerV2PlusFilterer: VRFMaliciousConsumerV2PlusFilterer{contract: contract}}, nil
}
type VRFMaliciousConsumerV2Plus struct {
diff --git a/core/gethwrappers/generated/vrf_owner/vrf_owner.go b/core/gethwrappers/generated/vrf_owner/vrf_owner.go
index 8a97fcf5aa..b029bd393f 100644
--- a/core/gethwrappers/generated/vrf_owner/vrf_owner.go
+++ b/core/gethwrappers/generated/vrf_owner/vrf_owner.go
@@ -84,7 +84,7 @@ func DeployVRFOwner(auth *bind.TransactOpts, backend bind.ContractBackend, _vrfC
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFOwner{VRFOwnerCaller: VRFOwnerCaller{contract: contract}, VRFOwnerTransactor: VRFOwnerTransactor{contract: contract}, VRFOwnerFilterer: VRFOwnerFilterer{contract: contract}}, nil
+ return address, tx, &VRFOwner{address: address, abi: *parsed, VRFOwnerCaller: VRFOwnerCaller{contract: contract}, VRFOwnerTransactor: VRFOwnerTransactor{contract: contract}, VRFOwnerFilterer: VRFOwnerFilterer{contract: contract}}, nil
}
type VRFOwner struct {
diff --git a/core/gethwrappers/generated/vrf_owner_test_consumer/vrf_owner_test_consumer.go b/core/gethwrappers/generated/vrf_owner_test_consumer/vrf_owner_test_consumer.go
index ce42ddb7d6..8a17b64378 100644
--- a/core/gethwrappers/generated/vrf_owner_test_consumer/vrf_owner_test_consumer.go
+++ b/core/gethwrappers/generated/vrf_owner_test_consumer/vrf_owner_test_consumer.go
@@ -52,7 +52,7 @@ func DeployVRFV2OwnerTestConsumer(auth *bind.TransactOpts, backend bind.Contract
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2OwnerTestConsumer{VRFV2OwnerTestConsumerCaller: VRFV2OwnerTestConsumerCaller{contract: contract}, VRFV2OwnerTestConsumerTransactor: VRFV2OwnerTestConsumerTransactor{contract: contract}, VRFV2OwnerTestConsumerFilterer: VRFV2OwnerTestConsumerFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2OwnerTestConsumer{address: address, abi: *parsed, VRFV2OwnerTestConsumerCaller: VRFV2OwnerTestConsumerCaller{contract: contract}, VRFV2OwnerTestConsumerTransactor: VRFV2OwnerTestConsumerTransactor{contract: contract}, VRFV2OwnerTestConsumerFilterer: VRFV2OwnerTestConsumerFilterer{contract: contract}}, nil
}
type VRFV2OwnerTestConsumer struct {
diff --git a/core/gethwrappers/generated/vrf_ownerless_consumer_example/vrf_ownerless_consumer_example.go b/core/gethwrappers/generated/vrf_ownerless_consumer_example/vrf_ownerless_consumer_example.go
index c71553ac81..697a862533 100644
--- a/core/gethwrappers/generated/vrf_ownerless_consumer_example/vrf_ownerless_consumer_example.go
+++ b/core/gethwrappers/generated/vrf_ownerless_consumer_example/vrf_ownerless_consumer_example.go
@@ -50,7 +50,7 @@ func DeployVRFOwnerlessConsumerExample(auth *bind.TransactOpts, backend bind.Con
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFOwnerlessConsumerExample{VRFOwnerlessConsumerExampleCaller: VRFOwnerlessConsumerExampleCaller{contract: contract}, VRFOwnerlessConsumerExampleTransactor: VRFOwnerlessConsumerExampleTransactor{contract: contract}, VRFOwnerlessConsumerExampleFilterer: VRFOwnerlessConsumerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFOwnerlessConsumerExample{address: address, abi: *parsed, VRFOwnerlessConsumerExampleCaller: VRFOwnerlessConsumerExampleCaller{contract: contract}, VRFOwnerlessConsumerExampleTransactor: VRFOwnerlessConsumerExampleTransactor{contract: contract}, VRFOwnerlessConsumerExampleFilterer: VRFOwnerlessConsumerExampleFilterer{contract: contract}}, nil
}
type VRFOwnerlessConsumerExample struct {
diff --git a/core/gethwrappers/generated/vrf_single_consumer_example/vrf_single_consumer_example.go b/core/gethwrappers/generated/vrf_single_consumer_example/vrf_single_consumer_example.go
index affc8c5371..ac5c081ab3 100644
--- a/core/gethwrappers/generated/vrf_single_consumer_example/vrf_single_consumer_example.go
+++ b/core/gethwrappers/generated/vrf_single_consumer_example/vrf_single_consumer_example.go
@@ -50,7 +50,7 @@ func DeployVRFSingleConsumerExample(auth *bind.TransactOpts, backend bind.Contra
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFSingleConsumerExample{VRFSingleConsumerExampleCaller: VRFSingleConsumerExampleCaller{contract: contract}, VRFSingleConsumerExampleTransactor: VRFSingleConsumerExampleTransactor{contract: contract}, VRFSingleConsumerExampleFilterer: VRFSingleConsumerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFSingleConsumerExample{address: address, abi: *parsed, VRFSingleConsumerExampleCaller: VRFSingleConsumerExampleCaller{contract: contract}, VRFSingleConsumerExampleTransactor: VRFSingleConsumerExampleTransactor{contract: contract}, VRFSingleConsumerExampleFilterer: VRFSingleConsumerExampleFilterer{contract: contract}}, nil
}
type VRFSingleConsumerExample struct {
diff --git a/core/gethwrappers/generated/vrf_v2_consumer_wrapper/vrf_v2_consumer_wrapper.go b/core/gethwrappers/generated/vrf_v2_consumer_wrapper/vrf_v2_consumer_wrapper.go
index a5d5794580..e35efc9ec8 100644
--- a/core/gethwrappers/generated/vrf_v2_consumer_wrapper/vrf_v2_consumer_wrapper.go
+++ b/core/gethwrappers/generated/vrf_v2_consumer_wrapper/vrf_v2_consumer_wrapper.go
@@ -52,7 +52,7 @@ func DeployVRFv2Consumer(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFv2Consumer{VRFv2ConsumerCaller: VRFv2ConsumerCaller{contract: contract}, VRFv2ConsumerTransactor: VRFv2ConsumerTransactor{contract: contract}, VRFv2ConsumerFilterer: VRFv2ConsumerFilterer{contract: contract}}, nil
+ return address, tx, &VRFv2Consumer{address: address, abi: *parsed, VRFv2ConsumerCaller: VRFv2ConsumerCaller{contract: contract}, VRFv2ConsumerTransactor: VRFv2ConsumerTransactor{contract: contract}, VRFv2ConsumerFilterer: VRFv2ConsumerFilterer{contract: contract}}, nil
}
type VRFv2Consumer struct {
diff --git a/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics/vrf_v2plus_load_test_with_metrics.go b/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics/vrf_v2plus_load_test_with_metrics.go
index c8971595c5..017423772f 100644
--- a/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics/vrf_v2plus_load_test_with_metrics.go
+++ b/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics/vrf_v2plus_load_test_with_metrics.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusLoadTestWithMetrics(auth *bind.TransactOpts, backend bind.Co
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusLoadTestWithMetrics{VRFV2PlusLoadTestWithMetricsCaller: VRFV2PlusLoadTestWithMetricsCaller{contract: contract}, VRFV2PlusLoadTestWithMetricsTransactor: VRFV2PlusLoadTestWithMetricsTransactor{contract: contract}, VRFV2PlusLoadTestWithMetricsFilterer: VRFV2PlusLoadTestWithMetricsFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusLoadTestWithMetrics{address: address, abi: *parsed, VRFV2PlusLoadTestWithMetricsCaller: VRFV2PlusLoadTestWithMetricsCaller{contract: contract}, VRFV2PlusLoadTestWithMetricsTransactor: VRFV2PlusLoadTestWithMetricsTransactor{contract: contract}, VRFV2PlusLoadTestWithMetricsFilterer: VRFV2PlusLoadTestWithMetricsFilterer{contract: contract}}, nil
}
type VRFV2PlusLoadTestWithMetrics struct {
diff --git a/core/gethwrappers/generated/vrf_v2plus_single_consumer/vrf_v2plus_single_consumer.go b/core/gethwrappers/generated/vrf_v2plus_single_consumer/vrf_v2plus_single_consumer.go
index afa659269d..b9de348b10 100644
--- a/core/gethwrappers/generated/vrf_v2plus_single_consumer/vrf_v2plus_single_consumer.go
+++ b/core/gethwrappers/generated/vrf_v2plus_single_consumer/vrf_v2plus_single_consumer.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusSingleConsumerExample(auth *bind.TransactOpts, backend bind.
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusSingleConsumerExample{VRFV2PlusSingleConsumerExampleCaller: VRFV2PlusSingleConsumerExampleCaller{contract: contract}, VRFV2PlusSingleConsumerExampleTransactor: VRFV2PlusSingleConsumerExampleTransactor{contract: contract}, VRFV2PlusSingleConsumerExampleFilterer: VRFV2PlusSingleConsumerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusSingleConsumerExample{address: address, abi: *parsed, VRFV2PlusSingleConsumerExampleCaller: VRFV2PlusSingleConsumerExampleCaller{contract: contract}, VRFV2PlusSingleConsumerExampleTransactor: VRFV2PlusSingleConsumerExampleTransactor{contract: contract}, VRFV2PlusSingleConsumerExampleFilterer: VRFV2PlusSingleConsumerExampleFilterer{contract: contract}}, nil
}
type VRFV2PlusSingleConsumerExample struct {
diff --git a/core/gethwrappers/generated/vrf_v2plus_sub_owner/vrf_v2plus_sub_owner.go b/core/gethwrappers/generated/vrf_v2plus_sub_owner/vrf_v2plus_sub_owner.go
index da32a6a202..8cc57fce6c 100644
--- a/core/gethwrappers/generated/vrf_v2plus_sub_owner/vrf_v2plus_sub_owner.go
+++ b/core/gethwrappers/generated/vrf_v2plus_sub_owner/vrf_v2plus_sub_owner.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusExternalSubOwnerExample(auth *bind.TransactOpts, backend bin
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusExternalSubOwnerExample{VRFV2PlusExternalSubOwnerExampleCaller: VRFV2PlusExternalSubOwnerExampleCaller{contract: contract}, VRFV2PlusExternalSubOwnerExampleTransactor: VRFV2PlusExternalSubOwnerExampleTransactor{contract: contract}, VRFV2PlusExternalSubOwnerExampleFilterer: VRFV2PlusExternalSubOwnerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusExternalSubOwnerExample{address: address, abi: *parsed, VRFV2PlusExternalSubOwnerExampleCaller: VRFV2PlusExternalSubOwnerExampleCaller{contract: contract}, VRFV2PlusExternalSubOwnerExampleTransactor: VRFV2PlusExternalSubOwnerExampleTransactor{contract: contract}, VRFV2PlusExternalSubOwnerExampleFilterer: VRFV2PlusExternalSubOwnerExampleFilterer{contract: contract}}, nil
}
type VRFV2PlusExternalSubOwnerExample struct {
diff --git a/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go b/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go
index 852501d09e..7aae3d3777 100644
--- a/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go
+++ b/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go
@@ -87,7 +87,7 @@ func DeployVRFCoordinatorV2PlusUpgradedVersion(auth *bind.TransactOpts, backend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFCoordinatorV2PlusUpgradedVersion{VRFCoordinatorV2PlusUpgradedVersionCaller: VRFCoordinatorV2PlusUpgradedVersionCaller{contract: contract}, VRFCoordinatorV2PlusUpgradedVersionTransactor: VRFCoordinatorV2PlusUpgradedVersionTransactor{contract: contract}, VRFCoordinatorV2PlusUpgradedVersionFilterer: VRFCoordinatorV2PlusUpgradedVersionFilterer{contract: contract}}, nil
+ return address, tx, &VRFCoordinatorV2PlusUpgradedVersion{address: address, abi: *parsed, VRFCoordinatorV2PlusUpgradedVersionCaller: VRFCoordinatorV2PlusUpgradedVersionCaller{contract: contract}, VRFCoordinatorV2PlusUpgradedVersionTransactor: VRFCoordinatorV2PlusUpgradedVersionTransactor{contract: contract}, VRFCoordinatorV2PlusUpgradedVersionFilterer: VRFCoordinatorV2PlusUpgradedVersionFilterer{contract: contract}}, nil
}
type VRFCoordinatorV2PlusUpgradedVersion struct {
diff --git a/core/gethwrappers/generated/vrfv2_proxy_admin/vrfv2_proxy_admin.go b/core/gethwrappers/generated/vrfv2_proxy_admin/vrfv2_proxy_admin.go
index 2cb4edd208..d92679f4ad 100644
--- a/core/gethwrappers/generated/vrfv2_proxy_admin/vrfv2_proxy_admin.go
+++ b/core/gethwrappers/generated/vrfv2_proxy_admin/vrfv2_proxy_admin.go
@@ -52,7 +52,7 @@ func DeployVRFV2ProxyAdmin(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2ProxyAdmin{VRFV2ProxyAdminCaller: VRFV2ProxyAdminCaller{contract: contract}, VRFV2ProxyAdminTransactor: VRFV2ProxyAdminTransactor{contract: contract}, VRFV2ProxyAdminFilterer: VRFV2ProxyAdminFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2ProxyAdmin{address: address, abi: *parsed, VRFV2ProxyAdminCaller: VRFV2ProxyAdminCaller{contract: contract}, VRFV2ProxyAdminTransactor: VRFV2ProxyAdminTransactor{contract: contract}, VRFV2ProxyAdminFilterer: VRFV2ProxyAdminFilterer{contract: contract}}, nil
}
type VRFV2ProxyAdmin struct {
diff --git a/core/gethwrappers/generated/vrfv2_reverting_example/vrfv2_reverting_example.go b/core/gethwrappers/generated/vrfv2_reverting_example/vrfv2_reverting_example.go
index 9f8a4eb0fa..facfc931c9 100644
--- a/core/gethwrappers/generated/vrfv2_reverting_example/vrfv2_reverting_example.go
+++ b/core/gethwrappers/generated/vrfv2_reverting_example/vrfv2_reverting_example.go
@@ -50,7 +50,7 @@ func DeployVRFV2RevertingExample(auth *bind.TransactOpts, backend bind.ContractB
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2RevertingExample{VRFV2RevertingExampleCaller: VRFV2RevertingExampleCaller{contract: contract}, VRFV2RevertingExampleTransactor: VRFV2RevertingExampleTransactor{contract: contract}, VRFV2RevertingExampleFilterer: VRFV2RevertingExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2RevertingExample{address: address, abi: *parsed, VRFV2RevertingExampleCaller: VRFV2RevertingExampleCaller{contract: contract}, VRFV2RevertingExampleTransactor: VRFV2RevertingExampleTransactor{contract: contract}, VRFV2RevertingExampleFilterer: VRFV2RevertingExampleFilterer{contract: contract}}, nil
}
type VRFV2RevertingExample struct {
diff --git a/core/gethwrappers/generated/vrfv2_transparent_upgradeable_proxy/vrfv2_transparent_upgradeable_proxy.go b/core/gethwrappers/generated/vrfv2_transparent_upgradeable_proxy/vrfv2_transparent_upgradeable_proxy.go
index 657cc1894f..c808650a08 100644
--- a/core/gethwrappers/generated/vrfv2_transparent_upgradeable_proxy/vrfv2_transparent_upgradeable_proxy.go
+++ b/core/gethwrappers/generated/vrfv2_transparent_upgradeable_proxy/vrfv2_transparent_upgradeable_proxy.go
@@ -52,7 +52,7 @@ func DeployVRFV2TransparentUpgradeableProxy(auth *bind.TransactOpts, backend bin
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2TransparentUpgradeableProxy{VRFV2TransparentUpgradeableProxyCaller: VRFV2TransparentUpgradeableProxyCaller{contract: contract}, VRFV2TransparentUpgradeableProxyTransactor: VRFV2TransparentUpgradeableProxyTransactor{contract: contract}, VRFV2TransparentUpgradeableProxyFilterer: VRFV2TransparentUpgradeableProxyFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2TransparentUpgradeableProxy{address: address, abi: *parsed, VRFV2TransparentUpgradeableProxyCaller: VRFV2TransparentUpgradeableProxyCaller{contract: contract}, VRFV2TransparentUpgradeableProxyTransactor: VRFV2TransparentUpgradeableProxyTransactor{contract: contract}, VRFV2TransparentUpgradeableProxyFilterer: VRFV2TransparentUpgradeableProxyFilterer{contract: contract}}, nil
}
type VRFV2TransparentUpgradeableProxy struct {
diff --git a/core/gethwrappers/generated/vrfv2_wrapper/vrfv2_wrapper.go b/core/gethwrappers/generated/vrfv2_wrapper/vrfv2_wrapper.go
index 61cb52e117..9e7e25229e 100644
--- a/core/gethwrappers/generated/vrfv2_wrapper/vrfv2_wrapper.go
+++ b/core/gethwrappers/generated/vrfv2_wrapper/vrfv2_wrapper.go
@@ -52,7 +52,7 @@ func DeployVRFV2Wrapper(auth *bind.TransactOpts, backend bind.ContractBackend, _
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2Wrapper{VRFV2WrapperCaller: VRFV2WrapperCaller{contract: contract}, VRFV2WrapperTransactor: VRFV2WrapperTransactor{contract: contract}, VRFV2WrapperFilterer: VRFV2WrapperFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2Wrapper{address: address, abi: *parsed, VRFV2WrapperCaller: VRFV2WrapperCaller{contract: contract}, VRFV2WrapperTransactor: VRFV2WrapperTransactor{contract: contract}, VRFV2WrapperFilterer: VRFV2WrapperFilterer{contract: contract}}, nil
}
type VRFV2Wrapper struct {
diff --git a/core/gethwrappers/generated/vrfv2_wrapper_consumer_example/vrfv2_wrapper_consumer_example.go b/core/gethwrappers/generated/vrfv2_wrapper_consumer_example/vrfv2_wrapper_consumer_example.go
index ba38ddf436..dbf5d97f9c 100644
--- a/core/gethwrappers/generated/vrfv2_wrapper_consumer_example/vrfv2_wrapper_consumer_example.go
+++ b/core/gethwrappers/generated/vrfv2_wrapper_consumer_example/vrfv2_wrapper_consumer_example.go
@@ -52,7 +52,7 @@ func DeployVRFV2WrapperConsumerExample(auth *bind.TransactOpts, backend bind.Con
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2WrapperConsumerExample{VRFV2WrapperConsumerExampleCaller: VRFV2WrapperConsumerExampleCaller{contract: contract}, VRFV2WrapperConsumerExampleTransactor: VRFV2WrapperConsumerExampleTransactor{contract: contract}, VRFV2WrapperConsumerExampleFilterer: VRFV2WrapperConsumerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2WrapperConsumerExample{address: address, abi: *parsed, VRFV2WrapperConsumerExampleCaller: VRFV2WrapperConsumerExampleCaller{contract: contract}, VRFV2WrapperConsumerExampleTransactor: VRFV2WrapperConsumerExampleTransactor{contract: contract}, VRFV2WrapperConsumerExampleFilterer: VRFV2WrapperConsumerExampleFilterer{contract: contract}}, nil
}
type VRFV2WrapperConsumerExample struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_client/vrfv2plus_client.go b/core/gethwrappers/generated/vrfv2plus_client/vrfv2plus_client.go
index 91112ff856..f6a65a63f2 100644
--- a/core/gethwrappers/generated/vrfv2plus_client/vrfv2plus_client.go
+++ b/core/gethwrappers/generated/vrfv2plus_client/vrfv2plus_client.go
@@ -50,7 +50,7 @@ func DeployVRFV2PlusClient(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusClient{VRFV2PlusClientCaller: VRFV2PlusClientCaller{contract: contract}, VRFV2PlusClientTransactor: VRFV2PlusClientTransactor{contract: contract}, VRFV2PlusClientFilterer: VRFV2PlusClientFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusClient{address: address, abi: *parsed, VRFV2PlusClientCaller: VRFV2PlusClientCaller{contract: contract}, VRFV2PlusClientTransactor: VRFV2PlusClientTransactor{contract: contract}, VRFV2PlusClientFilterer: VRFV2PlusClientFilterer{contract: contract}}, nil
}
type VRFV2PlusClient struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_consumer_example/vrfv2plus_consumer_example.go b/core/gethwrappers/generated/vrfv2plus_consumer_example/vrfv2plus_consumer_example.go
index 2ad412a122..20f3d4422b 100644
--- a/core/gethwrappers/generated/vrfv2plus_consumer_example/vrfv2plus_consumer_example.go
+++ b/core/gethwrappers/generated/vrfv2plus_consumer_example/vrfv2plus_consumer_example.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusConsumerExample(auth *bind.TransactOpts, backend bind.Contra
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusConsumerExample{VRFV2PlusConsumerExampleCaller: VRFV2PlusConsumerExampleCaller{contract: contract}, VRFV2PlusConsumerExampleTransactor: VRFV2PlusConsumerExampleTransactor{contract: contract}, VRFV2PlusConsumerExampleFilterer: VRFV2PlusConsumerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusConsumerExample{address: address, abi: *parsed, VRFV2PlusConsumerExampleCaller: VRFV2PlusConsumerExampleCaller{contract: contract}, VRFV2PlusConsumerExampleTransactor: VRFV2PlusConsumerExampleTransactor{contract: contract}, VRFV2PlusConsumerExampleFilterer: VRFV2PlusConsumerExampleFilterer{contract: contract}}, nil
}
type VRFV2PlusConsumerExample struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_malicious_migrator/vrfv2plus_malicious_migrator.go b/core/gethwrappers/generated/vrfv2plus_malicious_migrator/vrfv2plus_malicious_migrator.go
index c0c19a1134..03c5ffd8cc 100644
--- a/core/gethwrappers/generated/vrfv2plus_malicious_migrator/vrfv2plus_malicious_migrator.go
+++ b/core/gethwrappers/generated/vrfv2plus_malicious_migrator/vrfv2plus_malicious_migrator.go
@@ -50,7 +50,7 @@ func DeployVRFV2PlusMaliciousMigrator(auth *bind.TransactOpts, backend bind.Cont
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusMaliciousMigrator{VRFV2PlusMaliciousMigratorCaller: VRFV2PlusMaliciousMigratorCaller{contract: contract}, VRFV2PlusMaliciousMigratorTransactor: VRFV2PlusMaliciousMigratorTransactor{contract: contract}, VRFV2PlusMaliciousMigratorFilterer: VRFV2PlusMaliciousMigratorFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusMaliciousMigrator{address: address, abi: *parsed, VRFV2PlusMaliciousMigratorCaller: VRFV2PlusMaliciousMigratorCaller{contract: contract}, VRFV2PlusMaliciousMigratorTransactor: VRFV2PlusMaliciousMigratorTransactor{contract: contract}, VRFV2PlusMaliciousMigratorFilterer: VRFV2PlusMaliciousMigratorFilterer{contract: contract}}, nil
}
type VRFV2PlusMaliciousMigrator struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_reverting_example/vrfv2plus_reverting_example.go b/core/gethwrappers/generated/vrfv2plus_reverting_example/vrfv2plus_reverting_example.go
index 7236470139..5e66eb2474 100644
--- a/core/gethwrappers/generated/vrfv2plus_reverting_example/vrfv2plus_reverting_example.go
+++ b/core/gethwrappers/generated/vrfv2plus_reverting_example/vrfv2plus_reverting_example.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusRevertingExample(auth *bind.TransactOpts, backend bind.Contr
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusRevertingExample{VRFV2PlusRevertingExampleCaller: VRFV2PlusRevertingExampleCaller{contract: contract}, VRFV2PlusRevertingExampleTransactor: VRFV2PlusRevertingExampleTransactor{contract: contract}, VRFV2PlusRevertingExampleFilterer: VRFV2PlusRevertingExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusRevertingExample{address: address, abi: *parsed, VRFV2PlusRevertingExampleCaller: VRFV2PlusRevertingExampleCaller{contract: contract}, VRFV2PlusRevertingExampleTransactor: VRFV2PlusRevertingExampleTransactor{contract: contract}, VRFV2PlusRevertingExampleFilterer: VRFV2PlusRevertingExampleFilterer{contract: contract}}, nil
}
type VRFV2PlusRevertingExample struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go b/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go
index d7894c576e..5a5ccb34f1 100644
--- a/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go
+++ b/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusWrapper(auth *bind.TransactOpts, backend bind.ContractBacken
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusWrapper{VRFV2PlusWrapperCaller: VRFV2PlusWrapperCaller{contract: contract}, VRFV2PlusWrapperTransactor: VRFV2PlusWrapperTransactor{contract: contract}, VRFV2PlusWrapperFilterer: VRFV2PlusWrapperFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusWrapper{address: address, abi: *parsed, VRFV2PlusWrapperCaller: VRFV2PlusWrapperCaller{contract: contract}, VRFV2PlusWrapperTransactor: VRFV2PlusWrapperTransactor{contract: contract}, VRFV2PlusWrapperFilterer: VRFV2PlusWrapperFilterer{contract: contract}}, nil
}
type VRFV2PlusWrapper struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_wrapper_consumer_example/vrfv2plus_wrapper_consumer_example.go b/core/gethwrappers/generated/vrfv2plus_wrapper_consumer_example/vrfv2plus_wrapper_consumer_example.go
index 9cbd5ef964..ee2f1e360b 100644
--- a/core/gethwrappers/generated/vrfv2plus_wrapper_consumer_example/vrfv2plus_wrapper_consumer_example.go
+++ b/core/gethwrappers/generated/vrfv2plus_wrapper_consumer_example/vrfv2plus_wrapper_consumer_example.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusWrapperConsumerExample(auth *bind.TransactOpts, backend bind
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusWrapperConsumerExample{VRFV2PlusWrapperConsumerExampleCaller: VRFV2PlusWrapperConsumerExampleCaller{contract: contract}, VRFV2PlusWrapperConsumerExampleTransactor: VRFV2PlusWrapperConsumerExampleTransactor{contract: contract}, VRFV2PlusWrapperConsumerExampleFilterer: VRFV2PlusWrapperConsumerExampleFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusWrapperConsumerExample{address: address, abi: *parsed, VRFV2PlusWrapperConsumerExampleCaller: VRFV2PlusWrapperConsumerExampleCaller{contract: contract}, VRFV2PlusWrapperConsumerExampleTransactor: VRFV2PlusWrapperConsumerExampleTransactor{contract: contract}, VRFV2PlusWrapperConsumerExampleFilterer: VRFV2PlusWrapperConsumerExampleFilterer{contract: contract}}, nil
}
type VRFV2PlusWrapperConsumerExample struct {
diff --git a/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer/vrfv2plus_wrapper_load_test_consumer.go b/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer/vrfv2plus_wrapper_load_test_consumer.go
index 231945c9b7..8da1419620 100644
--- a/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer/vrfv2plus_wrapper_load_test_consumer.go
+++ b/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer/vrfv2plus_wrapper_load_test_consumer.go
@@ -52,7 +52,7 @@ func DeployVRFV2PlusWrapperLoadTestConsumer(auth *bind.TransactOpts, backend bin
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VRFV2PlusWrapperLoadTestConsumer{VRFV2PlusWrapperLoadTestConsumerCaller: VRFV2PlusWrapperLoadTestConsumerCaller{contract: contract}, VRFV2PlusWrapperLoadTestConsumerTransactor: VRFV2PlusWrapperLoadTestConsumerTransactor{contract: contract}, VRFV2PlusWrapperLoadTestConsumerFilterer: VRFV2PlusWrapperLoadTestConsumerFilterer{contract: contract}}, nil
+ return address, tx, &VRFV2PlusWrapperLoadTestConsumer{address: address, abi: *parsed, VRFV2PlusWrapperLoadTestConsumerCaller: VRFV2PlusWrapperLoadTestConsumerCaller{contract: contract}, VRFV2PlusWrapperLoadTestConsumerTransactor: VRFV2PlusWrapperLoadTestConsumerTransactor{contract: contract}, VRFV2PlusWrapperLoadTestConsumerFilterer: VRFV2PlusWrapperLoadTestConsumerFilterer{contract: contract}}, nil
}
type VRFV2PlusWrapperLoadTestConsumer struct {
diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go
index ce553dc818..67090d16c6 100644
--- a/core/gethwrappers/go_generate.go
+++ b/core/gethwrappers/go_generate.go
@@ -2,7 +2,7 @@
// golang packages, using abigen.
package gethwrappers
-// Make sure solidity compiler artifacts are up to date. Only output stdout on failure.
+// Make sure solidity compiler artifacts are up-to-date. Only output stdout on failure.
//go:generate ./generation/compile_contracts.sh
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator.bin FluxAggregator flux_aggregator_wrapper
diff --git a/core/gethwrappers/llo-feeds/generated/errored_verifier/errored_verifier.go b/core/gethwrappers/llo-feeds/generated/errored_verifier/errored_verifier.go
index 846ebb197b..ad0ff29478 100644
--- a/core/gethwrappers/llo-feeds/generated/errored_verifier/errored_verifier.go
+++ b/core/gethwrappers/llo-feeds/generated/errored_verifier/errored_verifier.go
@@ -55,7 +55,7 @@ func DeployErroredVerifier(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &ErroredVerifier{ErroredVerifierCaller: ErroredVerifierCaller{contract: contract}, ErroredVerifierTransactor: ErroredVerifierTransactor{contract: contract}, ErroredVerifierFilterer: ErroredVerifierFilterer{contract: contract}}, nil
+ return address, tx, &ErroredVerifier{address: address, abi: *parsed, ErroredVerifierCaller: ErroredVerifierCaller{contract: contract}, ErroredVerifierTransactor: ErroredVerifierTransactor{contract: contract}, ErroredVerifierFilterer: ErroredVerifierFilterer{contract: contract}}, nil
}
type ErroredVerifier struct {
diff --git a/core/gethwrappers/llo-feeds/generated/exposed_verifier/exposed_verifier.go b/core/gethwrappers/llo-feeds/generated/exposed_verifier/exposed_verifier.go
index 2ca74b7cf3..e27cb58d15 100644
--- a/core/gethwrappers/llo-feeds/generated/exposed_verifier/exposed_verifier.go
+++ b/core/gethwrappers/llo-feeds/generated/exposed_verifier/exposed_verifier.go
@@ -50,7 +50,7 @@ func DeployExposedVerifier(auth *bind.TransactOpts, backend bind.ContractBackend
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &ExposedVerifier{ExposedVerifierCaller: ExposedVerifierCaller{contract: contract}, ExposedVerifierTransactor: ExposedVerifierTransactor{contract: contract}, ExposedVerifierFilterer: ExposedVerifierFilterer{contract: contract}}, nil
+ return address, tx, &ExposedVerifier{address: address, abi: *parsed, ExposedVerifierCaller: ExposedVerifierCaller{contract: contract}, ExposedVerifierTransactor: ExposedVerifierTransactor{contract: contract}, ExposedVerifierFilterer: ExposedVerifierFilterer{contract: contract}}, nil
}
type ExposedVerifier struct {
diff --git a/core/gethwrappers/llo-feeds/generated/fee_manager/fee_manager.go b/core/gethwrappers/llo-feeds/generated/fee_manager/fee_manager.go
index 666edd3385..742ec91bf9 100644
--- a/core/gethwrappers/llo-feeds/generated/fee_manager/fee_manager.go
+++ b/core/gethwrappers/llo-feeds/generated/fee_manager/fee_manager.go
@@ -67,7 +67,7 @@ func DeployFeeManager(auth *bind.TransactOpts, backend bind.ContractBackend, _li
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &FeeManager{FeeManagerCaller: FeeManagerCaller{contract: contract}, FeeManagerTransactor: FeeManagerTransactor{contract: contract}, FeeManagerFilterer: FeeManagerFilterer{contract: contract}}, nil
+ return address, tx, &FeeManager{address: address, abi: *parsed, FeeManagerCaller: FeeManagerCaller{contract: contract}, FeeManagerTransactor: FeeManagerTransactor{contract: contract}, FeeManagerFilterer: FeeManagerFilterer{contract: contract}}, nil
}
type FeeManager struct {
diff --git a/core/gethwrappers/llo-feeds/generated/reward_manager/reward_manager.go b/core/gethwrappers/llo-feeds/generated/reward_manager/reward_manager.go
index 224fb37ef6..c870a40301 100644
--- a/core/gethwrappers/llo-feeds/generated/reward_manager/reward_manager.go
+++ b/core/gethwrappers/llo-feeds/generated/reward_manager/reward_manager.go
@@ -62,7 +62,7 @@ func DeployRewardManager(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &RewardManager{RewardManagerCaller: RewardManagerCaller{contract: contract}, RewardManagerTransactor: RewardManagerTransactor{contract: contract}, RewardManagerFilterer: RewardManagerFilterer{contract: contract}}, nil
+ return address, tx, &RewardManager{address: address, abi: *parsed, RewardManagerCaller: RewardManagerCaller{contract: contract}, RewardManagerTransactor: RewardManagerTransactor{contract: contract}, RewardManagerFilterer: RewardManagerFilterer{contract: contract}}, nil
}
type RewardManager struct {
diff --git a/core/gethwrappers/llo-feeds/generated/verifier/verifier.go b/core/gethwrappers/llo-feeds/generated/verifier/verifier.go
index 993de18eb5..09bf78b23b 100644
--- a/core/gethwrappers/llo-feeds/generated/verifier/verifier.go
+++ b/core/gethwrappers/llo-feeds/generated/verifier/verifier.go
@@ -57,7 +57,7 @@ func DeployVerifier(auth *bind.TransactOpts, backend bind.ContractBackend, verif
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Verifier{VerifierCaller: VerifierCaller{contract: contract}, VerifierTransactor: VerifierTransactor{contract: contract}, VerifierFilterer: VerifierFilterer{contract: contract}}, nil
+ return address, tx, &Verifier{address: address, abi: *parsed, VerifierCaller: VerifierCaller{contract: contract}, VerifierTransactor: VerifierTransactor{contract: contract}, VerifierFilterer: VerifierFilterer{contract: contract}}, nil
}
type Verifier struct {
diff --git a/core/gethwrappers/llo-feeds/generated/verifier_proxy/verifier_proxy.go b/core/gethwrappers/llo-feeds/generated/verifier_proxy/verifier_proxy.go
index 5ed70fef20..fc7f10b641 100644
--- a/core/gethwrappers/llo-feeds/generated/verifier_proxy/verifier_proxy.go
+++ b/core/gethwrappers/llo-feeds/generated/verifier_proxy/verifier_proxy.go
@@ -57,7 +57,7 @@ func DeployVerifierProxy(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &VerifierProxy{VerifierProxyCaller: VerifierProxyCaller{contract: contract}, VerifierProxyTransactor: VerifierProxyTransactor{contract: contract}, VerifierProxyFilterer: VerifierProxyFilterer{contract: contract}}, nil
+ return address, tx, &VerifierProxy{address: address, abi: *parsed, VerifierProxyCaller: VerifierProxyCaller{contract: contract}, VerifierProxyTransactor: VerifierProxyTransactor{contract: contract}, VerifierProxyFilterer: VerifierProxyFilterer{contract: contract}}, nil
}
type VerifierProxy struct {
diff --git a/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go b/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go
index f138b3b1f0..1d5b1c4ab1 100644
--- a/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go
+++ b/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go
@@ -52,7 +52,7 @@ func DeployBurnMintERC677(auth *bind.TransactOpts, backend bind.ContractBackend,
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &BurnMintERC677{BurnMintERC677Caller: BurnMintERC677Caller{contract: contract}, BurnMintERC677Transactor: BurnMintERC677Transactor{contract: contract}, BurnMintERC677Filterer: BurnMintERC677Filterer{contract: contract}}, nil
+ return address, tx, &BurnMintERC677{address: address, abi: *parsed, BurnMintERC677Caller: BurnMintERC677Caller{contract: contract}, BurnMintERC677Transactor: BurnMintERC677Transactor{contract: contract}, BurnMintERC677Filterer: BurnMintERC677Filterer{contract: contract}}, nil
}
type BurnMintERC677 struct {
diff --git a/core/gethwrappers/shared/generated/erc20/erc20.go b/core/gethwrappers/shared/generated/erc20/erc20.go
index f5b1d9b7bf..9fd43134b6 100644
--- a/core/gethwrappers/shared/generated/erc20/erc20.go
+++ b/core/gethwrappers/shared/generated/erc20/erc20.go
@@ -52,7 +52,7 @@ func DeployERC20(auth *bind.TransactOpts, backend bind.ContractBackend, name_ st
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &ERC20{ERC20Caller: ERC20Caller{contract: contract}, ERC20Transactor: ERC20Transactor{contract: contract}, ERC20Filterer: ERC20Filterer{contract: contract}}, nil
+ return address, tx, &ERC20{address: address, abi: *parsed, ERC20Caller: ERC20Caller{contract: contract}, ERC20Transactor: ERC20Transactor{contract: contract}, ERC20Filterer: ERC20Filterer{contract: contract}}, nil
}
type ERC20 struct {
diff --git a/core/gethwrappers/shared/generated/link_token/link_token.go b/core/gethwrappers/shared/generated/link_token/link_token.go
index 98de7de66a..1467680626 100644
--- a/core/gethwrappers/shared/generated/link_token/link_token.go
+++ b/core/gethwrappers/shared/generated/link_token/link_token.go
@@ -52,7 +52,7 @@ func DeployLinkToken(auth *bind.TransactOpts, backend bind.ContractBackend) (com
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &LinkToken{LinkTokenCaller: LinkTokenCaller{contract: contract}, LinkTokenTransactor: LinkTokenTransactor{contract: contract}, LinkTokenFilterer: LinkTokenFilterer{contract: contract}}, nil
+ return address, tx, &LinkToken{address: address, abi: *parsed, LinkTokenCaller: LinkTokenCaller{contract: contract}, LinkTokenTransactor: LinkTokenTransactor{contract: contract}, LinkTokenFilterer: LinkTokenFilterer{contract: contract}}, nil
}
type LinkToken struct {
diff --git a/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go b/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go
index 3d8660c701..c8ff372275 100644
--- a/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go
+++ b/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go
@@ -52,7 +52,7 @@ func DeployWERC20Mock(auth *bind.TransactOpts, backend bind.ContractBackend) (co
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &WERC20Mock{WERC20MockCaller: WERC20MockCaller{contract: contract}, WERC20MockTransactor: WERC20MockTransactor{contract: contract}, WERC20MockFilterer: WERC20MockFilterer{contract: contract}}, nil
+ return address, tx, &WERC20Mock{address: address, abi: *parsed, WERC20MockCaller: WERC20MockCaller{contract: contract}, WERC20MockTransactor: WERC20MockTransactor{contract: contract}, WERC20MockFilterer: WERC20MockFilterer{contract: contract}}, nil
}
type WERC20Mock struct {
diff --git a/core/gethwrappers/transmission/generated/entry_point/entry_point.go b/core/gethwrappers/transmission/generated/entry_point/entry_point.go
index 9177186f4d..09a3a94a7f 100644
--- a/core/gethwrappers/transmission/generated/entry_point/entry_point.go
+++ b/core/gethwrappers/transmission/generated/entry_point/entry_point.go
@@ -99,7 +99,7 @@ func DeployEntryPoint(auth *bind.TransactOpts, backend bind.ContractBackend) (co
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &EntryPoint{EntryPointCaller: EntryPointCaller{contract: contract}, EntryPointTransactor: EntryPointTransactor{contract: contract}, EntryPointFilterer: EntryPointFilterer{contract: contract}}, nil
+ return address, tx, &EntryPoint{address: address, abi: *parsed, EntryPointCaller: EntryPointCaller{contract: contract}, EntryPointTransactor: EntryPointTransactor{contract: contract}, EntryPointFilterer: EntryPointFilterer{contract: contract}}, nil
}
type EntryPoint struct {
diff --git a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go
index 857472422f..9814c6a12c 100644
--- a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go
+++ b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go
@@ -50,7 +50,7 @@ func DeployGreeter(auth *bind.TransactOpts, backend bind.ContractBackend) (commo
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Greeter{GreeterCaller: GreeterCaller{contract: contract}, GreeterTransactor: GreeterTransactor{contract: contract}, GreeterFilterer: GreeterFilterer{contract: contract}}, nil
+ return address, tx, &Greeter{address: address, abi: *parsed, GreeterCaller: GreeterCaller{contract: contract}, GreeterTransactor: GreeterTransactor{contract: contract}, GreeterFilterer: GreeterFilterer{contract: contract}}, nil
}
type Greeter struct {
diff --git a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go
index 84283b28bb..4910d2b4bb 100644
--- a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go
+++ b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go
@@ -66,7 +66,7 @@ func DeployPaymaster(auth *bind.TransactOpts, backend bind.ContractBackend, link
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Paymaster{PaymasterCaller: PaymasterCaller{contract: contract}, PaymasterTransactor: PaymasterTransactor{contract: contract}, PaymasterFilterer: PaymasterFilterer{contract: contract}}, nil
+ return address, tx, &Paymaster{address: address, abi: *parsed, PaymasterCaller: PaymasterCaller{contract: contract}, PaymasterTransactor: PaymasterTransactor{contract: contract}, PaymasterFilterer: PaymasterFilterer{contract: contract}}, nil
}
type Paymaster struct {
diff --git a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go
index 36838fc1b0..55a3107710 100644
--- a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go
+++ b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go
@@ -64,7 +64,7 @@ func DeploySCA(auth *bind.TransactOpts, backend bind.ContractBackend, owner comm
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &SCA{SCACaller: SCACaller{contract: contract}, SCATransactor: SCATransactor{contract: contract}, SCAFilterer: SCAFilterer{contract: contract}}, nil
+ return address, tx, &SCA{address: address, abi: *parsed, SCACaller: SCACaller{contract: contract}, SCATransactor: SCATransactor{contract: contract}, SCAFilterer: SCAFilterer{contract: contract}}, nil
}
type SCA struct {
diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go
index 1e7761bffe..0b4daf3fa8 100644
--- a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go
+++ b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go
@@ -52,7 +52,7 @@ func DeploySmartContractAccountFactory(auth *bind.TransactOpts, backend bind.Con
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &SmartContractAccountFactory{SmartContractAccountFactoryCaller: SmartContractAccountFactoryCaller{contract: contract}, SmartContractAccountFactoryTransactor: SmartContractAccountFactoryTransactor{contract: contract}, SmartContractAccountFactoryFilterer: SmartContractAccountFactoryFilterer{contract: contract}}, nil
+ return address, tx, &SmartContractAccountFactory{address: address, abi: *parsed, SmartContractAccountFactoryCaller: SmartContractAccountFactoryCaller{contract: contract}, SmartContractAccountFactoryTransactor: SmartContractAccountFactoryTransactor{contract: contract}, SmartContractAccountFactoryFilterer: SmartContractAccountFactoryFilterer{contract: contract}}, nil
}
type SmartContractAccountFactory struct {
diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go
index add1d2ce51..d951227c3a 100644
--- a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go
+++ b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go
@@ -50,7 +50,7 @@ func DeploySmartContractAccountHelper(auth *bind.TransactOpts, backend bind.Cont
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &SmartContractAccountHelper{SmartContractAccountHelperCaller: SmartContractAccountHelperCaller{contract: contract}, SmartContractAccountHelperTransactor: SmartContractAccountHelperTransactor{contract: contract}, SmartContractAccountHelperFilterer: SmartContractAccountHelperFilterer{contract: contract}}, nil
+ return address, tx, &SmartContractAccountHelper{address: address, abi: *parsed, SmartContractAccountHelperCaller: SmartContractAccountHelperCaller{contract: contract}, SmartContractAccountHelperTransactor: SmartContractAccountHelperTransactor{contract: contract}, SmartContractAccountHelperFilterer: SmartContractAccountHelperFilterer{contract: contract}}, nil
}
type SmartContractAccountHelper struct {
From 78c658e04539db27c0c6322fa1e80744f1f7cfb0 Mon Sep 17 00:00:00 2001
From: Kashif
Date: Thu, 26 Oct 2023 23:21:53 +0900
Subject: [PATCH 015/327] [FTM] Enable suggested gas fee on Fantom (#10963)
* Enable suggested gas fee on Fantom
* update docs
* Add contract deployer
* Add config change reasoning
---------
Co-authored-by: davidcauchi
---
.github/workflows/on-demand-ocr-soak-test.yml | 2 ++
core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml | 5 +++--
core/chains/evm/config/toml/defaults/Fantom_Testnet.toml | 3 +--
docs/CONFIG.md | 8 ++++----
integration-tests/contracts/contract_deployer.go | 6 ++++++
5 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index 7dc144264d..15f259e7e8 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -24,6 +24,8 @@ on:
- "POLYGON_MAINNET"
- "LINEA_GOERLI"
- "LINEA_MAINNET"
+ - "FANTOM_TESTNET"
+ - "FANTOM_MAINNET"
fundingPrivateKey:
description: Private funding key (Skip for Simulated)
required: false
diff --git a/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml b/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml
index f7678c37eb..7046642bb9 100644
--- a/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml
+++ b/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml
@@ -9,8 +9,9 @@ RPCBlockQueryDelay = 2
Enabled = true
[GasEstimator]
-PriceDefault = '15 gwei'
-PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+# Fantom network has been slow to include txs at times when using the BlockHistory estimator, and the recommendation is to use L2Suggested mode.
+# There is work under way to improve L2Suggested mode's name so that its use on non-L2 chains will be less confusing in the future.
+Mode = 'L2Suggested'
[OCR2.Automation]
GasLimit = 3800000
\ No newline at end of file
diff --git a/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml b/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml
index c7a6f72f9a..0292ed5b74 100644
--- a/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml
+++ b/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml
@@ -7,8 +7,7 @@ NoNewHeadsThreshold = '0'
RPCBlockQueryDelay = 2
[GasEstimator]
-PriceDefault = '15 gwei'
-PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+Mode = 'L2Suggested'
[OCR2.Automation]
GasLimit = 3800000
\ No newline at end of file
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 9582a940c3..1fc7d9b632 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -2724,8 +2724,8 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'BlockHistory'
-PriceDefault = '15 gwei'
+Mode = 'L2Suggested'
+PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
LimitDefault = 500000
@@ -3197,8 +3197,8 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'BlockHistory'
-PriceDefault = '15 gwei'
+Mode = 'L2Suggested'
+PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
LimitDefault = 500000
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index bdf63d1919..710422891c 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -169,6 +169,8 @@ func NewContractDeployer(bcClient blockchain.EVMClient, logger zerolog.Logger) (
return &PolygonZkEvmContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
case *blockchain.LineaClient:
return &LineaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
+ case *blockchain.FantomClient:
+ return &FantomContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
}
return nil, errors.New("unknown blockchain client implementation for contract deployer, register blockchain client in NewContractDeployer")
}
@@ -232,6 +234,10 @@ type LineaContractDeployer struct {
*EthereumContractDeployer
}
+type FantomContractDeployer struct {
+ *EthereumContractDeployer
+}
+
// NewEthereumContractDeployer returns an instantiated instance of the ETH contract deployer
func NewEthereumContractDeployer(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractDeployer {
return &EthereumContractDeployer{
From 7fef66dc1fb82a865120601f38a1bd8f3c507b01 Mon Sep 17 00:00:00 2001
From: Lei
Date: Thu, 26 Oct 2023 13:27:35 -0700
Subject: [PATCH 016/327] tune debugging script (#11070)
---
core/scripts/chaincli/handler/debug.go | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go
index bdbce79926..7cf801d332 100644
--- a/core/scripts/chaincli/handler/debug.go
+++ b/core/scripts/chaincli/handler/debug.go
@@ -70,7 +70,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
// verify contract is correct
typeAndVersion, err := keeperRegistry21.TypeAndVersion(latestCallOpts)
if err != nil {
- failCheckConfig("failed to get typeAndVersion: are you sure you have the correct contract address?", err)
+ failCheckConfig("failed to get typeAndVersion: make sure your registry contract address and archive node are valid", err)
}
if typeAndVersion != expectedTypeAndVersion {
failCheckConfig(fmt.Sprintf("invalid registry contract: this command can only debug %s, got: %s", expectedTypeAndVersion, typeAndVersion), nil)
@@ -148,10 +148,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
if err != nil {
failCheckArgs("unable to parse log index", err)
}
- // find transaciton receipt
+ // find transaction receipt
_, isPending, err := k.client.TransactionByHash(ctx, txHash)
if err != nil {
- log.Fatal("failed to fetch tx receipt", err)
+ log.Fatal("failed to get tx by hash", err)
}
if isPending {
resolveIneligible(fmt.Sprintf("tx %s is still pending confirmation", txHash))
@@ -256,6 +256,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
message("using mercury lookup v0.3")
}
streamsLookup := &StreamsLookup{streamsLookupErr.FeedParamKey, streamsLookupErr.Feeds, streamsLookupErr.TimeParamKey, streamsLookupErr.Time, streamsLookupErr.ExtraData, upkeepID, blockNum}
+
+ if k.cfg.MercuryLegacyURL == "" || k.cfg.MercuryURL == "" || k.cfg.MercuryID == "" || k.cfg.MercuryKey == "" {
+ failCheckConfig("Mercury configs not set properly, check your MERCURY_LEGACY_URL, MERCURY_URL, MERCURY_ID and MERCURY_KEY", nil)
+ }
handler := NewMercuryLookupHandler(&MercuryCredentials{k.cfg.MercuryLegacyURL, k.cfg.MercuryURL, k.cfg.MercuryID, k.cfg.MercuryKey}, k.rpcClient)
state, failureReason, values, _, err := handler.doMercuryRequest(ctx, streamsLookup)
if failureReason == UpkeepFailureReasonInvalidRevertDataInput {
From e062e38b82aa1b3f150d463b96aedd44bab9f74c Mon Sep 17 00:00:00 2001
From: Tate
Date: Thu, 26 Oct 2023 15:29:38 -0600
Subject: [PATCH 017/327] [TT-647] Bump Metrics For More Go Package + Test Name
Preprocessing (#11095)
---
.github/actions/golangci-lint/action.yml | 2 +-
.../workflows/automation-benchmark-tests.yml | 2 +-
.../workflows/automation-ondemand-tests.yml | 6 ++---
.github/workflows/build-publish-develop.yml | 2 +-
.github/workflows/build-publish.yml | 2 +-
.github/workflows/build.yml | 2 +-
.github/workflows/changelog.yml | 2 +-
.github/workflows/ci-core.yml | 6 ++---
.github/workflows/codeql-analysis.yml | 2 +-
.github/workflows/delete-deployments.yml | 2 +-
.github/workflows/dependency-check.yml | 2 +-
.../goreleaser-build-publish-develop.yml | 2 +-
.github/workflows/integration-chaos-tests.yml | 6 ++---
.../workflows/integration-tests-publish.yml | 2 +-
.github/workflows/integration-tests.yml | 26 +++++++++----------
.github/workflows/lint-gh-workflows.yml | 2 +-
.github/workflows/on-demand-ocr-soak-test.yml | 2 +-
.../on-demand-vrfv2plus-performance-test.yml | 2 +-
.github/workflows/operator-ui-cd.yml | 2 +-
.github/workflows/performance-tests.yml | 4 +--
.github/workflows/readme.yml | 2 +-
.github/workflows/sigscanner.yml | 2 +-
.github/workflows/solidity-foundry.yml | 2 +-
.github/workflows/solidity-hardhat.yml | 8 +++---
.github/workflows/solidity.yml | 8 +++---
...evelop-from-smartcontractkit-chainlink.yml | 2 +-
26 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml
index c0aeb529c1..c9ea735d1f 100644
--- a/.github/actions/golangci-lint/action.yml
+++ b/.github/actions/golangci-lint/action.yml
@@ -69,7 +69,7 @@ runs:
path: ${{ inputs.go-directory }}/golangci-lint-report.xml
- name: Collect Metrics
if: always()
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ inputs.gc-basic-auth }}
hostname: ${{ inputs.gc-host }}
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index 45491af026..f23102f1ee 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -128,7 +128,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml
index 20415b599e..ac0e34e083 100644
--- a/.github/workflows/automation-ondemand-tests.yml
+++ b/.github/workflows/automation-ondemand-tests.yml
@@ -46,7 +46,7 @@ jobs:
- name: Collect Metrics
if: inputs.chainlinkImage == ''
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -91,7 +91,7 @@ jobs:
steps:
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -205,7 +205,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/build-publish-develop.yml b/.github/workflows/build-publish-develop.yml
index 54ccaad581..076fdf817d 100644
--- a/.github/workflows/build-publish-develop.yml
+++ b/.github/workflows/build-publish-develop.yml
@@ -56,7 +56,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml
index 5db70576b3..4d5a42a369 100644
--- a/.github/workflows/build-publish.yml
+++ b/.github/workflows/build-publish.yml
@@ -50,7 +50,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7cdf5e46b9..0f9a8ea8b3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -22,7 +22,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index a8e6e266a9..c7ca0b880c 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -31,7 +31,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml
index 4037dc0cd9..4053585590 100644
--- a/.github/workflows/ci-core.yml
+++ b/.github/workflows/ci-core.yml
@@ -117,7 +117,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -215,7 +215,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -253,7 +253,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 822bf259f9..8bc066f408 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -45,7 +45,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/delete-deployments.yml b/.github/workflows/delete-deployments.yml
index 3ec5fb35c9..dc3c17852b 100644
--- a/.github/workflows/delete-deployments.yml
+++ b/.github/workflows/delete-deployments.yml
@@ -24,7 +24,7 @@ jobs:
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml
index 42729a8cf1..dbf0889575 100644
--- a/.github/workflows/dependency-check.yml
+++ b/.github/workflows/dependency-check.yml
@@ -47,7 +47,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/goreleaser-build-publish-develop.yml b/.github/workflows/goreleaser-build-publish-develop.yml
index 1edfdedd70..514067fd85 100644
--- a/.github/workflows/goreleaser-build-publish-develop.yml
+++ b/.github/workflows/goreleaser-build-publish-develop.yml
@@ -39,7 +39,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml
index 503e5ec58a..648d5f9daa 100644
--- a/.github/workflows/integration-chaos-tests.yml
+++ b/.github/workflows/integration-chaos-tests.yml
@@ -53,7 +53,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -79,7 +79,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -99,7 +99,7 @@ jobs:
steps:
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml
index 06f7bb1b81..60f67f0357 100644
--- a/.github/workflows/integration-tests-publish.yml
+++ b/.github/workflows/integration-tests-publish.yml
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index edd7755e8b..98e59ce8d4 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -45,7 +45,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -74,7 +74,7 @@ jobs:
- name: Collect Metrics
if: needs.changes.outputs.src == 'true'
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -122,7 +122,7 @@ jobs:
- name: Collect Metrics
if: needs.changes.outputs.src == 'true'
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -228,7 +228,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -440,7 +440,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -468,7 +468,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -496,7 +496,7 @@ jobs:
- name: Collect Metrics
if: ${{ github.event_name == 'pull_request' }}
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -591,7 +591,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -697,7 +697,7 @@ jobs:
- name: Collect Metrics
if: needs.changes.outputs.src == 'true'
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -738,7 +738,7 @@ jobs:
- name: Collect Metrics
if: needs.changes.outputs.src == 'true' && needs.solana-test-image-exists.outputs.exists == 'false'
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -796,7 +796,7 @@ jobs:
- name: Collect Metrics
if: needs.changes.outputs.src == 'true'
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -874,7 +874,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -946,7 +946,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/lint-gh-workflows.yml b/.github/workflows/lint-gh-workflows.yml
index 8facdc038c..f1a3cc2080 100644
--- a/.github/workflows/lint-gh-workflows.yml
+++ b/.github/workflows/lint-gh-workflows.yml
@@ -13,7 +13,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index 15f259e7e8..1fb79d8ccd 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -89,7 +89,7 @@ jobs:
steps:
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
index 41b6618ba6..deb977e43f 100644
--- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml
+++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
@@ -86,7 +86,7 @@ jobs:
steps:
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/operator-ui-cd.yml b/.github/workflows/operator-ui-cd.yml
index 36a9d8b715..54f423e6dc 100644
--- a/.github/workflows/operator-ui-cd.yml
+++ b/.github/workflows/operator-ui-cd.yml
@@ -50,7 +50,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml
index 43ed80cb3f..277940dc2d 100644
--- a/.github/workflows/performance-tests.yml
+++ b/.github/workflows/performance-tests.yml
@@ -42,7 +42,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -79,7 +79,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml
index e847216eb0..585bed41c6 100644
--- a/.github/workflows/readme.yml
+++ b/.github/workflows/readme.yml
@@ -31,7 +31,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/sigscanner.yml b/.github/workflows/sigscanner.yml
index 285a63cacb..de34766d2c 100644
--- a/.github/workflows/sigscanner.yml
+++ b/.github/workflows/sigscanner.yml
@@ -26,7 +26,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml
index f6c515b5b8..19c879b09e 100644
--- a/.github/workflows/solidity-foundry.yml
+++ b/.github/workflows/solidity-foundry.yml
@@ -86,7 +86,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml
index 6e7de2eba1..129f37c0de 100644
--- a/.github/workflows/solidity-hardhat.yml
+++ b/.github/workflows/solidity-hardhat.yml
@@ -48,7 +48,7 @@ jobs:
config: ./contracts/ci.json
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -90,7 +90,7 @@ jobs:
path: ./contracts/coverage-${{ matrix.split.idx }}.json
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -145,7 +145,7 @@ jobs:
run: pnpm test -- $SPLIT
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -170,7 +170,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml
index f46b13191d..782dc93a0f 100644
--- a/.github/workflows/solidity.yml
+++ b/.github/workflows/solidity.yml
@@ -40,7 +40,7 @@ jobs:
run: pnpm prepublishOnly
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -84,7 +84,7 @@ jobs:
run: gh pr comment -b 'Go solidity wrappers are out-of-date, regenerate them via the `make wrappers-all` command'
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -110,7 +110,7 @@ jobs:
run: pnpm solhint
- name: Collect Metrics
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
@@ -136,7 +136,7 @@ jobs:
- name: Collect Metrics
if: needs.changes.outputs.changes == 'true'
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
diff --git a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml
index 7fe9ffd526..d27acceca6 100644
--- a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml
+++ b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml
@@ -30,7 +30,7 @@ jobs:
- name: Collect Metrics
if: always()
id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@f4d2fcbe12e9e44921e0171d24085ab7d2a30bc9 # v2.0.1
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
From eabdba0c76de266554cc33db3cbdb2e123afac4b Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Thu, 26 Oct 2023 16:56:02 -0500
Subject: [PATCH 018/327] core/chains/cosmos/types: rm unused (#11099)
---
core/chains/cosmos/types/types.go | 8 --------
1 file changed, 8 deletions(-)
delete mode 100644 core/chains/cosmos/types/types.go
diff --git a/core/chains/cosmos/types/types.go b/core/chains/cosmos/types/types.go
deleted file mode 100644
index 69b086a970..0000000000
--- a/core/chains/cosmos/types/types.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package types
-
-// NewNode defines a new node to create.
-type NewNode struct {
- Name string `json:"name"`
- CosmosChainID string `json:"cosmosChainId"`
- TendermintURL string `json:"tendermintURL" db:"tendermint_url"`
-}
From 01200f8ef8d3fab71d130dd8cd80855bf27bc5bb Mon Sep 17 00:00:00 2001
From: Ilja Pavlovs
Date: Fri, 27 Oct 2023 13:01:05 +0300
Subject: [PATCH 019/327] =?UTF-8?q?VRF-678:create=20sub,=20fund=20it,=20de?=
=?UTF-8?q?ploy=20consumer=20and=20add=20to=20sub=20when=20usin=E2=80=A6?=
=?UTF-8?q?=20(#11086)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* VRF-678:create sub, fund it, deploy consumer and add to sub when using VRFV2 Plus WASP load test with existing env
* VRF-678: cleanup
* VRF-678: fixing smoke test; adding additional logging
---
.../vrfv2plus/vrfv2plus_config/config.go | 1 +
.../actions/vrfv2plus/vrfv2plus_steps.go | 96 ++++++++++++-------
.../contracts/contract_vrf_models.go | 4 +-
.../contracts/ethereum_vrfv2plus_contracts.go | 12 +--
integration-tests/load/vrfv2plus/config.go | 13 ++-
integration-tests/load/vrfv2plus/config.toml | 18 ++--
.../load/vrfv2plus/vrfv2plus_test.go | 35 +++++--
integration-tests/smoke/vrfv2plus_test.go | 4 +-
8 files changed, 119 insertions(+), 64 deletions(-)
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
index caee353294..10d4f19c24 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
@@ -39,6 +39,7 @@ type VRFV2PlusConfig struct {
UseExistingEnv bool `envconfig:"USE_EXISTING_ENV" default:"false"` // Whether to use an existing environment or create a new one
CoordinatorAddress string `envconfig:"COORDINATOR_ADDRESS" default:""` // Coordinator address
ConsumerAddress string `envconfig:"CONSUMER_ADDRESS" default:""` // Consumer address
+ LinkAddress string `envconfig:"LINK_ADDRESS" default:""` // Link address
SubID string `envconfig:"SUB_ID" default:""` // Subscription ID
KeyHash string `envconfig:"KEY_HASH" default:""`
}
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index 3bfa5d4f41..46f0ca58e6 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -241,13 +241,16 @@ func SetupVRFV2_5Environment(
mockNativeLINKFeed contracts.MockETHLINKFeed,
numberOfConsumers int,
numberOfSubToCreate int,
+ l zerolog.Logger,
) (*VRFV2_5Contracts, []*big.Int, *VRFV2PlusData, error) {
-
+ l.Info().Msg("Starting VRFV2 Plus environment setup")
+ l.Info().Msg("Deploying VRFV2 Plus contracts")
vrfv2_5Contracts, err := DeployVRFV2_5Contracts(env.ContractDeployer, env.EVMClient, numberOfConsumers)
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrDeployVRFV2_5Contracts)
}
+ l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Setting Coordinator Config")
err = vrfv2_5Contracts.Coordinator.SetConfig(
vrfv2PlusConfig.MinimumConfirmations,
vrfv2PlusConfig.MaxGasLimitCoordinatorConfig,
@@ -263,6 +266,7 @@ func SetupVRFV2_5Environment(
return nil, nil, nil, errors.Wrap(err, ErrSetVRFCoordinatorConfig)
}
+ l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Setting Link and ETH/LINK feed")
err = vrfv2_5Contracts.Coordinator.SetLINKAndLINKNativeFeed(linkToken.Address(), mockNativeLINKFeed.Address())
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrSetLinkNativeLinkFeed)
@@ -271,32 +275,12 @@ func SetupVRFV2_5Environment(
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
}
-
- subIDs, err := CreateSubsAndFund(env, vrfv2PlusConfig, linkToken, vrfv2_5Contracts, numberOfSubToCreate)
- if err != nil {
- return nil, nil, nil, err
- }
-
- subToConsumersMap := map[*big.Int][]contracts.VRFv2PlusLoadTestConsumer{}
-
- //each subscription will have the same consumers
- for _, subID := range subIDs {
- subToConsumersMap[subID] = vrfv2_5Contracts.LoadTestConsumers
- }
-
- err = AddConsumersToSubs(
- subToConsumersMap,
- vrfv2_5Contracts.Coordinator,
- )
+ l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Creating and funding subscriptions, adding consumers")
+ subIDs, err := CreateFundSubsAndAddConsumers(env, vrfv2PlusConfig, linkToken, vrfv2_5Contracts.Coordinator, vrfv2_5Contracts.LoadTestConsumers, numberOfSubToCreate)
if err != nil {
return nil, nil, nil, err
}
-
- err = env.EVMClient.WaitForEvents()
- if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
- }
-
+ l.Info().Str("Node URL", env.ClCluster.NodeAPIs()[0].URL()).Msg("Creating VRF Key on the Node")
vrfKey, err := env.ClCluster.NodeAPIs()[0].MustCreateVRFKey()
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrCreatingVRFv2PlusKey)
@@ -307,6 +291,7 @@ func SetupVRFV2_5Environment(
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrNodePrimaryKey)
}
+ l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Registering Proving Key")
provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, nativeTokenPrimaryKeyAddress, vrfv2_5Contracts.Coordinator)
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrRegisteringProvingKey)
@@ -318,6 +303,7 @@ func SetupVRFV2_5Environment(
chainID := env.EVMClient.GetChainID()
+ l.Info().Msg("Creating VRFV2 Plus Job")
job, err := CreateVRFV2PlusJob(
env.ClCluster.NodeAPIs()[0],
vrfv2_5Contracts.Coordinator.Address(),
@@ -340,6 +326,7 @@ func SetupVRFV2_5Environment(
nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig,
node.WithVRFv2EVMEstimator(addr),
)
+ l.Info().Msg("Restarting Node with new sending key PriceMax configuration")
err = env.ClCluster.Nodes[0].Restart(nodeConfig)
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrRestartCLNode)
@@ -358,17 +345,52 @@ func SetupVRFV2_5Environment(
chainID,
}
+ l.Info().Msg("VRFV2 Plus environment setup is finished")
return vrfv2_5Contracts, subIDs, &data, nil
}
+func CreateFundSubsAndAddConsumers(
+ env *test_env.CLClusterTestEnv,
+ vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ linkToken contracts.LinkToken,
+ coordinator contracts.VRFCoordinatorV2_5,
+ consumers []contracts.VRFv2PlusLoadTestConsumer,
+ numberOfSubToCreate int,
+) ([]*big.Int, error) {
+ subIDs, err := CreateSubsAndFund(env, vrfv2PlusConfig, linkToken, coordinator, numberOfSubToCreate)
+ if err != nil {
+ return nil, err
+ }
+ subToConsumersMap := map[*big.Int][]contracts.VRFv2PlusLoadTestConsumer{}
+
+ //each subscription will have the same consumers
+ for _, subID := range subIDs {
+ subToConsumersMap[subID] = consumers
+ }
+
+ err = AddConsumersToSubs(
+ subToConsumersMap,
+ coordinator,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ err = env.EVMClient.WaitForEvents()
+ if err != nil {
+ return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ }
+ return subIDs, nil
+}
+
func CreateSubsAndFund(
env *test_env.CLClusterTestEnv,
vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
linkToken contracts.LinkToken,
- vrfv2_5Contracts *VRFV2_5Contracts,
+ coordinator contracts.VRFCoordinatorV2_5,
subAmountToCreate int,
) ([]*big.Int, error) {
- subs, err := CreateSubs(env, vrfv2_5Contracts.Coordinator, subAmountToCreate)
+ subs, err := CreateSubs(env, coordinator, subAmountToCreate)
if err != nil {
return nil, err
}
@@ -376,7 +398,7 @@ func CreateSubsAndFund(
if err != nil {
return nil, errors.Wrap(err, ErrWaitTXsComplete)
}
- err = FundSubscriptions(env, vrfv2PlusConfig, linkToken, vrfv2_5Contracts.Coordinator, subs)
+ err = FundSubscriptions(env, vrfv2PlusConfig, linkToken, coordinator, subs)
if err != nil {
return nil, err
}
@@ -503,21 +525,27 @@ func SetupVRFV2PlusWrapperEnvironment(
return wrapperContracts, wrapperSubID, nil
}
func CreateSubAndFindSubID(env *test_env.CLClusterTestEnv, coordinator contracts.VRFCoordinatorV2_5) (*big.Int, error) {
- err := coordinator.CreateSubscription()
+ tx, err := coordinator.CreateSubscription()
if err != nil {
return nil, errors.Wrap(err, ErrCreateVRFSubscription)
}
-
- sub, err := coordinator.WaitForSubscriptionCreatedEvent(time.Second * 10)
+ err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrFindSubID)
+ return nil, errors.Wrap(err, ErrWaitTXsComplete)
}
- err = env.EVMClient.WaitForEvents()
+ receipt, err := env.EVMClient.GetTxReceipt(tx.Hash())
+
+ //SubscriptionsCreated Log should be emitted with the subscription ID
+ subID := receipt.Logs[0].Topics[1].Big()
+
+ //verify that the subscription was created
+ _, err = coordinator.FindSubscriptionID(subID)
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, errors.Wrap(err, ErrFindSubID)
}
- return sub.SubId, nil
+
+ return subID, nil
}
func GetUpgradedCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion) (linkTotalBalance *big.Int, nativeTokenTotalBalance *big.Int, err error) {
diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go
index 656cabb92e..f0f57f58e7 100644
--- a/integration-tests/contracts/contract_vrf_models.go
+++ b/integration-tests/contracts/contract_vrf_models.go
@@ -73,7 +73,7 @@ type VRFCoordinatorV2_5 interface {
publicProvingKey [2]*big.Int,
) error
HashOfKey(ctx context.Context, pubKey [2]*big.Int) ([32]byte, error)
- CreateSubscription() error
+ CreateSubscription() (*types.Transaction, error)
GetActiveSubscriptionIds(ctx context.Context, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error)
Migrate(subId *big.Int, coordinatorAddress string) error
RegisterMigratableCoordinator(migratableCoordinatorAddress string) error
@@ -83,7 +83,7 @@ type VRFCoordinatorV2_5 interface {
GetSubscription(ctx context.Context, subID *big.Int) (vrf_coordinator_v2_5.GetSubscription, error)
GetNativeTokenTotalBalance(ctx context.Context) (*big.Int, error)
GetLinkTotalBalance(ctx context.Context) (*big.Int, error)
- FindSubscriptionID() (*big.Int, error)
+ FindSubscriptionID(subID *big.Int) (*big.Int, error)
WaitForSubscriptionCreatedEvent(timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCreated, error)
WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error)
WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []*big.Int, sender []common.Address, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, error)
diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go
index df7cca54b2..1488f97131 100644
--- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go
+++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go
@@ -182,16 +182,16 @@ func (v *EthereumVRFCoordinatorV2_5) RegisterProvingKey(
return v.client.ProcessTransaction(tx)
}
-func (v *EthereumVRFCoordinatorV2_5) CreateSubscription() error {
+func (v *EthereumVRFCoordinatorV2_5) CreateSubscription() (*types.Transaction, error) {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
- return err
+ return nil, err
}
tx, err := v.coordinator.CreateSubscription(opts)
if err != nil {
- return err
+ return nil, err
}
- return v.client.ProcessTransaction(tx)
+ return tx, v.client.ProcessTransaction(tx)
}
func (v *EthereumVRFCoordinatorV2_5) Migrate(subId *big.Int, coordinatorAddress string) error {
@@ -250,11 +250,11 @@ func (v *EthereumVRFCoordinatorV2_5) FundSubscriptionWithNative(subId *big.Int,
return v.client.ProcessTransaction(tx)
}
-func (v *EthereumVRFCoordinatorV2_5) FindSubscriptionID() (*big.Int, error) {
+func (v *EthereumVRFCoordinatorV2_5) FindSubscriptionID(subID *big.Int) (*big.Int, error) {
owner := v.client.GetDefaultWallet().Address()
subscriptionIterator, err := v.coordinator.FilterSubscriptionCreated(
nil,
- nil,
+ []*big.Int{subID},
)
if err != nil {
return nil, err
diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go
index 329e4abf13..50003c8286 100644
--- a/integration-tests/load/vrfv2plus/config.go
+++ b/integration-tests/load/vrfv2plus/config.go
@@ -36,8 +36,11 @@ type PerformanceConfig struct {
type ExistingEnvConfig struct {
CoordinatorAddress string `toml:"coordinator_address"`
ConsumerAddress string `toml:"consumer_address"`
+ LinkAddress string `toml:"link_address"`
SubID string `toml:"sub_id"`
KeyHash string `toml:"key_hash"`
+ SubFunding
+ CreateFundSubsAndAddConsumers bool `toml:"create_fund_subs_and_add_consumers"`
}
type NewEnvConfig struct {
@@ -49,9 +52,13 @@ type Common struct {
}
type Funding struct {
- NodeFunds float64 `toml:"node_funds"`
- SubFundsLink int64 `toml:"sub_funds_link"`
- SubFundsNative int64 `toml:"sub_funds_native"`
+ NodeFunds float64 `toml:"node_funds"`
+ SubFunding
+}
+
+type SubFunding struct {
+ SubFundsLink int64 `toml:"sub_funds_link"`
+ SubFundsNative int64 `toml:"sub_funds_native"`
}
type Soak struct {
diff --git a/integration-tests/load/vrfv2plus/config.toml b/integration-tests/load/vrfv2plus/config.toml
index 31a0bf5665..05e22bd51e 100644
--- a/integration-tests/load/vrfv2plus/config.toml
+++ b/integration-tests/load/vrfv2plus/config.toml
@@ -3,17 +3,19 @@
minimum_confirmations = 3
[NewEnvConfig]
-sub_funds_link = 1000
-sub_funds_native = 1000
+sub_funds_link = 1
+sub_funds_native = 1
node_funds = 10
-
[ExistingEnvConfig]
-coordinator_address = "0x4931Ce2e341398c8eD8A5D0F6ADb920476D6DaBb"
+coordinator_address = "0x27b61f155F772b291D1d9B478BeAd37B2Ae447b0"
consumer_address = "0x087F232165D9bA1A602f148025e5D0666953F64a"
sub_id = "52116875585187328970776211988181422347535732407068188096422095950800466618218"
-key_hash = "0x4c422465ed6a06cfc84575a5437fef7b9dc6263133f648afbe6ae7b2c694d3b3"
-
+key_hash = "0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae"
+create_fund_subs_and_add_consumers = true
+link_address = "0x779877A7B0D9E8603169DdbD7836e478b4624789"
+sub_funds_link = 3
+sub_funds_native = 1
# 10 RPM - 1 tx request with 1 rand request in each tx every 6 seconds
[Soak]
@@ -29,7 +31,7 @@ rate_limit_unit_duration = "3s"
rps = 1
randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting
-number_of_sub_to_create = 10
+number_of_sub_to_create = 5
# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx
[Stress]
@@ -37,7 +39,7 @@ rate_limit_unit_duration = "1s"
rps = 3
randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting
-number_of_sub_to_create = 20
+number_of_sub_to_create = 5
# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds
[Spike]
diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
index a3cb4d4b7f..e619cf78fd 100644
--- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go
+++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
@@ -74,6 +74,9 @@ func TestVRFV2PlusPerformance(t *testing.T) {
//todo: temporary solution with envconfig and toml config until VRF-662 is implemented
vrfv2PlusConfig.CoordinatorAddress = cfg.ExistingEnvConfig.CoordinatorAddress
vrfv2PlusConfig.ConsumerAddress = cfg.ExistingEnvConfig.ConsumerAddress
+ vrfv2PlusConfig.LinkAddress = cfg.ExistingEnvConfig.LinkAddress
+ vrfv2PlusConfig.SubscriptionFundingAmountLink = cfg.ExistingEnvConfig.SubFunding.SubFundsLink
+ vrfv2PlusConfig.SubscriptionFundingAmountNative = cfg.ExistingEnvConfig.SubFunding.SubFundsNative
vrfv2PlusConfig.SubID = cfg.ExistingEnvConfig.SubID
vrfv2PlusConfig.KeyHash = cfg.ExistingEnvConfig.KeyHash
@@ -90,17 +93,29 @@ func TestVRFV2PlusPerformance(t *testing.T) {
coordinator, err := env.ContractLoader.LoadVRFCoordinatorV2_5(vrfv2PlusConfig.CoordinatorAddress)
require.NoError(t, err)
- consumer, err := env.ContractLoader.LoadVRFv2PlusLoadTestConsumer(vrfv2PlusConfig.ConsumerAddress)
- require.NoError(t, err)
+ var consumers []contracts.VRFv2PlusLoadTestConsumer
+ if cfg.ExistingEnvConfig.CreateFundSubsAndAddConsumers {
+ linkToken, err := env.ContractLoader.LoadLINKToken(vrfv2PlusConfig.LinkAddress)
+ require.NoError(t, err)
+ consumers, err = vrfv2plus.DeployVRFV2PlusConsumers(env.ContractDeployer, coordinator, 1)
+ require.NoError(t, err)
+ subIDs, err = vrfv2plus.CreateFundSubsAndAddConsumers(env, &vrfv2PlusConfig, linkToken, coordinator, consumers, vrfv2PlusConfig.NumberOfSubToCreate)
+ require.NoError(t, err)
+ } else {
+ consumer, err := env.ContractLoader.LoadVRFv2PlusLoadTestConsumer(vrfv2PlusConfig.ConsumerAddress)
+ require.NoError(t, err)
+ consumers = append(consumers, consumer)
+ var ok bool
+ subID, ok := new(big.Int).SetString(vrfv2PlusConfig.SubID, 10)
+ require.True(t, ok)
+ subIDs = append(subIDs, subID)
+ }
vrfv2PlusContracts = &vrfv2plus.VRFV2_5Contracts{
Coordinator: coordinator,
- LoadTestConsumers: []contracts.VRFv2PlusLoadTestConsumer{consumer},
+ LoadTestConsumers: consumers,
BHS: nil,
}
- var ok bool
- subID, ok := new(big.Int).SetString(vrfv2PlusConfig.SubID, 10)
- require.True(t, ok)
vrfv2PlusData = &vrfv2plus.VRFV2PlusData{
VRFV2PlusKeyData: vrfv2plus.VRFV2PlusKeyData{
@@ -112,7 +127,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
PrimaryEthAddress: "",
ChainID: nil,
}
- subIDs = append(subIDs, subID)
+
} else {
//todo: temporary solution with envconfig and toml config until VRF-662 is implemented
vrfv2PlusConfig.ChainlinkNodeFunding = cfg.NewEnvConfig.NodeFunds
@@ -150,6 +165,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
mockETHLinkFeed,
1,
vrfv2PlusConfig.NumberOfSubToCreate,
+ l,
)
require.NoError(t, err, "error setting up VRF v2_5 env")
}
@@ -198,7 +214,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
var wg sync.WaitGroup
wg.Add(1)
//todo - timeout should be configurable depending on the perf test type
- requestCount, fulfilmentCount, err := vrfv2plus.WaitForRequestCountEqualToFulfilmentCount(consumer, 30*time.Second, &wg)
+ requestCount, fulfilmentCount, err := vrfv2plus.WaitForRequestCountEqualToFulfilmentCount(consumer, 2*time.Minute, &wg)
require.NoError(t, err)
wg.Wait()
@@ -212,7 +228,8 @@ func TestVRFV2PlusPerformance(t *testing.T) {
func teardown(
t *testing.T,
consumer contracts.VRFv2PlusLoadTestConsumer,
- lc *wasp.LokiClient, updatedLabels map[string]string,
+ lc *wasp.LokiClient,
+ updatedLabels map[string]string,
testReporter *testreporters.VRFV2PlusTestReporter,
testType string,
vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go
index c2cc0878b6..408e5a95ed 100644
--- a/integration-tests/smoke/vrfv2plus_test.go
+++ b/integration-tests/smoke/vrfv2plus_test.go
@@ -46,7 +46,7 @@ func TestVRFv2Plus(t *testing.T) {
linkToken, err := actions.DeployLINKToken(env.ContractDeployer)
require.NoError(t, err, "error deploying LINK contract")
- vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkToken, mockETHLinkFeed, 1, 1)
+ vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkToken, mockETHLinkFeed, 1, 1, l)
require.NoError(t, err, "error setting up VRF v2_5 env")
subID := subIDs[0]
@@ -271,7 +271,7 @@ func TestVRFv2PlusMigration(t *testing.T) {
linkAddress, err := actions.DeployLINKToken(env.ContractDeployer)
require.NoError(t, err, "error deploying LINK contract")
- vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkAddress, mockETHLinkFeedAddress, 2, 1)
+ vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkAddress, mockETHLinkFeedAddress, 2, 1, l)
require.NoError(t, err, "error setting up VRF v2_5 env")
subID := subIDs[0]
From d8414631ddf1464eb4b06056cbfa21cbf991bcfa Mon Sep 17 00:00:00 2001
From: "app-token-issuer-infra-releng[bot]"
<120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com>
Date: Fri, 27 Oct 2023 13:56:54 +0300
Subject: [PATCH 020/327] Update Operator UI from v0.8.0-06f745d to
v0.8.0-e10948a (#11094)
* Update Operator UI from v0.8.0-06f745d to v0.8.0-e10948a
* Sig scanner check
---------
Co-authored-by: github-merge-queue[bot]
Co-authored-by: george-dorin
---
operator_ui/TAG | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/operator_ui/TAG b/operator_ui/TAG
index 023fd8732c..e08ca07267 100644
--- a/operator_ui/TAG
+++ b/operator_ui/TAG
@@ -1 +1 @@
-v0.8.0-06f745d
+v0.8.0-e10948a
From e6118da8b89033d857efa1aef6d7f4ba9bdd9d91 Mon Sep 17 00:00:00 2001
From: george-dorin <120329946+george-dorin@users.noreply.github.com>
Date: Fri, 27 Oct 2023 15:09:24 +0300
Subject: [PATCH 021/327] Add string equivalent for observation price, bid, ask
(#11077)
* Add string equivalent for observation price, bid, ask
* Update logging
---
core/services/ocrcommon/telemetry.go | 64 ++--
core/services/ocrcommon/telemetry_test.go | 57 ++--
.../telem/telem_enhanced_ea_mercury.pb.go | 280 ++++++++++--------
.../telem/telem_enhanced_ea_mercury.proto | 3 +
4 files changed, 227 insertions(+), 177 deletions(-)
diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go
index 54a5002093..5277143c8b 100644
--- a/core/services/ocrcommon/telemetry.go
+++ b/core/services/ocrcommon/telemetry.go
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "math/big"
"github.com/ethereum/go-ethereum/common"
@@ -230,7 +231,7 @@ func (e *EnhancedTelemetryService[T]) collectAndSend(trrs *pipeline.TaskRunResul
}
eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse))
if err != nil {
- e.lggr.Warnf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID())
+ e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", err)
}
value := e.getParsedValue(trrs, trr)
@@ -278,39 +279,42 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(obs relaym
bridgeRawResponse, ok := trr.Result.Value.(string)
if !ok {
- e.lggr.Warnf("cannot get bridge response from bridge task, job %d, id %s", e.job.ID, trr.Task.DotID())
+ e.lggr.Warnf("cannot get bridge response from bridge task, job %d, id %s, expected string got %T", e.job.ID, trr.Task.DotID(), trr.Result.Value)
continue
}
eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse))
if err != nil {
- e.lggr.Warnf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID())
+ e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", err)
}
assetSymbol := e.getAssetSymbolFromRequestData(bridgeTask.RequestData)
benchmarkPrice, bidPrice, askPrice := e.getPricesFromResults(trr, &trrs)
t := &telem.EnhancedEAMercury{
- DataSource: eaTelem.DataSource,
- DpBenchmarkPrice: benchmarkPrice,
- DpBid: bidPrice,
- DpAsk: askPrice,
- CurrentBlockNumber: obsBlockNum,
- CurrentBlockHash: common.BytesToHash(obsBlockHash).String(),
- CurrentBlockTimestamp: obsBlockTimestamp,
- BridgeTaskRunStartedTimestamp: trr.CreatedAt.UnixMilli(),
- BridgeTaskRunEndedTimestamp: trr.FinishedAt.Time.UnixMilli(),
- ProviderRequestedTimestamp: eaTelem.ProviderRequestedTimestamp,
- ProviderReceivedTimestamp: eaTelem.ProviderReceivedTimestamp,
- ProviderDataStreamEstablished: eaTelem.ProviderDataStreamEstablished,
- ProviderIndicatedTime: eaTelem.ProviderIndicatedTime,
- Feed: e.job.OCR2OracleSpec.FeedID.Hex(),
- ObservationBenchmarkPrice: obsBenchmarkPrice,
- ObservationBid: obsBid,
- ObservationAsk: obsAsk,
- ConfigDigest: repts.ConfigDigest.Hex(),
- Round: int64(repts.Round),
- Epoch: int64(repts.Epoch),
- AssetSymbol: assetSymbol,
+ DataSource: eaTelem.DataSource,
+ DpBenchmarkPrice: benchmarkPrice,
+ DpBid: bidPrice,
+ DpAsk: askPrice,
+ CurrentBlockNumber: obsBlockNum,
+ CurrentBlockHash: common.BytesToHash(obsBlockHash).String(),
+ CurrentBlockTimestamp: obsBlockTimestamp,
+ BridgeTaskRunStartedTimestamp: trr.CreatedAt.UnixMilli(),
+ BridgeTaskRunEndedTimestamp: trr.FinishedAt.Time.UnixMilli(),
+ ProviderRequestedTimestamp: eaTelem.ProviderRequestedTimestamp,
+ ProviderReceivedTimestamp: eaTelem.ProviderReceivedTimestamp,
+ ProviderDataStreamEstablished: eaTelem.ProviderDataStreamEstablished,
+ ProviderIndicatedTime: eaTelem.ProviderIndicatedTime,
+ Feed: e.job.OCR2OracleSpec.FeedID.Hex(),
+ ObservationBenchmarkPrice: obsBenchmarkPrice.Int64(), //Deprecated: observation value will not fit in int64, we will use the string equivalent field ObservationBenchmarkPriceString
+ ObservationBid: obsBid.Int64(), //Deprecated: observation value will not fit in int64, we will use the string equivalent field ObservationBidString
+ ObservationAsk: obsAsk.Int64(), //Deprecated: observation value will not fit in int64, we will use the string equivalent field ObservationAskString
+ ConfigDigest: repts.ConfigDigest.Hex(),
+ Round: int64(repts.Round),
+ Epoch: int64(repts.Epoch),
+ AssetSymbol: assetSymbol,
+ ObservationBenchmarkPriceString: obsBenchmarkPrice.String(),
+ ObservationBidString: obsBid.String(),
+ ObservationAskString: obsAsk.String(),
}
bytes, err := proto.Marshal(t)
@@ -408,17 +412,19 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta
}
// getFinalValues runs a parse on the pipeline.TaskRunResults and returns the values
-func (e *EnhancedTelemetryService[T]) getFinalValues(obs relaymercuryv1.Observation) (int64, int64, int64, int64, []byte, uint64) {
- var benchmarkPrice, bid, ask int64
+func (e *EnhancedTelemetryService[T]) getFinalValues(obs relaymercuryv1.Observation) (*big.Int, *big.Int, *big.Int, int64, []byte, uint64) {
+ benchmarkPrice := big.NewInt(0)
+ bid := big.NewInt(0)
+ ask := big.NewInt(0)
if obs.BenchmarkPrice.Val != nil {
- benchmarkPrice = obs.BenchmarkPrice.Val.Int64()
+ benchmarkPrice = obs.BenchmarkPrice.Val
}
if obs.Bid.Val != nil {
- bid = obs.Bid.Val.Int64()
+ bid = obs.Bid.Val
}
if obs.Ask.Val != nil {
- ask = obs.Ask.Val.Int64()
+ ask = obs.Ask.Val
}
return benchmarkPrice, bid, ask, obs.CurrentBlockNum.Val, obs.CurrentBlockHash.Val, obs.CurrentBlockTimestamp.Val
diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go
index 88fb7de3e3..5d1494a038 100644
--- a/core/services/ocrcommon/telemetry_test.go
+++ b/core/services/ocrcommon/telemetry_test.go
@@ -433,17 +433,17 @@ func TestGetFinalValues(t *testing.T) {
}
benchmarkPrice, bid, ask, blockNr, blockHash, blockTimestamp := e.getFinalValues(o)
- require.Equal(t, benchmarkPrice, int64(111111))
- require.Equal(t, bid, int64(222222))
- require.Equal(t, ask, int64(333333))
+ require.Equal(t, benchmarkPrice, big.NewInt(111111))
+ require.Equal(t, bid, big.NewInt(222222))
+ require.Equal(t, ask, big.NewInt(333333))
require.Equal(t, blockNr, int64(123456789))
require.Equal(t, blockHash, common.HexToHash("0x123321").Bytes())
require.Equal(t, blockTimestamp, uint64(987654321))
benchmarkPrice, bid, ask, blockNr, blockHash, blockTimestamp = e.getFinalValues(mercuryv1.Observation{})
- require.Equal(t, benchmarkPrice, int64(0))
- require.Equal(t, bid, int64(0))
- require.Equal(t, ask, int64(0))
+ require.Equal(t, benchmarkPrice, big.NewInt(0))
+ require.Equal(t, bid, big.NewInt(0))
+ require.Equal(t, ask, big.NewInt(0))
require.Equal(t, blockNr, int64(0))
require.Nil(t, blockHash)
require.Equal(t, blockTimestamp, uint64(0))
@@ -598,27 +598,30 @@ func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
}
expectedTelemetry := telem.EnhancedEAMercury{
- DataSource: "data-source-name",
- DpBenchmarkPrice: 123456.123456,
- DpBid: 1234567.1234567,
- DpAsk: 321123,
- CurrentBlockNumber: 123456789,
- CurrentBlockHash: common.HexToHash("0x123321").String(),
- CurrentBlockTimestamp: 987654321,
- BridgeTaskRunStartedTimestamp: trrsMercury[0].CreatedAt.UnixMilli(),
- BridgeTaskRunEndedTimestamp: trrsMercury[0].FinishedAt.Time.UnixMilli(),
- ProviderRequestedTimestamp: 92233720368547760,
- ProviderReceivedTimestamp: -92233720368547760,
- ProviderDataStreamEstablished: 1,
- ProviderIndicatedTime: -123456789,
- Feed: common.HexToHash("0x111").String(),
- ObservationBenchmarkPrice: 111111,
- ObservationBid: 222222,
- ObservationAsk: 333333,
- ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000",
- Round: 22,
- Epoch: 11,
- AssetSymbol: "USD/LINK",
+ DataSource: "data-source-name",
+ DpBenchmarkPrice: 123456.123456,
+ DpBid: 1234567.1234567,
+ DpAsk: 321123,
+ CurrentBlockNumber: 123456789,
+ CurrentBlockHash: common.HexToHash("0x123321").String(),
+ CurrentBlockTimestamp: 987654321,
+ BridgeTaskRunStartedTimestamp: trrsMercury[0].CreatedAt.UnixMilli(),
+ BridgeTaskRunEndedTimestamp: trrsMercury[0].FinishedAt.Time.UnixMilli(),
+ ProviderRequestedTimestamp: 92233720368547760,
+ ProviderReceivedTimestamp: -92233720368547760,
+ ProviderDataStreamEstablished: 1,
+ ProviderIndicatedTime: -123456789,
+ Feed: common.HexToHash("0x111").String(),
+ ObservationBenchmarkPrice: 111111,
+ ObservationBid: 222222,
+ ObservationAsk: 333333,
+ ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000",
+ Round: 22,
+ Epoch: 11,
+ AssetSymbol: "USD/LINK",
+ ObservationBenchmarkPriceString: "111111",
+ ObservationBidString: "222222",
+ ObservationAskString: "333333",
}
expectedMessage, _ := proto.Marshal(&expectedTelemetry)
diff --git a/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go b/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go
index 571a725b88..32c3061cc4 100644
--- a/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go
+++ b/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go
@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
-// protoc v3.21.12
-// source: telem_enhanced_ea_mercury.proto
+// protoc-gen-go v1.31.0
+// protoc v4.24.3
+// source: core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
package telem
@@ -25,33 +25,36 @@ type EnhancedEAMercury struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- DataSource string `protobuf:"bytes,1,opt,name=data_source,json=dataSource,proto3" json:"data_source,omitempty"`
- DpBenchmarkPrice float64 `protobuf:"fixed64,2,opt,name=dp_benchmark_price,json=dpBenchmarkPrice,proto3" json:"dp_benchmark_price,omitempty"`
- DpBid float64 `protobuf:"fixed64,3,opt,name=dp_bid,json=dpBid,proto3" json:"dp_bid,omitempty"`
- DpAsk float64 `protobuf:"fixed64,4,opt,name=dp_ask,json=dpAsk,proto3" json:"dp_ask,omitempty"`
- CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=current_block_number,json=currentBlockNumber,proto3" json:"current_block_number,omitempty"`
- CurrentBlockHash string `protobuf:"bytes,6,opt,name=current_block_hash,json=currentBlockHash,proto3" json:"current_block_hash,omitempty"`
- CurrentBlockTimestamp uint64 `protobuf:"varint,7,opt,name=current_block_timestamp,json=currentBlockTimestamp,proto3" json:"current_block_timestamp,omitempty"`
- BridgeTaskRunStartedTimestamp int64 `protobuf:"varint,8,opt,name=bridge_task_run_started_timestamp,json=bridgeTaskRunStartedTimestamp,proto3" json:"bridge_task_run_started_timestamp,omitempty"`
- BridgeTaskRunEndedTimestamp int64 `protobuf:"varint,9,opt,name=bridge_task_run_ended_timestamp,json=bridgeTaskRunEndedTimestamp,proto3" json:"bridge_task_run_ended_timestamp,omitempty"`
- ProviderRequestedTimestamp int64 `protobuf:"varint,10,opt,name=provider_requested_timestamp,json=providerRequestedTimestamp,proto3" json:"provider_requested_timestamp,omitempty"`
- ProviderReceivedTimestamp int64 `protobuf:"varint,11,opt,name=provider_received_timestamp,json=providerReceivedTimestamp,proto3" json:"provider_received_timestamp,omitempty"`
- ProviderDataStreamEstablished int64 `protobuf:"varint,12,opt,name=provider_data_stream_established,json=providerDataStreamEstablished,proto3" json:"provider_data_stream_established,omitempty"`
- ProviderIndicatedTime int64 `protobuf:"varint,13,opt,name=provider_indicated_time,json=providerIndicatedTime,proto3" json:"provider_indicated_time,omitempty"`
- Feed string `protobuf:"bytes,14,opt,name=feed,proto3" json:"feed,omitempty"`
- ObservationBenchmarkPrice int64 `protobuf:"varint,15,opt,name=observation_benchmark_price,json=observationBenchmarkPrice,proto3" json:"observation_benchmark_price,omitempty"`
- ObservationBid int64 `protobuf:"varint,16,opt,name=observation_bid,json=observationBid,proto3" json:"observation_bid,omitempty"`
- ObservationAsk int64 `protobuf:"varint,17,opt,name=observation_ask,json=observationAsk,proto3" json:"observation_ask,omitempty"`
- ConfigDigest string `protobuf:"bytes,18,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"`
- Round int64 `protobuf:"varint,19,opt,name=round,proto3" json:"round,omitempty"`
- Epoch int64 `protobuf:"varint,20,opt,name=epoch,proto3" json:"epoch,omitempty"`
- AssetSymbol string `protobuf:"bytes,21,opt,name=asset_symbol,json=assetSymbol,proto3" json:"asset_symbol,omitempty"`
+ DataSource string `protobuf:"bytes,1,opt,name=data_source,json=dataSource,proto3" json:"data_source,omitempty"`
+ DpBenchmarkPrice float64 `protobuf:"fixed64,2,opt,name=dp_benchmark_price,json=dpBenchmarkPrice,proto3" json:"dp_benchmark_price,omitempty"`
+ DpBid float64 `protobuf:"fixed64,3,opt,name=dp_bid,json=dpBid,proto3" json:"dp_bid,omitempty"`
+ DpAsk float64 `protobuf:"fixed64,4,opt,name=dp_ask,json=dpAsk,proto3" json:"dp_ask,omitempty"`
+ CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=current_block_number,json=currentBlockNumber,proto3" json:"current_block_number,omitempty"`
+ CurrentBlockHash string `protobuf:"bytes,6,opt,name=current_block_hash,json=currentBlockHash,proto3" json:"current_block_hash,omitempty"`
+ CurrentBlockTimestamp uint64 `protobuf:"varint,7,opt,name=current_block_timestamp,json=currentBlockTimestamp,proto3" json:"current_block_timestamp,omitempty"`
+ BridgeTaskRunStartedTimestamp int64 `protobuf:"varint,8,opt,name=bridge_task_run_started_timestamp,json=bridgeTaskRunStartedTimestamp,proto3" json:"bridge_task_run_started_timestamp,omitempty"`
+ BridgeTaskRunEndedTimestamp int64 `protobuf:"varint,9,opt,name=bridge_task_run_ended_timestamp,json=bridgeTaskRunEndedTimestamp,proto3" json:"bridge_task_run_ended_timestamp,omitempty"`
+ ProviderRequestedTimestamp int64 `protobuf:"varint,10,opt,name=provider_requested_timestamp,json=providerRequestedTimestamp,proto3" json:"provider_requested_timestamp,omitempty"`
+ ProviderReceivedTimestamp int64 `protobuf:"varint,11,opt,name=provider_received_timestamp,json=providerReceivedTimestamp,proto3" json:"provider_received_timestamp,omitempty"`
+ ProviderDataStreamEstablished int64 `protobuf:"varint,12,opt,name=provider_data_stream_established,json=providerDataStreamEstablished,proto3" json:"provider_data_stream_established,omitempty"`
+ ProviderIndicatedTime int64 `protobuf:"varint,13,opt,name=provider_indicated_time,json=providerIndicatedTime,proto3" json:"provider_indicated_time,omitempty"`
+ Feed string `protobuf:"bytes,14,opt,name=feed,proto3" json:"feed,omitempty"`
+ ObservationBenchmarkPrice int64 `protobuf:"varint,15,opt,name=observation_benchmark_price,json=observationBenchmarkPrice,proto3" json:"observation_benchmark_price,omitempty"`
+ ObservationBid int64 `protobuf:"varint,16,opt,name=observation_bid,json=observationBid,proto3" json:"observation_bid,omitempty"`
+ ObservationAsk int64 `protobuf:"varint,17,opt,name=observation_ask,json=observationAsk,proto3" json:"observation_ask,omitempty"`
+ ConfigDigest string `protobuf:"bytes,18,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"`
+ Round int64 `protobuf:"varint,19,opt,name=round,proto3" json:"round,omitempty"`
+ Epoch int64 `protobuf:"varint,20,opt,name=epoch,proto3" json:"epoch,omitempty"`
+ AssetSymbol string `protobuf:"bytes,21,opt,name=asset_symbol,json=assetSymbol,proto3" json:"asset_symbol,omitempty"`
+ ObservationBenchmarkPriceString string `protobuf:"bytes,22,opt,name=observation_benchmark_price_string,json=observationBenchmarkPriceString,proto3" json:"observation_benchmark_price_string,omitempty"`
+ ObservationBidString string `protobuf:"bytes,23,opt,name=observation_bid_string,json=observationBidString,proto3" json:"observation_bid_string,omitempty"`
+ ObservationAskString string `protobuf:"bytes,24,opt,name=observation_ask_string,json=observationAskString,proto3" json:"observation_ask_string,omitempty"`
}
func (x *EnhancedEAMercury) Reset() {
*x = EnhancedEAMercury{}
if protoimpl.UnsafeEnabled {
- mi := &file_telem_enhanced_ea_mercury_proto_msgTypes[0]
+ mi := &file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -64,7 +67,7 @@ func (x *EnhancedEAMercury) String() string {
func (*EnhancedEAMercury) ProtoMessage() {}
func (x *EnhancedEAMercury) ProtoReflect() protoreflect.Message {
- mi := &file_telem_enhanced_ea_mercury_proto_msgTypes[0]
+ mi := &file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -77,7 +80,7 @@ func (x *EnhancedEAMercury) ProtoReflect() protoreflect.Message {
// Deprecated: Use EnhancedEAMercury.ProtoReflect.Descriptor instead.
func (*EnhancedEAMercury) Descriptor() ([]byte, []int) {
- return file_telem_enhanced_ea_mercury_proto_rawDescGZIP(), []int{0}
+ return file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescGZIP(), []int{0}
}
func (x *EnhancedEAMercury) GetDataSource() string {
@@ -227,98 +230,133 @@ func (x *EnhancedEAMercury) GetAssetSymbol() string {
return ""
}
-var File_telem_enhanced_ea_mercury_proto protoreflect.FileDescriptor
-
-var file_telem_enhanced_ea_mercury_proto_rawDesc = []byte{
- 0x0a, 0x1f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x65, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x64,
- 0x5f, 0x65, 0x61, 0x5f, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0xd5, 0x07, 0x0a, 0x11, 0x45, 0x6e, 0x68,
- 0x61, 0x6e, 0x63, 0x65, 0x64, 0x45, 0x41, 0x4d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x12, 0x1f,
- 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12,
- 0x2c, 0x0a, 0x12, 0x64, 0x70, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f,
- 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x64, 0x70, 0x42,
- 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x15, 0x0a,
- 0x06, 0x64, 0x70, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x64,
- 0x70, 0x42, 0x69, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x70, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x64, 0x70, 0x41, 0x73, 0x6b, 0x12, 0x30, 0x0a, 0x14, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d,
- 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a,
- 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68,
- 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x36, 0x0a, 0x17, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d,
- 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x63, 0x75,
- 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
- 0x61, 0x6d, 0x70, 0x12, 0x48, 0x0a, 0x21, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x74, 0x61,
- 0x73, 0x6b, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1d,
- 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61,
- 0x72, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x44, 0x0a,
- 0x1f, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x75, 0x6e,
- 0x5f, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
- 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x61,
- 0x73, 0x6b, 0x52, 0x75, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
- 0x61, 0x6d, 0x70, 0x12, 0x40, 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f,
- 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
- 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65,
- 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3e, 0x0a, 0x1b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
- 0x72, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73,
- 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x70, 0x72, 0x6f, 0x76,
- 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65,
- 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x47, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
- 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x65, 0x73,
- 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x1d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x53, 0x74, 0x72,
- 0x65, 0x61, 0x6d, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x36,
- 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63,
- 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74,
- 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x65, 0x65, 0x64, 0x18, 0x0e,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x65, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1b, 0x6f, 0x62,
- 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d,
- 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x6e, 0x63,
- 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x62,
- 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x10, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x42, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x62,
- 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x23, 0x0a, 0x0d,
- 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x12, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73,
- 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68,
- 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x21, 0x0a,
- 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x15, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x65, 0x74, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
- 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73,
- 0x6d, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f,
- 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72,
- 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68,
- 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d,
- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+func (x *EnhancedEAMercury) GetObservationBenchmarkPriceString() string {
+ if x != nil {
+ return x.ObservationBenchmarkPriceString
+ }
+ return ""
+}
+
+func (x *EnhancedEAMercury) GetObservationBidString() string {
+ if x != nil {
+ return x.ObservationBidString
+ }
+ return ""
+}
+
+func (x *EnhancedEAMercury) GetObservationAskString() string {
+ if x != nil {
+ return x.ObservationAskString
+ }
+ return ""
+}
+
+var File_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto protoreflect.FileDescriptor
+
+var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDesc = []byte{
+ 0x0a, 0x43, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f,
+ 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f,
+ 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x65, 0x6e, 0x68, 0x61,
+ 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x65, 0x61, 0x5f, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0x8e, 0x09, 0x0a,
+ 0x11, 0x45, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x45, 0x41, 0x4d, 0x65, 0x72, 0x63, 0x75,
+ 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x70, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d,
+ 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52,
+ 0x10, 0x64, 0x70, 0x42, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63,
+ 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x70, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x05, 0x64, 0x70, 0x42, 0x69, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x70, 0x5f, 0x61,
+ 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x64, 0x70, 0x41, 0x73, 0x6b, 0x12,
+ 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x63,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65,
+ 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12,
+ 0x36, 0x0a, 0x17, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x15, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69,
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x48, 0x0a, 0x21, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x1d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x75,
+ 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x12, 0x44, 0x0a, 0x1f, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b,
+ 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x75, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x69,
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x40, 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x76, 0x69,
+ 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64,
+ 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3e, 0x0a, 0x1b, 0x70, 0x72, 0x6f,
+ 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x74,
+ 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+ 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x47, 0x0a, 0x20, 0x70, 0x72, 0x6f,
+ 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
+ 0x6d, 0x5f, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x0c, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x44, 0x61, 0x74,
+ 0x61, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68,
+ 0x65, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69,
+ 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0d, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x64,
+ 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x65,
+ 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x65, 0x65, 0x64, 0x12, 0x3e,
+ 0x0a, 0x1b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x65,
+ 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0f, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x42, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x27,
+ 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69,
+ 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b,
+ 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73,
+ 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44,
+ 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x13,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65,
+ 0x70, 0x6f, 0x63, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63,
+ 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f,
+ 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x65, 0x74, 0x53, 0x79,
+ 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x4b, 0x0a, 0x22, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72,
+ 0x69, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x1f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x6e,
+ 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e,
+ 0x67, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x14, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69,
+ 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x62, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
+ 0x67, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x4e, 0x5a,
+ 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72,
+ 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61,
+ 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e,
+ 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
- file_telem_enhanced_ea_mercury_proto_rawDescOnce sync.Once
- file_telem_enhanced_ea_mercury_proto_rawDescData = file_telem_enhanced_ea_mercury_proto_rawDesc
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescOnce sync.Once
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescData = file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDesc
)
-func file_telem_enhanced_ea_mercury_proto_rawDescGZIP() []byte {
- file_telem_enhanced_ea_mercury_proto_rawDescOnce.Do(func() {
- file_telem_enhanced_ea_mercury_proto_rawDescData = protoimpl.X.CompressGZIP(file_telem_enhanced_ea_mercury_proto_rawDescData)
+func file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescGZIP() []byte {
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescOnce.Do(func() {
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescData)
})
- return file_telem_enhanced_ea_mercury_proto_rawDescData
+ return file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescData
}
-var file_telem_enhanced_ea_mercury_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_telem_enhanced_ea_mercury_proto_goTypes = []interface{}{
+var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_goTypes = []interface{}{
(*EnhancedEAMercury)(nil), // 0: telem.EnhancedEAMercury
}
-var file_telem_enhanced_ea_mercury_proto_depIdxs = []int32{
+var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
@@ -326,13 +364,13 @@ var file_telem_enhanced_ea_mercury_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for field type_name
}
-func init() { file_telem_enhanced_ea_mercury_proto_init() }
-func file_telem_enhanced_ea_mercury_proto_init() {
- if File_telem_enhanced_ea_mercury_proto != nil {
+func init() { file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_init() }
+func file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_init() {
+ if File_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
- file_telem_enhanced_ea_mercury_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnhancedEAMercury); i {
case 0:
return &v.state
@@ -349,18 +387,18 @@ func file_telem_enhanced_ea_mercury_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_telem_enhanced_ea_mercury_proto_rawDesc,
+ RawDescriptor: file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
- GoTypes: file_telem_enhanced_ea_mercury_proto_goTypes,
- DependencyIndexes: file_telem_enhanced_ea_mercury_proto_depIdxs,
- MessageInfos: file_telem_enhanced_ea_mercury_proto_msgTypes,
+ GoTypes: file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_goTypes,
+ DependencyIndexes: file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_depIdxs,
+ MessageInfos: file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_msgTypes,
}.Build()
- File_telem_enhanced_ea_mercury_proto = out.File
- file_telem_enhanced_ea_mercury_proto_rawDesc = nil
- file_telem_enhanced_ea_mercury_proto_goTypes = nil
- file_telem_enhanced_ea_mercury_proto_depIdxs = nil
+ File_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto = out.File
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDesc = nil
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_goTypes = nil
+ file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_depIdxs = nil
}
diff --git a/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto b/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
index 805d976d2d..92242fd2a1 100644
--- a/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
+++ b/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
@@ -26,4 +26,7 @@ message EnhancedEAMercury {
int64 round=19;
int64 epoch=20;
string asset_symbol=21;
+ string observation_benchmark_price_string = 22;
+ string observation_bid_string = 23;
+ string observation_ask_string = 24;
}
From 12ff0e6dabfd52333bf4ebdc3f1725f5c4172ba7 Mon Sep 17 00:00:00 2001
From: Lukasz <120112546+lukaszcl@users.noreply.github.com>
Date: Fri, 27 Oct 2023 15:42:05 +0200
Subject: [PATCH 022/327] Update CTF and SELECTED_NETWORKS env in E2E tests
(#11103)
* Update CTF and SELECTED_NETWORKS env
* Update go mod
---
integration-tests/benchmark/keeper_test.go | 2 +-
integration-tests/chaos/automation_chaos_test.go | 11 ++++++-----
integration-tests/chaos/ocr2vrf_chaos_test.go | 4 ++--
integration-tests/chaos/ocr_chaos_test.go | 2 +-
integration-tests/docker/test_env/test_env_builder.go | 2 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
integration-tests/load/functions/setup.go | 2 +-
integration-tests/performance/cron_test.go | 2 +-
integration-tests/performance/directrequest_test.go | 2 +-
integration-tests/performance/flux_test.go | 2 +-
integration-tests/performance/keeper_test.go | 2 +-
integration-tests/performance/ocr_test.go | 2 +-
integration-tests/performance/vrf_test.go | 2 +-
integration-tests/reorg/automation_reorg_test.go | 4 ++--
integration-tests/smoke/automation_test.go | 8 ++++----
integration-tests/smoke/ocr2_test.go | 2 +-
integration-tests/smoke/ocr2vrf_test.go | 2 +-
integration-tests/testsetups/ocr.go | 8 ++++----
19 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index 7178ab854e..ed26caf470 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -299,7 +299,7 @@ func getEnv(key, fallback string) string {
func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockchain.EVMNetwork) {
l := logging.GetTestLogger(t)
- testNetwork := networks.SelectedNetwork // Environment currently being used to run benchmark test on
+ testNetwork := networks.MustGetSelectedNetworksFromEnv()[0] // Environment currently being used to run benchmark test on
blockTime := "1"
networkDetailTOML := `MinIncomingConfirmations = 1`
diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go
index 244f6c36ea..62f85d3256 100644
--- a/integration-tests/chaos/automation_chaos_test.go
+++ b/integration-tests/chaos/automation_chaos_test.go
@@ -43,7 +43,7 @@ ListenAddresses = ["0.0.0.0:6690"]`
defaultAutomationSettings = map[string]interface{}{
"replicas": 6,
- "toml": client.AddNetworksConfig(baseTOML, networks.SelectedNetwork),
+ "toml": client.AddNetworksConfig(baseTOML, networks.MustGetSelectedNetworksFromEnv()[0]),
"db": map[string]interface{}{
"stateful": true,
"capacity": "1Gi",
@@ -61,9 +61,10 @@ ListenAddresses = ["0.0.0.0:6690"]`
}
defaultEthereumSettings = ðereum.Props{
- NetworkName: networks.SelectedNetwork.Name,
- Simulated: networks.SelectedNetwork.Simulated,
- WsURLs: networks.SelectedNetwork.URLs,
+ // utils.MustGetSelectedNetworksFromEnv()
+ NetworkName: networks.MustGetSelectedNetworksFromEnv()[0].Name,
+ Simulated: networks.MustGetSelectedNetworksFromEnv()[0].Simulated,
+ WsURLs: networks.MustGetSelectedNetworksFromEnv()[0].URLs,
Values: map[string]interface{}{
"resources": map[string]interface{}{
"requests": map[string]interface{}{
@@ -182,7 +183,7 @@ func TestAutomationChaos(t *testing.T) {
testCase := tst
t.Run(fmt.Sprintf("Automation_%s", name), func(t *testing.T) {
t.Parallel()
- network := networks.SelectedNetwork // Need a new copy of the network for each test
+ network := networks.MustGetSelectedNetworksFromEnv()[0] // Need a new copy of the network for each test
testEnvironment := environment.
New(&environment.Config{
diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go
index 1d7f61f783..cbab1bf9e7 100644
--- a/integration-tests/chaos/ocr2vrf_chaos_test.go
+++ b/integration-tests/chaos/ocr2vrf_chaos_test.go
@@ -31,7 +31,7 @@ import (
func TestOCR2VRFChaos(t *testing.T) {
t.Parallel()
l := logging.GetTestLogger(t)
- loadedNetwork := networks.SelectedNetwork
+ loadedNetwork := networks.MustGetSelectedNetworksFromEnv()[0]
defaultOCR2VRFSettings := map[string]interface{}{
"replicas": 6,
@@ -119,7 +119,7 @@ func TestOCR2VRFChaos(t *testing.T) {
testCase := tc
t.Run(fmt.Sprintf("OCR2VRF_%s", testCaseName), func(t *testing.T) {
t.Parallel()
- testNetwork := networks.SelectedNetwork // Need a new copy of the network for each test
+ testNetwork := networks.MustGetSelectedNetworksFromEnv()[0] // Need a new copy of the network for each test
testEnvironment := environment.
New(&environment.Config{
NamespacePrefix: fmt.Sprintf(
diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go
index f3ee12046f..0d72e3932e 100644
--- a/integration-tests/chaos/ocr_chaos_test.go
+++ b/integration-tests/chaos/ocr_chaos_test.go
@@ -53,7 +53,7 @@ var (
)
func TestMain(m *testing.M) {
- defaultOCRSettings["toml"] = client.AddNetworksConfig(config.BaseOCRP2PV1Config, networks.SelectedNetwork)
+ defaultOCRSettings["toml"] = client.AddNetworksConfig(config.BaseOCRP2PV1Config, networks.MustGetSelectedNetworksFromEnv()[0])
os.Exit(m.Run())
}
diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go
index 072728321b..d155024050 100644
--- a/integration-tests/docker/test_env/test_env_builder.go
+++ b/integration-tests/docker/test_env/test_env_builder.go
@@ -238,7 +238,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
}
return b.te, nil
}
- networkConfig := networks.SelectedNetwork
+ networkConfig := networks.MustGetSelectedNetworksFromEnv()[0]
var internalDockerUrls test_env.InternalDockerUrls
if b.hasGeth && networkConfig.Simulated {
networkConfig, internalDockerUrls, err = b.te.StartGeth()
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 7dd2d01778..7683a96692 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -21,7 +21,7 @@ require (
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-env v0.38.3
- github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231018101901-23824db88d36
+ github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231027132403-4898f11e80b6
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.27
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 3be7407727..d280310b9f 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2370,8 +2370,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231018101901-23824db88d36 h1:ow84QG8vEHMvfjGg0RF8HNYh80WcHci6PIenXyY6K8Y=
-github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231018101901-23824db88d36/go.mod h1:RWlmjwnjIGbQAnRfKwe02Ife82nNI3rZmdI0zgkfbyk=
+github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231027132403-4898f11e80b6 h1:f1nUQ/1eUTMwNbOZK0P7P6OHvTDGQSn2KE+LtwY0rXA=
+github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231027132403-4898f11e80b6/go.mod h1:RWlmjwnjIGbQAnRfKwe02Ife82nNI3rZmdI0zgkfbyk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go
index 5d44cbc698..5253c531ee 100644
--- a/integration-tests/load/functions/setup.go
+++ b/integration-tests/load/functions/setup.go
@@ -50,7 +50,7 @@ type S4SecretsCfg struct {
}
func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) {
- bc, err := blockchain.NewEVMClientFromNetwork(networks.SelectedNetwork, log.Logger)
+ bc, err := blockchain.NewEVMClientFromNetwork(networks.MustGetSelectedNetworksFromEnv()[0], log.Logger)
if err != nil {
return nil, err
}
diff --git a/integration-tests/performance/cron_test.go b/integration-tests/performance/cron_test.go
index 959cb0fa3e..84a4964647 100644
--- a/integration-tests/performance/cron_test.go
+++ b/integration-tests/performance/cron_test.go
@@ -109,7 +109,7 @@ func TestCronPerformance(t *testing.T) {
func setupCronTest(t *testing.T) (testEnvironment *environment.Environment) {
logging.Init()
- network := networks.SelectedNetwork
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := ethereum.New(nil)
if !network.Simulated {
evmConfig = ethereum.New(ðereum.Props{
diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go
index 4ff2b85619..faaac5910d 100644
--- a/integration-tests/performance/directrequest_test.go
+++ b/integration-tests/performance/directrequest_test.go
@@ -129,7 +129,7 @@ func TestDirectRequestPerformance(t *testing.T) {
}
func setupDirectRequestTest(t *testing.T) (testEnvironment *environment.Environment) {
- network := networks.SelectedNetwork
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := ethereum.New(nil)
if !network.Simulated {
evmConfig = ethereum.New(ðereum.Props{
diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go
index 3f9db27c10..df3022003e 100644
--- a/integration-tests/performance/flux_test.go
+++ b/integration-tests/performance/flux_test.go
@@ -173,7 +173,7 @@ func TestFluxPerformance(t *testing.T) {
}
func setupFluxTest(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) {
- testNetwork = networks.SelectedNetwork
+ testNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
evmConf := ethereum.New(nil)
if !testNetwork.Simulated {
evmConf = ethereum.New(ðereum.Props{
diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go
index 08ea95b434..7a2cc933de 100644
--- a/integration-tests/performance/keeper_test.go
+++ b/integration-tests/performance/keeper_test.go
@@ -134,7 +134,7 @@ func setupKeeperTest(
contracts.ContractDeployer,
contracts.LinkToken,
) {
- network := networks.SelectedNetwork
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := eth.New(nil)
if !network.Simulated {
evmConfig = eth.New(ð.Props{
diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go
index b18d7f1f79..1db030f1cc 100644
--- a/integration-tests/performance/ocr_test.go
+++ b/integration-tests/performance/ocr_test.go
@@ -90,7 +90,7 @@ func TestOCRBasic(t *testing.T) {
}
func setupOCRTest(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) {
- testNetwork = networks.SelectedNetwork
+ testNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := ethereum.New(nil)
if !testNetwork.Simulated {
evmConfig = ethereum.New(ðereum.Props{
diff --git a/integration-tests/performance/vrf_test.go b/integration-tests/performance/vrf_test.go
index 510e378eb8..c715641692 100644
--- a/integration-tests/performance/vrf_test.go
+++ b/integration-tests/performance/vrf_test.go
@@ -135,7 +135,7 @@ func TestVRFBasic(t *testing.T) {
}
func setupVRFTest(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) {
- testNetwork = networks.SelectedNetwork
+ testNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := ethereum.New(nil)
if !testNetwork.Simulated {
evmConfig = ethereum.New(ðereum.Props{
diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go
index e94e5c2853..a1260cc37a 100644
--- a/integration-tests/reorg/automation_reorg_test.go
+++ b/integration-tests/reorg/automation_reorg_test.go
@@ -48,7 +48,7 @@ HistoryDepth = 400
[EVM.GasEstimator]
Mode = 'FixedPrice'
LimitDefault = 5_000_000`
- activeEVMNetwork = networks.SelectedNetwork
+ activeEVMNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
defaultAutomationSettings = map[string]interface{}{
"toml": client.AddNetworkDetailedConfig(baseTOML, networkTOML, activeEVMNetwork),
"db": map[string]interface{}{
@@ -135,7 +135,7 @@ func TestAutomationReorg(t *testing.T) {
for name, registryVersion := range registryVersions {
t.Run(name, func(t *testing.T) {
t.Parallel()
- network := networks.SelectedNetwork
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
defaultAutomationSettings["replicas"] = numberOfNodes
cd := chainlink.New(0, defaultAutomationSettings)
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 834de5ce48..3addac1b9d 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -79,9 +79,9 @@ var (
func TestMain(m *testing.M) {
logging.Init()
- fmt.Printf("Running Smoke Test on %s\n", networks.SelectedNetwork.Name) // Print to get around disabled logging
- fmt.Printf("Chainlink Image %s\n", os.Getenv("CHAINLINK_IMAGE")) // Print to get around disabled logging
- fmt.Printf("Chainlink Version %s\n", os.Getenv("CHAINLINK_VERSION")) // Print to get around disabled logging
+ fmt.Printf("Running Smoke Test on %s\n", networks.MustGetSelectedNetworksFromEnv()[0].Name) // Print to get around disabled logging
+ fmt.Printf("Chainlink Image %s\n", os.Getenv("CHAINLINK_IMAGE")) // Print to get around disabled logging
+ fmt.Printf("Chainlink Version %s\n", os.Getenv("CHAINLINK_VERSION")) // Print to get around disabled logging
os.Exit(m.Run())
}
@@ -1028,7 +1028,7 @@ func setupAutomationTestDocker(
l := logging.GetTestLogger(t)
// Add registry version to config
registryConfig.RegistryVersion = registryVersion
- network := networks.SelectedNetwork
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
// build the node config
clNodeConfig := node.NewConfig(node.NewBaseConfig())
diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go
index d82d84a207..582ca17f7b 100644
--- a/integration-tests/smoke/ocr2_test.go
+++ b/integration-tests/smoke/ocr2_test.go
@@ -107,7 +107,7 @@ func setupOCR2Test(t *testing.T, forwardersEnabled bool) (
testEnvironment *environment.Environment,
testNetwork blockchain.EVMNetwork,
) {
- testNetwork = networks.SelectedNetwork
+ testNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := ethereum.New(nil)
if !testNetwork.Simulated {
evmConfig = ethereum.New(ðereum.Props{
diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go
index 8148863918..8c102f6fd2 100644
--- a/integration-tests/smoke/ocr2vrf_test.go
+++ b/integration-tests/smoke/ocr2vrf_test.go
@@ -149,7 +149,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) {
}
func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) {
- testNetwork = networks.SelectedNetwork
+ testNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
evmConfig := eth.New(nil)
if !testNetwork.Simulated {
evmConfig = eth.New(ð.Props{
diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go
index 048f3124ad..c4b1fc7ab1 100644
--- a/integration-tests/testsetups/ocr.go
+++ b/integration-tests/testsetups/ocr.go
@@ -126,7 +126,7 @@ func NewOCRSoakTest(t *testing.T, forwarderFlow bool) (*OCRSoakTest, error) {
// DeployEnvironment deploys the test environment, starting all Chainlink nodes and other components for the test
func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) {
- network := networks.SelectedNetwork // Environment currently being used to soak test on
+ network := networks.MustGetSelectedNetworksFromEnv()[0] // Environment currently being used to soak test on
nsPre := "soak-ocr-"
if o.OperatorForwarderFlow {
nsPre = fmt.Sprintf("%sforwarder-", nsPre)
@@ -165,7 +165,7 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) {
// LoadEnvironment loads an existing test environment using the provided URLs
func (o *OCRSoakTest) LoadEnvironment(chainlinkURLs []string, chainURL, mockServerURL string) {
var (
- network = networks.SelectedNetwork
+ network = networks.MustGetSelectedNetworksFromEnv()[0]
err error
)
o.chainClient, err = blockchain.ConnectEVMClient(network, o.log)
@@ -185,7 +185,7 @@ func (o *OCRSoakTest) Environment() *environment.Environment {
func (o *OCRSoakTest) Setup() {
var (
err error
- network = networks.SelectedNetwork
+ network = networks.MustGetSelectedNetworksFromEnv()[0]
)
// Environment currently being used to soak test on
@@ -387,7 +387,7 @@ func (o *OCRSoakTest) LoadState() error {
o.startTime = testState.StartTime
o.startingBlockNum = testState.StartingBlockNum
- network := networks.SelectedNetwork
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
o.chainClient, err = blockchain.ConnectEVMClient(network, o.log)
if err != nil {
return err
From 5808e734cf024a5e8c5450e939e1f2d5b3cba546 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Fri, 27 Oct 2023 08:52:16 -0500
Subject: [PATCH 023/327] core: log a warning when deprecated P2P.V1 config is
set in TOML (#11073)
* core: log a warning when deprecated P2P.V1 config is set in TOML
* change default P2P from V1 to V2
* bump operator ui
---
.../evm/config/mocks/chain_scoped_config.go | 6 +-
core/cmd/shell_local.go | 5 +-
core/config/app_config.go | 2 +-
core/config/docs/core.toml | 7 +-
core/scripts/chaincli/handler/handler.go | 4 +-
.../common/vrf/docker/toml-config/base.toml | 1 -
core/scripts/ocr2vrf/util.go | 13 +-
core/services/chainlink/config.go | 44 +++
core/services/chainlink/config_general.go | 14 +-
core/services/chainlink/config_p2p_test.go | 7 +-
core/services/chainlink/config_test.go | 39 ++-
.../chainlink/mocks/general_config.go | 6 +-
.../testdata/config-empty-effective.toml | 4 +-
.../chainlink/testdata/config-full.toml | 4 +-
.../config-multi-chain-effective.toml | 4 +-
.../ocr2/plugins/mercury/helpers_test.go | 4 -
core/utils/config/validate.go | 14 +
.../testdata/config-empty-effective.toml | 4 +-
core/web/resolver/testdata/config-full.toml | 4 +-
.../config-multi-chain-effective.toml | 4 +-
docs/CHANGELOG.md | 10 +-
docs/CONFIG.md | 12 +-
integration-tests/benchmark/keeper_test.go | 1 -
.../chaos/automation_chaos_test.go | 1 -
integration-tests/config/config.go | 6 +-
integration-tests/performance/ocr_test.go | 4 +
.../reorg/automation_reorg_test.go | 6 +-
integration-tests/smoke/automation_test.go | 1 -
integration-tests/smoke/keeper_test.go | 2 +-
integration-tests/types/config/node/core.go | 11 +-
.../types/config/node/defaults/sample.toml | 1 -
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 +-
testdata/scripts/node/validate/invalid.txtar | 4 +-
testdata/scripts/node/validate/valid.txtar | 4 +-
testdata/scripts/node/validate/warnings.txtar | 279 ++++++++++++++++++
38 files changed, 463 insertions(+), 85 deletions(-)
create mode 100644 testdata/scripts/node/validate/warnings.txtar
diff --git a/core/chains/evm/config/mocks/chain_scoped_config.go b/core/chains/evm/config/mocks/chain_scoped_config.go
index 0854b82165..cb18282f49 100644
--- a/core/chains/evm/config/mocks/chain_scoped_config.go
+++ b/core/chains/evm/config/mocks/chain_scoped_config.go
@@ -252,9 +252,9 @@ func (_m *ChainScopedConfig) Log() coreconfig.Log {
return r0
}
-// LogConfiguration provides a mock function with given fields: log
-func (_m *ChainScopedConfig) LogConfiguration(log coreconfig.LogfFn) {
- _m.Called(log)
+// LogConfiguration provides a mock function with given fields: log, warn
+func (_m *ChainScopedConfig) LogConfiguration(log coreconfig.LogfFn, warn coreconfig.LogfFn) {
+ _m.Called(log, warn)
}
// Mercury provides a mock function with given fields:
diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go
index f578604db3..401375238d 100644
--- a/core/cmd/shell_local.go
+++ b/core/cmd/shell_local.go
@@ -290,7 +290,7 @@ func (s *Shell) runNode(c *cli.Context) error {
s.Config.SetPasswords(pwd, vrfpwd)
- s.Config.LogConfiguration(lggr.Debugf)
+ s.Config.LogConfiguration(lggr.Debugf, lggr.Warnf)
if err := s.Config.Validate(); err != nil {
return errors.Wrap(err, "config validation failed")
@@ -689,7 +689,8 @@ var errDBURLMissing = errors.New("You must set CL_DATABASE_URL env variable or p
// ConfigValidate validate the client configuration and pretty-prints results
func (s *Shell) ConfigFileValidate(_ *cli.Context) error {
- s.Config.LogConfiguration(func(f string, params ...any) { fmt.Printf(f, params...) })
+ fn := func(f string, params ...any) { fmt.Printf(f, params...) }
+ s.Config.LogConfiguration(fn, fn)
if err := s.configExitErr(s.Config.Validate); err != nil {
return err
}
diff --git a/core/config/app_config.go b/core/config/app_config.go
index ab8d955967..648939b871 100644
--- a/core/config/app_config.go
+++ b/core/config/app_config.go
@@ -28,7 +28,7 @@ type AppConfig interface {
Validate() error
ValidateDB() error
- LogConfiguration(log LogfFn)
+ LogConfiguration(log, warn LogfFn)
SetLogLevel(lvl zapcore.Level) error
SetLogSQL(logSQL bool)
SetPasswords(keystore, vrf *string)
diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml
index 18f5810adc..1ca4c656a7 100644
--- a/core/config/docs/core.toml
+++ b/core/config/docs/core.toml
@@ -359,6 +359,8 @@ TraceLogging = false # Default
# automatically fall back to V1. If V2 starts working again later, it will automatically be preferred again. This is useful
# for migrating networks without downtime. Note that the two networking stacks _must not_ be configured to bind to the same IP/port.
#
+# Note: P2P.V1 is deprecated will be removed in the future.
+#
# All nodes in the OCR network should share the same networking stack.
[P2P]
# IncomingMessageBufferSize is the per-remote number of incoming
@@ -377,9 +379,10 @@ PeerID = '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw' # Example
# TraceLogging enables trace level logging.
TraceLogging = false # Default
+# P2P.V1 is deprecated and will be removed in a future version.
[P2P.V1]
# Enabled enables P2P V1.
-Enabled = true # Default
+Enabled = false # Default
# AnnounceIP should be set as the externally reachable IP address of the Chainlink node.
AnnounceIP = '1.2.3.4' # Example
# AnnouncePort should be set as the externally reachable port of the Chainlink node.
@@ -423,7 +426,7 @@ PeerstoreWriteInterval = '5m' # Default
[P2P.V2]
# Enabled enables P2P V2.
# Note: V1.Enabled is true by default, so it must be set false in order to run V2 only.
-Enabled = false # Default
+Enabled = true # Default
# AnnounceAddresses is the addresses the peer will advertise on the network in `host:port` form as accepted by the TCP version of Go’s `net.Dial`.
# The addresses should be reachable by other nodes on the network. When attempting to connect to another node,
# a node will attempt to dial all of the other node’s AnnounceAddresses in round-robin fashion.
diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go
index c51792f9ad..f72e94605d 100644
--- a/core/scripts/chaincli/handler/handler.go
+++ b/core/scripts/chaincli/handler/handler.go
@@ -64,9 +64,7 @@ HTTPSPort = 0
LogPoller = true
[OCR2]
Enabled = true
-[P2P]
-[P2P.V2]
-Enabled = true
+
[Keeper]
TurnLookBack = 0
[[EVM]]
diff --git a/core/scripts/common/vrf/docker/toml-config/base.toml b/core/scripts/common/vrf/docker/toml-config/base.toml
index 0bb83beb94..39aab2e63a 100644
--- a/core/scripts/common/vrf/docker/toml-config/base.toml
+++ b/core/scripts/common/vrf/docker/toml-config/base.toml
@@ -26,6 +26,5 @@ HTTPSPort = 0
[P2P]
[P2P.V2]
-Enabled = true
AnnounceAddresses = ['0.0.0.0:6690']
ListenAddresses = ['0.0.0.0:6690']
diff --git a/core/scripts/ocr2vrf/util.go b/core/scripts/ocr2vrf/util.go
index f8d104a5f3..a2ff55524d 100644
--- a/core/scripts/ocr2vrf/util.go
+++ b/core/scripts/ocr2vrf/util.go
@@ -14,16 +14,17 @@ import (
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
+ "github.com/urfave/cli"
+ "go.dedis.ch/kyber/v3"
+ "go.dedis.ch/kyber/v3/group/edwards25519"
+ "go.dedis.ch/kyber/v3/pairing"
+
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/ocr2vrf/altbn_128"
"github.com/smartcontractkit/ocr2vrf/dkg"
"github.com/smartcontractkit/ocr2vrf/ocr2vrf"
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
- "github.com/urfave/cli"
- "go.dedis.ch/kyber/v3"
- "go.dedis.ch/kyber/v3/group/edwards25519"
- "go.dedis.ch/kyber/v3/pairing"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder"
@@ -43,11 +44,7 @@ var (
g1 = suite.G1()
g2 = suite.G2()
tomlConfigTemplate = `
- [P2P.V1]
- Enabled = false
-
[P2P.V2]
- Enabled = true
ListenAddresses = ["127.0.0.1:8000"]
[Feature]
diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go
index 62be789f85..26e2d539ba 100644
--- a/core/services/chainlink/config.go
+++ b/core/services/chainlink/config.go
@@ -52,6 +52,50 @@ func (c *Config) TOMLString() (string, error) {
return string(b), nil
}
+// deprecationWarnings returns an error if the Config contains deprecated fields.
+// This is typically used before defaults have been applied, with input from the user.
+func (c *Config) deprecationWarnings() (err error) {
+ if c.P2P.V1 != (toml.P2PV1{}) {
+ err = multierr.Append(err, config.ErrDeprecated{Name: "P2P.V1"})
+ var err2 error
+ if c.P2P.V1.AnnounceIP != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "AnnounceIP"})
+ }
+ if c.P2P.V1.AnnouncePort != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "AnnouncePort"})
+ }
+ if c.P2P.V1.BootstrapCheckInterval != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "BootstrapCheckInterval"})
+ }
+ if c.P2P.V1.DefaultBootstrapPeers != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "DefaultBootstrapPeers"})
+ }
+ if c.P2P.V1.DHTAnnouncementCounterUserPrefix != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "DHTAnnouncementCounterUserPrefix"})
+ }
+ if c.P2P.V1.DHTLookupInterval != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "DHTLookupInterval"})
+ }
+ if c.P2P.V1.ListenIP != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "ListenIP"})
+ }
+ if c.P2P.V1.ListenPort != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "ListenPort"})
+ }
+ if c.P2P.V1.NewStreamTimeout != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "NewStreamTimeout"})
+ }
+ if c.P2P.V1.PeerstoreWriteInterval != nil {
+ err2 = multierr.Append(err2, config.ErrDeprecated{Name: "PeerstoreWriteInterval"})
+ }
+ err2 = config.NamedMultiErrorList(err2, "P2P.V1")
+ err = multierr.Append(err, err2)
+ }
+ return
+}
+
+// Validate returns an error if the Config is not valid for use, as-is.
+// This is typically used after defaults have been applied.
func (c *Config) Validate() error {
if err := config.Validate(c); err != nil {
return fmt.Errorf("invalid configuration: %w", err)
diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go
index 8e3dc100a4..6243146e91 100644
--- a/core/services/chainlink/config_general.go
+++ b/core/services/chainlink/config_general.go
@@ -35,11 +35,13 @@ import (
type generalConfig struct {
inputTOML string // user input, normalized via de/re-serialization
effectiveTOML string // with default values included
- secretsTOML string // with env overdies includes, redacted
+ secretsTOML string // with env overrides includes, redacted
c *Config // all fields non-nil (unless the legacy method signature return a pointer)
secrets *Secrets
+ warning error // warnings about inputTOML, e.g. deprecated fields
+
logLevelDefault zapcore.Level
appIDOnce sync.Once
@@ -123,7 +125,7 @@ func (o *GeneralConfigOpts) parseSecrets(secrets string) error {
return nil
}
-// New returns a coreconfig.GeneralConfig for the given options.
+// New returns a GeneralConfig for the given options.
func (o GeneralConfigOpts) New() (GeneralConfig, error) {
err := o.parse()
if err != nil {
@@ -135,6 +137,8 @@ func (o GeneralConfigOpts) New() (GeneralConfig, error) {
return nil, err
}
+ _, warning := utils.MultiErrorList(o.Config.deprecationWarnings())
+
o.Config.setDefaults()
if !o.SkipEnv {
err = o.Secrets.setEnv()
@@ -163,6 +167,7 @@ func (o GeneralConfigOpts) New() (GeneralConfig, error) {
secretsTOML: secrets,
c: &o.Config,
secrets: &o.Secrets,
+ warning: warning,
}
if lvl := o.Config.Log.Level; lvl != nil {
cfg.logLevelDefault = zapcore.Level(*lvl)
@@ -253,10 +258,13 @@ func validateEnv() (err error) {
return
}
-func (g *generalConfig) LogConfiguration(log coreconfig.LogfFn) {
+func (g *generalConfig) LogConfiguration(log, warn coreconfig.LogfFn) {
log("# Secrets:\n%s\n", g.secretsTOML)
log("# Input Configuration:\n%s\n", g.inputTOML)
log("# Effective Configuration, with defaults applied:\n%s\n", g.effectiveTOML)
+ if g.warning != nil {
+ warn("# Configuration warning:\n%s\n", g.warning)
+ }
}
// ConfigTOML implements chainlink.ConfigV2
diff --git a/core/services/chainlink/config_p2p_test.go b/core/services/chainlink/config_p2p_test.go
index d6adfe7051..21ce8f17e4 100644
--- a/core/services/chainlink/config_p2p_test.go
+++ b/core/services/chainlink/config_p2p_test.go
@@ -4,9 +4,10 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/libocr/commontypes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/libocr/commontypes"
)
func TestP2PConfig(t *testing.T) {
@@ -23,7 +24,7 @@ func TestP2PConfig(t *testing.T) {
assert.True(t, p2p.TraceLogging())
v1 := p2p.V1()
- assert.False(t, v1.Enabled())
+ assert.True(t, v1.Enabled())
assert.Equal(t, "1.2.3.4", v1.AnnounceIP().String())
assert.Equal(t, uint16(1234), v1.AnnouncePort())
assert.Equal(t, time.Minute, v1.BootstrapCheckInterval())
@@ -38,7 +39,7 @@ func TestP2PConfig(t *testing.T) {
assert.Equal(t, time.Minute, v1.PeerstoreWriteInterval())
v2 := p2p.V2()
- assert.True(t, v2.Enabled())
+ assert.False(t, v2.Enabled())
assert.Equal(t, []string{"a", "b", "c"}, v2.AnnounceAddresses())
assert.ElementsMatch(
t,
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index d811dd8209..597dab6ba1 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -389,7 +389,7 @@ func TestConfig_Marshal(t *testing.T) {
PeerID: mustPeerID("12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw"),
TraceLogging: ptr(true),
V1: toml.P2PV1{
- Enabled: ptr(false),
+ Enabled: ptr(true),
AnnounceIP: mustIP("1.2.3.4"),
AnnouncePort: ptr[uint16](1234),
BootstrapCheckInterval: models.MustNewDuration(time.Minute),
@@ -402,7 +402,7 @@ func TestConfig_Marshal(t *testing.T) {
PeerstoreWriteInterval: models.MustNewDuration(time.Minute),
},
V2: toml.P2PV2{
- Enabled: ptr(true),
+ Enabled: ptr(false),
AnnounceAddresses: &[]string{"a", "b", "c"},
DefaultBootstrappers: &[]ocrcommontypes.BootstrapperLocator{
{PeerID: "12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw", Addrs: []string{"foo:42", "bar:10"}},
@@ -820,7 +820,7 @@ PeerID = '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw'
TraceLogging = true
[P2P.V1]
-Enabled = false
+Enabled = true
AnnounceIP = '1.2.3.4'
AnnouncePort = 1234
BootstrapCheckInterval = '1m0s'
@@ -833,7 +833,7 @@ NewStreamTimeout = '1s'
PeerstoreWriteInterval = '1m0s'
[P2P.V2]
-Enabled = true
+Enabled = false
AnnounceAddresses = ['a', 'b', 'c']
DefaultBootstrappers = ['12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@foo:42/bar:10', '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@test:99']
DeltaDial = '1m0s'
@@ -1248,6 +1248,21 @@ func Test_generalConfig_LogConfiguration(t *testing.T) {
secrets = "# Secrets:\n"
input = "# Input Configuration:\n"
effective = "# Effective Configuration, with defaults applied:\n"
+ warning = "# Configuration warning:\n"
+
+ deprecated = `2 errors:
+ - P2P.V1: is deprecated and will be removed in a future version
+ - P2P.V1: 10 errors:
+ - AnnounceIP: is deprecated and will be removed in a future version
+ - AnnouncePort: is deprecated and will be removed in a future version
+ - BootstrapCheckInterval: is deprecated and will be removed in a future version
+ - DefaultBootstrapPeers: is deprecated and will be removed in a future version
+ - DHTAnnouncementCounterUserPrefix: is deprecated and will be removed in a future version
+ - DHTLookupInterval: is deprecated and will be removed in a future version
+ - ListenIP: is deprecated and will be removed in a future version
+ - ListenPort: is deprecated and will be removed in a future version
+ - NewStreamTimeout: is deprecated and will be removed in a future version
+ - PeerstoreWriteInterval: is deprecated and will be removed in a future version`
)
tests := []struct {
name string
@@ -1257,10 +1272,11 @@ func Test_generalConfig_LogConfiguration(t *testing.T) {
wantConfig string
wantEffective string
wantSecrets string
+ wantWarning string
}{
{name: "empty", wantEffective: emptyEffectiveTOML, wantSecrets: emptyEffectiveSecretsTOML},
{name: "full", inputSecrets: secretsFullTOML, inputConfig: fullTOML,
- wantConfig: fullTOML, wantEffective: fullTOML, wantSecrets: secretsFullRedactedTOML},
+ wantConfig: fullTOML, wantEffective: fullTOML, wantSecrets: secretsFullRedactedTOML, wantWarning: deprecated},
{name: "multi-chain", inputSecrets: secretsMultiTOML, inputConfig: multiChainTOML,
wantConfig: multiChainTOML, wantEffective: multiChainEffectiveTOML, wantSecrets: secretsMultiRedactedTOML},
}
@@ -1274,10 +1290,11 @@ func Test_generalConfig_LogConfiguration(t *testing.T) {
}
c, err := opts.New()
require.NoError(t, err)
- c.LogConfiguration(lggr.Infof)
+ c.LogConfiguration(lggr.Infof, lggr.Warnf)
inputLogs := observed.FilterMessageSnippet(secrets).All()
if assert.Len(t, inputLogs, 1) {
+ assert.Equal(t, zapcore.InfoLevel, inputLogs[0].Level)
got := strings.TrimPrefix(inputLogs[0].Message, secrets)
got = strings.TrimSuffix(got, "\n")
assert.Equal(t, tt.wantSecrets, got)
@@ -1285,6 +1302,7 @@ func Test_generalConfig_LogConfiguration(t *testing.T) {
inputLogs = observed.FilterMessageSnippet(input).All()
if assert.Len(t, inputLogs, 1) {
+ assert.Equal(t, zapcore.InfoLevel, inputLogs[0].Level)
got := strings.TrimPrefix(inputLogs[0].Message, input)
got = strings.TrimSuffix(got, "\n")
assert.Equal(t, tt.wantConfig, got)
@@ -1292,10 +1310,19 @@ func Test_generalConfig_LogConfiguration(t *testing.T) {
inputLogs = observed.FilterMessageSnippet(effective).All()
if assert.Len(t, inputLogs, 1) {
+ assert.Equal(t, zapcore.InfoLevel, inputLogs[0].Level)
got := strings.TrimPrefix(inputLogs[0].Message, effective)
got = strings.TrimSuffix(got, "\n")
assert.Equal(t, tt.wantEffective, got)
}
+
+ inputLogs = observed.FilterMessageSnippet(warning).All()
+ if tt.wantWarning != "" && assert.Len(t, inputLogs, 1) {
+ assert.Equal(t, zapcore.WarnLevel, inputLogs[0].Level)
+ got := strings.TrimPrefix(inputLogs[0].Message, warning)
+ got = strings.TrimSuffix(got, "\n")
+ assert.Equal(t, tt.wantWarning, got)
+ }
})
}
}
diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go
index 8098b9634f..0bc51ea431 100644
--- a/core/services/chainlink/mocks/general_config.go
+++ b/core/services/chainlink/mocks/general_config.go
@@ -298,9 +298,9 @@ func (_m *GeneralConfig) Log() config.Log {
return r0
}
-// LogConfiguration provides a mock function with given fields: log
-func (_m *GeneralConfig) LogConfiguration(log config.LogfFn) {
- _m.Called(log)
+// LogConfiguration provides a mock function with given fields: log, warn
+func (_m *GeneralConfig) LogConfiguration(log config.LogfFn, warn config.LogfFn) {
+ _m.Called(log, warn)
}
// Mercury provides a mock function with given fields:
diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml
index e746d66777..48d432138a 100644
--- a/core/services/chainlink/testdata/config-empty-effective.toml
+++ b/core/services/chainlink/testdata/config-empty-effective.toml
@@ -142,7 +142,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -155,7 +155,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml
index 3bd422f892..1534a411dc 100644
--- a/core/services/chainlink/testdata/config-full.toml
+++ b/core/services/chainlink/testdata/config-full.toml
@@ -148,7 +148,7 @@ PeerID = '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw'
TraceLogging = true
[P2P.V1]
-Enabled = false
+Enabled = true
AnnounceIP = '1.2.3.4'
AnnouncePort = 1234
BootstrapCheckInterval = '1m0s'
@@ -161,7 +161,7 @@ NewStreamTimeout = '1s'
PeerstoreWriteInterval = '1m0s'
[P2P.V2]
-Enabled = true
+Enabled = false
AnnounceAddresses = ['a', 'b', 'c']
DefaultBootstrappers = ['12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@foo:42/bar:10', '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@test:99']
DeltaDial = '1m0s'
diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml
index 89b034169c..1dcbfe3a83 100644
--- a/core/services/chainlink/testdata/config-multi-chain-effective.toml
+++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml
@@ -142,7 +142,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -155,7 +155,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go
index ce4e089516..60904b5813 100644
--- a/core/services/ocr2/plugins/mercury/helpers_test.go
+++ b/core/services/ocr2/plugins/mercury/helpers_test.go
@@ -190,10 +190,6 @@ func setupNode(
c.P2P.PeerID = ptr(p2pKey.PeerID())
c.P2P.TraceLogging = ptr(true)
- // [P2P.V1]
- // Enabled = false
- c.P2P.V1.Enabled = ptr(false)
-
// [P2P.V2]
// Enabled = true
// AnnounceAddresses = ['$EXT_IP:17775']
diff --git a/core/utils/config/validate.go b/core/utils/config/validate.go
index 3ed0ffbabb..32cb94b520 100644
--- a/core/utils/config/validate.go
+++ b/core/utils/config/validate.go
@@ -6,6 +6,7 @@ import (
"strconv"
"strings"
+ "github.com/Masterminds/semver/v3"
"go.uber.org/multierr"
"github.com/smartcontractkit/chainlink-relay/pkg/config"
@@ -146,3 +147,16 @@ type ErrOverride struct {
func (e ErrOverride) Error() string {
return fmt.Sprintf("%s: overrides (duplicate keys or list elements) are not allowed for multiple secrets files", e.Name)
}
+
+type ErrDeprecated struct {
+ Name string
+ Version semver.Version
+}
+
+func (e ErrDeprecated) Error() string {
+ when := "a future version"
+ if e.Version != (semver.Version{}) {
+ when = fmt.Sprintf("version %s", e.Version)
+ }
+ return fmt.Sprintf("%s: is deprecated and will be removed in %s", e.Name, when)
+}
diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml
index e746d66777..48d432138a 100644
--- a/core/web/resolver/testdata/config-empty-effective.toml
+++ b/core/web/resolver/testdata/config-empty-effective.toml
@@ -142,7 +142,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -155,7 +155,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml
index 5a815b2e01..4b53396b94 100644
--- a/core/web/resolver/testdata/config-full.toml
+++ b/core/web/resolver/testdata/config-full.toml
@@ -148,7 +148,7 @@ PeerID = '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw'
TraceLogging = true
[P2P.V1]
-Enabled = false
+Enabled = true
AnnounceIP = '1.2.3.4'
AnnouncePort = 1234
BootstrapCheckInterval = '1m0s'
@@ -161,7 +161,7 @@ NewStreamTimeout = '1s'
PeerstoreWriteInterval = '1m0s'
[P2P.V2]
-Enabled = true
+Enabled = false
AnnounceAddresses = ['a', 'b', 'c']
DefaultBootstrappers = ['12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@foo:42/bar:10', '12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@test:99']
DeltaDial = '1m0s'
diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml
index 89b034169c..1dcbfe3a83 100644
--- a/core/web/resolver/testdata/config-multi-chain-effective.toml
+++ b/core/web/resolver/testdata/config-multi-chain-effective.toml
@@ -142,7 +142,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -155,7 +155,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 44d018769e..daeddf2ce6 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -29,9 +29,15 @@ These will eventually replace `TelemetryIngress.URL` and `TelemetryIngress.Serve
- LogPoller will now use finality tags to dynamically determine finality on evm chains if `UseFinalityTags=true`, rather than the fixed `FinalityDepth` specified in toml config
-### Upcoming Required Configuration Change
+### Changed
+
+- `P2P.V1` is now disabled (`Enabled = false`) by default. It must be explicitly enabled with `true` to be used. However, it is deprecated and will be removed in the future.
+- `P2P.V2` is now enabled (`Enabled = true`) by default.
-- Starting in 2.9.0, chainlink nodes will no longer allow `TelemetryIngress.URL` and `TelemetryIngress.ServerPubKey`. Any TOML configuration that sets this fields will prevent the node from booting. These fields will be replaced by `[[TelemetryIngress.Endpoints]]`
+### Upcoming Required Configuration Changes
+Starting in `v2.9.0`:
+- `TelemetryIngress.URL` and `TelemetryIngress.ServerPubKey` will no longer be allowed. Any TOML configuration that sets this fields will prevent the node from booting. These fields will be replaced by `[[TelemetryIngress.Endpoints]]`
+- `P2P.V1` will no longer be supported and must not be set in TOML configuration in order to boot. Use `P2P.V2` instead. If you are using both, `V1` can simply be removed.
### Removed
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 1fc7d9b632..da986e0500 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -981,6 +981,8 @@ If both are configured, then for each link with another peer, V2 networking will
automatically fall back to V1. If V2 starts working again later, it will automatically be preferred again. This is useful
for migrating networks without downtime. Note that the two networking stacks _must not_ be configured to bind to the same IP/port.
+Note: P2P.V1 is deprecated will be removed in the future.
+
All nodes in the OCR network should share the same networking stack.
### IncomingMessageBufferSize
@@ -1017,7 +1019,7 @@ TraceLogging enables trace level logging.
## P2P.V1
```toml
[P2P.V1]
-Enabled = true # Default
+Enabled = false # Default
AnnounceIP = '1.2.3.4' # Example
AnnouncePort = 1337 # Example
BootstrapCheckInterval = '20s' # Default
@@ -1029,11 +1031,11 @@ ListenPort = 1337 # Example
NewStreamTimeout = '10s' # Default
PeerstoreWriteInterval = '5m' # Default
```
-
+P2P.V1 is deprecated and will be removed in a future version.
### Enabled
```toml
-Enabled = true # Default
+Enabled = false # Default
```
Enabled enables P2P V1.
@@ -1119,7 +1121,7 @@ PeerstoreWriteInterval controls how often the peerstore for the OCR V1 networkin
## P2P.V2
```toml
[P2P.V2]
-Enabled = false # Default
+Enabled = true # Default
AnnounceAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example
DefaultBootstrappers = ['12D3KooWMHMRLQkgPbFSYHwD3NBuwtS1AmxhvKVUrcfyaGDASR4U@1.2.3.4:9999', '12D3KooWM55u5Swtpw9r8aFLQHEtw7HR4t44GdNs654ej5gRs2Dh@example.com:1234'] # Example
DeltaDial = '15s' # Default
@@ -1130,7 +1132,7 @@ ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example
### Enabled
```toml
-Enabled = false # Default
+Enabled = true # Default
```
Enabled enables P2P V2.
Note: V1.Enabled is true by default, so it must be set false in order to run V2 only.
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index ed26caf470..7f484fc69f 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -37,7 +37,6 @@ Enabled = true
[P2P]
[P2P.V2]
-Enabled = true
AnnounceAddresses = ["0.0.0.0:6690"]
ListenAddresses = ["0.0.0.0:6690"]
[Keeper]
diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go
index 62f85d3256..8697044aa7 100644
--- a/integration-tests/chaos/automation_chaos_test.go
+++ b/integration-tests/chaos/automation_chaos_test.go
@@ -37,7 +37,6 @@ Enabled = true
[P2P]
[P2P.V2]
-Enabled = true
AnnounceAddresses = ["0.0.0.0:6690"]
ListenAddresses = ["0.0.0.0:6690"]`
diff --git a/integration-tests/config/config.go b/integration-tests/config/config.go
index cd3f5983a2..44c108b0d7 100644
--- a/integration-tests/config/config.go
+++ b/integration-tests/config/config.go
@@ -4,6 +4,10 @@ var (
BaseOCRP2PV1Config = `[OCR]
Enabled = true
+[P2P]
+[P2P.V2]
+Enabled = false
+
[P2P]
[P2P.V1]
Enabled = true
@@ -18,7 +22,6 @@ Enabled = true
[P2P]
[P2P.V2]
-Enabled = true
AnnounceAddresses = ["0.0.0.0:6690"]
ListenAddresses = ["0.0.0.0:6690"]`
@@ -67,7 +70,6 @@ CaptureEATelemetry = true
[P2P]
[P2P.V2]
-Enabled = true
ListenAddresses = ['0.0.0.0:6690']`
TelemetryIngressConfig = `[TelemetryIngress]
diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go
index 1db030f1cc..4d875022ed 100644
--- a/integration-tests/performance/ocr_test.go
+++ b/integration-tests/performance/ocr_test.go
@@ -102,6 +102,10 @@ func setupOCRTest(t *testing.T) (testEnvironment *environment.Environment, testN
baseTOML := `[OCR]
Enabled = true
+[P2P]
+[P2P.V2]
+Enabled = false
+
[P2P]
[P2P.V1]
Enabled = true
diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go
index a1260cc37a..608144eafd 100644
--- a/integration-tests/reorg/automation_reorg_test.go
+++ b/integration-tests/reorg/automation_reorg_test.go
@@ -9,6 +9,9 @@ import (
"time"
"github.com/onsi/gomega"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/zap/zapcore"
+
"github.com/smartcontractkit/chainlink-env/environment"
"github.com/smartcontractkit/chainlink-env/pkg/cdk8s/blockscout"
"github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
@@ -17,8 +20,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
- "github.com/stretchr/testify/require"
- "go.uber.org/zap/zapcore"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
@@ -35,7 +36,6 @@ Enabled = true
[P2P]
[P2P.V2]
-Enabled = true
AnnounceAddresses = ["0.0.0.0:6690"]
ListenAddresses = ["0.0.0.0:6690"]`
networkTOML = `Enabled = true
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 3addac1b9d..17373e6a95 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -1038,7 +1038,6 @@ func setupAutomationTestDocker(
clNodeConfig.Keeper.TurnLookBack = it_utils.Ptr[int64](int64(0))
clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval
clNodeConfig.Keeper.Registry.PerformGasOverhead = it_utils.Ptr[uint32](uint32(150000))
- clNodeConfig.P2P.V2.Enabled = it_utils.Ptr[bool](true)
clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"}
clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"}
diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go
index 21dbeb8753..d42944fd55 100644
--- a/integration-tests/smoke/keeper_test.go
+++ b/integration-tests/smoke/keeper_test.go
@@ -1098,7 +1098,7 @@ func setupKeeperTest(t *testing.T) (
contracts.LinkToken,
*test_env.CLClusterTestEnv,
) {
- clNodeConfig := node.NewConfig(node.NewBaseConfig())
+ clNodeConfig := node.NewConfig(node.NewBaseConfig(), node.WithP2Pv1())
turnLookBack := int64(0)
syncInterval := models.MustMakeDuration(5 * time.Second)
performGasOverhead := uint32(150000)
diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go
index 966e270e51..37047cdb66 100644
--- a/integration-tests/types/config/node/core.go
+++ b/integration-tests/types/config/node/core.go
@@ -115,13 +115,14 @@ func WithP2Pv1() NodeConfigOpt {
ListenIP: utils2.MustIP("0.0.0.0"),
ListenPort: utils2.Ptr[uint16](6690),
}
+ // disabled default
+ c.P2P.V2 = toml.P2PV2{Enabled: utils2.Ptr(false)}
}
}
func WithP2Pv2() NodeConfigOpt {
return func(c *chainlink.Config) {
c.P2P.V2 = toml.P2PV2{
- Enabled: utils2.Ptr(true),
ListenAddresses: &[]string{"0.0.0.0:6690"},
}
}
@@ -130,14 +131,14 @@ func WithP2Pv2() NodeConfigOpt {
func WithTracing() NodeConfigOpt {
return func(c *chainlink.Config) {
c.Tracing = toml.Tracing{
- Enabled: utils2.Ptr(true),
+ Enabled: utils2.Ptr(true),
CollectorTarget: utils2.Ptr("otel-collector:4317"),
// ksortable unique id
- NodeID: utils2.Ptr(ksuid.New().String()),
- Attributes: map[string]string{
+ NodeID: utils2.Ptr(ksuid.New().String()),
+ Attributes: map[string]string{
"env": "smoke",
},
- SamplingRatio: utils2.Ptr(1.0),
+ SamplingRatio: utils2.Ptr(1.0),
}
}
}
diff --git a/integration-tests/types/config/node/defaults/sample.toml b/integration-tests/types/config/node/defaults/sample.toml
index 3663998003..b0e1bc2a07 100644
--- a/integration-tests/types/config/node/defaults/sample.toml
+++ b/integration-tests/types/config/node/defaults/sample.toml
@@ -15,7 +15,6 @@ DefaultTransactionQueueDepth = 0
[P2P]
[P2P.V2]
-Enabled = true
ListenAddresses = ['0.0.0.0:6690']
AnnounceAddresses = ['0.0.0.0:6690']
DeltaDial = '500ms'
diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar
index 06a623c9ca..189476bfa8 100644
--- a/testdata/scripts/node/validate/default.txtar
+++ b/testdata/scripts/node/validate/default.txtar
@@ -154,7 +154,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -167,7 +167,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
index 1c0956b10d..593aa0b21d 100644
--- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
@@ -198,7 +198,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -211,7 +211,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
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 19e180e0cf..7b8aa5e383 100644
--- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar
@@ -198,7 +198,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -211,7 +211,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar
index 062a21b196..ef6548619e 100644
--- a/testdata/scripts/node/validate/disk-based-logging.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging.txtar
@@ -198,7 +198,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -211,7 +211,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar
index 0fa1647381..87b877bc88 100644
--- a/testdata/scripts/node/validate/invalid.txtar
+++ b/testdata/scripts/node/validate/invalid.txtar
@@ -188,7 +188,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -201,7 +201,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar
index 002c249fb7..c607da1064 100644
--- a/testdata/scripts/node/validate/valid.txtar
+++ b/testdata/scripts/node/validate/valid.txtar
@@ -195,7 +195,7 @@ PeerID = ''
TraceLogging = false
[P2P.V1]
-Enabled = true
+Enabled = false
AnnounceIP = ''
AnnouncePort = 0
BootstrapCheckInterval = '20s'
@@ -208,7 +208,7 @@ NewStreamTimeout = '10s'
PeerstoreWriteInterval = '5m0s'
[P2P.V2]
-Enabled = false
+Enabled = true
AnnounceAddresses = []
DefaultBootstrappers = []
DeltaDial = '15s'
diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar
new file mode 100644
index 0000000000..ee7926f8f5
--- /dev/null
+++ b/testdata/scripts/node/validate/warnings.txtar
@@ -0,0 +1,279 @@
+exec chainlink node -c config.toml -s secrets.toml validate
+cmp stdout out.txt
+
+-- config.toml --
+[P2P.V1]
+Enabled = true
+AnnounceIP = ''
+AnnouncePort = 0
+BootstrapCheckInterval = '20s'
+DefaultBootstrapPeers = []
+DHTAnnouncementCounterUserPrefix = 0
+DHTLookupInterval = 10
+ListenIP = '0.0.0.0'
+ListenPort = 0
+NewStreamTimeout = '10s'
+PeerstoreWriteInterval = '5m0s'
+
+-- secrets.toml --
+[Database]
+URL = 'postgresql://user:pass1234567890abcd@localhost:5432/dbname?sslmode=disable'
+
+[Password]
+Keystore = 'keystore_pass'
+
+-- out.txt --
+# Secrets:
+[Database]
+URL = 'xxxxx'
+AllowSimplePasswords = false
+
+[Password]
+Keystore = 'xxxxx'
+
+# Input Configuration:
+[P2P]
+[P2P.V1]
+Enabled = true
+AnnounceIP = ''
+AnnouncePort = 0
+BootstrapCheckInterval = '20s'
+DefaultBootstrapPeers = []
+DHTAnnouncementCounterUserPrefix = 0
+DHTLookupInterval = 10
+ListenIP = '0.0.0.0'
+ListenPort = 0
+NewStreamTimeout = '10s'
+PeerstoreWriteInterval = '5m0s'
+
+# Effective Configuration, with defaults applied:
+InsecureFastScrypt = false
+RootDir = '~/.chainlink'
+ShutdownGracePeriod = '5s'
+
+[Feature]
+FeedsManager = true
+LogPoller = false
+UICSAKeys = false
+
+[Database]
+DefaultIdleInTxSessionTimeout = '1h0m0s'
+DefaultLockTimeout = '15s'
+DefaultQueryTimeout = '10s'
+LogQueries = false
+MaxIdleConns = 10
+MaxOpenConns = 20
+MigrateOnStartup = true
+
+[Database.Backup]
+Dir = ''
+Frequency = '1h0m0s'
+Mode = 'none'
+OnVersionUpgrade = true
+
+[Database.Listener]
+MaxReconnectDuration = '10m0s'
+MinReconnectInterval = '1m0s'
+FallbackPollInterval = '30s'
+
+[Database.Lock]
+Enabled = true
+LeaseDuration = '10s'
+LeaseRefreshInterval = '1s'
+
+[TelemetryIngress]
+UniConn = true
+Logging = false
+BufferSize = 100
+MaxBatchSize = 50
+SendInterval = '500ms'
+SendTimeout = '10s'
+UseBatchSend = true
+URL = ''
+ServerPubKey = ''
+
+[AuditLogger]
+Enabled = false
+ForwardToUrl = ''
+JsonWrapperKey = ''
+Headers = []
+
+[Log]
+Level = 'info'
+JSONConsole = false
+UnixTS = false
+
+[Log.File]
+Dir = ''
+MaxSize = '5.12gb'
+MaxAgeDays = 0
+MaxBackups = 1
+
+[WebServer]
+AllowOrigins = 'http://localhost:3000,http://localhost:6688'
+BridgeResponseURL = ''
+BridgeCacheTTL = '0s'
+HTTPWriteTimeout = '10s'
+HTTPPort = 6688
+SecureCookies = true
+SessionTimeout = '15m0s'
+SessionReaperExpiration = '240h0m0s'
+HTTPMaxSize = '32.77kb'
+StartTimeout = '15s'
+ListenIP = '0.0.0.0'
+
+[WebServer.MFA]
+RPID = ''
+RPOrigin = ''
+
+[WebServer.RateLimit]
+Authenticated = 1000
+AuthenticatedPeriod = '1m0s'
+Unauthenticated = 5
+UnauthenticatedPeriod = '20s'
+
+[WebServer.TLS]
+CertPath = ''
+ForceRedirect = false
+Host = ''
+HTTPSPort = 6689
+KeyPath = ''
+ListenIP = '0.0.0.0'
+
+[JobPipeline]
+ExternalInitiatorsEnabled = false
+MaxRunDuration = '10m0s'
+MaxSuccessfulRuns = 10000
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '24h0m0s'
+ResultWriteQueueDepth = 100
+
+[JobPipeline.HTTPRequest]
+DefaultTimeout = '15s'
+MaxSize = '32.77kb'
+
+[FluxMonitor]
+DefaultTransactionQueueDepth = 1
+SimulateTransactions = false
+
+[OCR2]
+Enabled = false
+ContractConfirmations = 3
+BlockchainTimeout = '20s'
+ContractPollInterval = '1m0s'
+ContractSubscribeInterval = '2m0s'
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
+CaptureEATelemetry = false
+CaptureAutomationCustomTelemetry = false
+DefaultTransactionQueueDepth = 1
+SimulateTransactions = false
+TraceLogging = false
+
+[OCR]
+Enabled = false
+ObservationTimeout = '5s'
+BlockchainTimeout = '20s'
+ContractPollInterval = '1m0s'
+ContractSubscribeInterval = '2m0s'
+DefaultTransactionQueueDepth = 1
+KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
+SimulateTransactions = false
+TransmitterAddress = ''
+CaptureEATelemetry = false
+TraceLogging = false
+
+[P2P]
+IncomingMessageBufferSize = 10
+OutgoingMessageBufferSize = 10
+PeerID = ''
+TraceLogging = false
+
+[P2P.V1]
+Enabled = true
+AnnounceIP = ''
+AnnouncePort = 0
+BootstrapCheckInterval = '20s'
+DefaultBootstrapPeers = []
+DHTAnnouncementCounterUserPrefix = 0
+DHTLookupInterval = 10
+ListenIP = '0.0.0.0'
+ListenPort = 0
+NewStreamTimeout = '10s'
+PeerstoreWriteInterval = '5m0s'
+
+[P2P.V2]
+Enabled = true
+AnnounceAddresses = []
+DefaultBootstrappers = []
+DeltaDial = '15s'
+DeltaReconcile = '1m0s'
+ListenAddresses = []
+
+[Keeper]
+DefaultTransactionQueueDepth = 1
+GasPriceBufferPercent = 20
+GasTipCapBufferPercent = 20
+BaseFeeBufferPercent = 20
+MaxGracePeriod = 100
+TurnLookBack = 1000
+
+[Keeper.Registry]
+CheckGasOverhead = 200000
+PerformGasOverhead = 300000
+MaxPerformDataSize = 5000
+SyncInterval = '30m0s'
+SyncUpkeepQueueSize = 10
+
+[AutoPprof]
+Enabled = false
+ProfileRoot = ''
+PollInterval = '10s'
+GatherDuration = '10s'
+GatherTraceDuration = '5s'
+MaxProfileSize = '100.00mb'
+CPUProfileRate = 1
+MemProfileRate = 1
+BlockProfileRate = 1
+MutexProfileFraction = 1
+MemThreshold = '4.00gb'
+GoroutineThreshold = 5000
+
+[Pyroscope]
+ServerAddress = ''
+Environment = 'mainnet'
+
+[Sentry]
+Debug = false
+DSN = ''
+Environment = ''
+Release = ''
+
+[Insecure]
+DevWebServer = false
+OCRDevelopmentMode = false
+InfiniteDepthQueries = false
+DisableRateLimiting = false
+
+[Tracing]
+Enabled = false
+CollectorTarget = ''
+NodeID = ''
+SamplingRatio = 0.0
+
+# Configuration warning:
+2 errors:
+ - P2P.V1: is deprecated and will be removed in a future version
+ - P2P.V1: 10 errors:
+ - AnnounceIP: is deprecated and will be removed in a future version
+ - AnnouncePort: is deprecated and will be removed in a future version
+ - BootstrapCheckInterval: is deprecated and will be removed in a future version
+ - DefaultBootstrapPeers: is deprecated and will be removed in a future version
+ - DHTAnnouncementCounterUserPrefix: is deprecated and will be removed in a future version
+ - DHTLookupInterval: is deprecated and will be removed in a future version
+ - ListenIP: is deprecated and will be removed in a future version
+ - ListenPort: is deprecated and will be removed in a future version
+ - NewStreamTimeout: is deprecated and will be removed in a future version
+ - PeerstoreWriteInterval: is deprecated and will be removed in a future version
+Valid configuration.
From 7206a62a49f098c816172a1d4c1f51af04f24e15 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Fri, 27 Oct 2023 09:32:43 -0500
Subject: [PATCH 024/327] tools/docker: use longer password (#11098)
---
tools/docker/.env | 2 +-
tools/docker/dev-secrets.toml | 4 ----
tools/docker/develop.Dockerfile | 2 +-
tools/docker/docker-compose.yaml | 8 ++------
4 files changed, 4 insertions(+), 12 deletions(-)
delete mode 100644 tools/docker/dev-secrets.toml
diff --git a/tools/docker/.env b/tools/docker/.env
index 32de93edb4..05f4314ff2 100644
--- a/tools/docker/.env
+++ b/tools/docker/.env
@@ -4,7 +4,7 @@
# Chainlink env vars
CHAINLINK_DB_NAME=node_dev
CL_DEV=true
-CHAINLINK_PGPASSWORD=node
+CHAINLINK_PGPASSWORD=thispasswordislongenough
# Explorer env vars
EXPLORER_DB_NAME=explorer_dev
diff --git a/tools/docker/dev-secrets.toml b/tools/docker/dev-secrets.toml
deleted file mode 100644
index b27b8a8a8e..0000000000
--- a/tools/docker/dev-secrets.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-# dev only credentials
-
-[Database]
-AllowSimplePasswords = true
diff --git a/tools/docker/develop.Dockerfile b/tools/docker/develop.Dockerfile
index 46fad445d6..f663eaf1cf 100644
--- a/tools/docker/develop.Dockerfile
+++ b/tools/docker/develop.Dockerfile
@@ -54,7 +54,7 @@ EXPOSE 8546
# Default env setup for testing
ENV CHAINLINK_DB_NAME chainlink_test
-ENV CHAINLINK_PGPASSWORD=node
+ENV CHAINLINK_PGPASSWORD=thispasswordislongenough
ENV CL_DATABASE_URL=postgresql://postgres:$CHAINLINK_PGPASSWORD@localhost:5432/$CHAINLINK_DB_NAME?sslmode=disable
ENV TYPEORM_USERNAME=postgres
ENV TYPEORM_PASSWORD=node
diff --git a/tools/docker/docker-compose.yaml b/tools/docker/docker-compose.yaml
index 4d3ef7def2..c01d357935 100644
--- a/tools/docker/docker-compose.yaml
+++ b/tools/docker/docker-compose.yaml
@@ -10,7 +10,7 @@ services:
# Note that the keystore import allows us to submit transactions
# immediately because addresses are specified when starting the
# parity/geth node to be prefunded with eth.
- entrypoint: /bin/sh -c "chainlink -c /run/secrets/config -s /run/secrets/secrets node start -d -p /run/secrets/node_password -a /run/secrets/apicredentials"
+ entrypoint: /bin/sh -c "chainlink -c /run/secrets/config node start -d -p /run/secrets/node_password -a /run/secrets/apicredentials"
restart: always
environment:
- CL_DATABASE_URL
@@ -23,7 +23,6 @@ services:
- apicredentials
- keystore
- config
- - secrets
node-2:
container_name: chainlink-node-2
@@ -31,7 +30,7 @@ services:
build:
context: ../../
dockerfile: core/chainlink.Dockerfile
- entrypoint: /bin/sh -c "chainlink -c /run/secrets/config -s /run/secrets/secrets node start -d -p /run/secrets/node_password -a /run/secrets/apicredentials"
+ entrypoint: /bin/sh -c "chainlink -c /run/secrets/config node start -d -p /run/secrets/node_password -a /run/secrets/apicredentials"
restart: always
environment:
- CL_DATABASE_URL
@@ -44,7 +43,6 @@ services:
- apicredentials
- keystore
- config
- - secrets
# TODO
# - replace clroot with secrets
@@ -59,6 +57,4 @@ secrets:
file: ../secrets/0xb90c7E3F7815F59EAD74e7543eB6D9E8538455D6.json
config:
file: config.toml
- secrets:
- file: dev-secrets.toml
From c95d8f80832d7867daf98dd73ae2f4ad670b970c Mon Sep 17 00:00:00 2001
From: Lei
Date: Fri, 27 Oct 2023 09:41:34 -0700
Subject: [PATCH 025/327] fix solhint issues under src/v0.8/automation (#11065)
---
contracts/package.json | 2 +-
contracts/src/v0.8/automation/AutomationBase.sol | 5 +++--
contracts/src/v0.8/automation/AutomationCompatible.sol | 4 ++--
contracts/src/v0.8/automation/Chainable.sol | 10 ++++++----
contracts/src/v0.8/automation/ExecutionPrevention.sol | 5 +++--
contracts/src/v0.8/automation/HeartbeatRequester.sol | 6 ++++--
contracts/src/v0.8/automation/UpkeepTranscoder.sol | 6 ++++--
7 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/contracts/package.json b/contracts/package.json
index 46b47440a6..935c7901b6 100644
--- a/contracts/package.json
+++ b/contracts/package.json
@@ -18,7 +18,7 @@
"prepublishOnly": "pnpm compile && ./scripts/prepublish_generate_abi_folder",
"publish-beta": "pnpm publish --tag beta",
"publish-prod": "npm dist-tag add @chainlink/contracts@0.8.0 latest",
- "solhint": "solhint --max-warnings 377 \"./src/v0.8/**/*.sol\""
+ "solhint": "solhint --max-warnings 350 \"./src/v0.8/**/*.sol\""
},
"files": [
"src/v0.8",
diff --git a/contracts/src/v0.8/automation/AutomationBase.sol b/contracts/src/v0.8/automation/AutomationBase.sol
index d91780a79f..8267fbc6a4 100644
--- a/contracts/src/v0.8/automation/AutomationBase.sol
+++ b/contracts/src/v0.8/automation/AutomationBase.sol
@@ -8,7 +8,8 @@ contract AutomationBase {
* @notice method that allows it to be simulated via eth_call by checking that
* the sender is the zero address.
*/
- function preventExecution() internal view {
+ function _preventExecution() internal view {
+ // solhint-disable-next-line avoid-tx-origin
if (tx.origin != address(0)) {
revert OnlySimulatedBackend();
}
@@ -19,7 +20,7 @@ contract AutomationBase {
* that the sender is the zero address.
*/
modifier cannotExecute() {
- preventExecution();
+ _preventExecution();
_;
}
}
diff --git a/contracts/src/v0.8/automation/AutomationCompatible.sol b/contracts/src/v0.8/automation/AutomationCompatible.sol
index 5634956ea7..6533243684 100644
--- a/contracts/src/v0.8/automation/AutomationCompatible.sol
+++ b/contracts/src/v0.8/automation/AutomationCompatible.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import "./AutomationBase.sol";
-import "./interfaces/AutomationCompatibleInterface.sol";
+import {AutomationBase} from "./AutomationBase.sol";
+import {AutomationCompatibleInterface} from "./interfaces/AutomationCompatibleInterface.sol";
abstract contract AutomationCompatible is AutomationBase, AutomationCompatibleInterface {}
diff --git a/contracts/src/v0.8/automation/Chainable.sol b/contracts/src/v0.8/automation/Chainable.sol
index 1b446f013a..29ac7796c4 100644
--- a/contracts/src/v0.8/automation/Chainable.sol
+++ b/contracts/src/v0.8/automation/Chainable.sol
@@ -10,29 +10,31 @@ contract Chainable {
/**
* @dev addresses of the next contract in the chain **have to be immutable/constant** or the system won't work
*/
- address private immutable FALLBACK_ADDRESS;
+ address private immutable i_FALLBACK_ADDRESS;
/**
* @param fallbackAddress the address of the next contract in the chain
*/
constructor(address fallbackAddress) {
- FALLBACK_ADDRESS = fallbackAddress;
+ i_FALLBACK_ADDRESS = fallbackAddress;
}
/**
* @notice returns the address of the next contract in the chain
*/
function fallbackTo() external view returns (address) {
- return FALLBACK_ADDRESS;
+ return i_FALLBACK_ADDRESS;
}
/**
* @notice the fallback function routes the call to the next contract in the chain
* @dev most of the implementation is copied directly from OZ's Proxy contract
*/
+ // solhint-disable payable-fallback
+ // solhint-disable-next-line no-complex-fallback
fallback() external {
// copy to memory for assembly access
- address next = FALLBACK_ADDRESS;
+ address next = i_FALLBACK_ADDRESS;
// copied directly from OZ's Proxy contract
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
diff --git a/contracts/src/v0.8/automation/ExecutionPrevention.sol b/contracts/src/v0.8/automation/ExecutionPrevention.sol
index a8baf55fd2..30a823c4b8 100644
--- a/contracts/src/v0.8/automation/ExecutionPrevention.sol
+++ b/contracts/src/v0.8/automation/ExecutionPrevention.sol
@@ -8,7 +8,8 @@ abstract contract ExecutionPrevention {
* @notice method that allows it to be simulated via eth_call by checking that
* the sender is the zero address.
*/
- function preventExecution() internal view {
+ function _preventExecution() internal view {
+ // solhint-disable-next-line avoid-tx-origin
if (tx.origin != address(0)) {
revert OnlySimulatedBackend();
}
@@ -19,7 +20,7 @@ abstract contract ExecutionPrevention {
* that the sender is the zero address.
*/
modifier cannotExecute() {
- preventExecution();
+ _preventExecution();
_;
}
}
diff --git a/contracts/src/v0.8/automation/HeartbeatRequester.sol b/contracts/src/v0.8/automation/HeartbeatRequester.sol
index d5802a7958..aa39073800 100644
--- a/contracts/src/v0.8/automation/HeartbeatRequester.sol
+++ b/contracts/src/v0.8/automation/HeartbeatRequester.sol
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: MIT
+// solhint-disable-next-line one-contract-per-file
pragma solidity 0.8.6;
-import "./../interfaces/TypeAndVersionInterface.sol";
-import "../shared/access/ConfirmedOwner.sol";
+import {TypeAndVersionInterface} from "./../interfaces/TypeAndVersionInterface.sol";
+import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
// defines some interfaces for type safety and reduces encoding/decoding
// does not use the full interfaces intentionally because the requester only uses a fraction of them
@@ -32,6 +33,7 @@ contract HeartbeatRequester is TypeAndVersionInterface, ConfirmedOwner {
* - HeartbeatRequester 1.0.0: The requester fetches the latest aggregator address from proxy, and request a new round
* using the aggregator address.
*/
+ // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
string public constant override typeAndVersion = "HeartbeatRequester 1.0.0";
constructor() ConfirmedOwner(msg.sender) {}
diff --git a/contracts/src/v0.8/automation/UpkeepTranscoder.sol b/contracts/src/v0.8/automation/UpkeepTranscoder.sol
index 450da8c14a..144a96c7e7 100644
--- a/contracts/src/v0.8/automation/UpkeepTranscoder.sol
+++ b/contracts/src/v0.8/automation/UpkeepTranscoder.sol
@@ -2,8 +2,9 @@
pragma solidity ^0.8.0;
-import "./interfaces/UpkeepTranscoderInterface.sol";
-import "../interfaces/TypeAndVersionInterface.sol";
+import {UpkeepTranscoderInterface} from "./interfaces/UpkeepTranscoderInterface.sol";
+import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
+import {UpkeepFormat} from "./UpkeepFormat.sol";
/**
* @notice Transcoder for converting upkeep data from one keeper
@@ -16,6 +17,7 @@ contract UpkeepTranscoder is UpkeepTranscoderInterface, TypeAndVersionInterface
* @notice versions:
* - UpkeepTranscoder 1.0.0: placeholder to allow new formats in the future
*/
+ // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
string public constant override typeAndVersion = "UpkeepTranscoder 1.0.0";
/**
From 2df49da68def10542e9f885aa8e8435f807ba2b8 Mon Sep 17 00:00:00 2001
From: Erik Burton
Date: Sat, 28 Oct 2023 04:01:16 -0700
Subject: [PATCH 026/327] [RE-2009] Bump action references (#11115)
* Bump docker/setup-buildx-action from 2.7.0 to 3.0.0
* Bump docker/build-push-action from 3.2.0 to 5.0.0
* Bump aws-actions/configure-aws-credentials from 3.0.2 to 4.0.1
---
.github/actions/build-sign-publish-chainlink/action.yml | 6 +++---
.github/actions/goreleaser-build-sign-publish/action.yml | 2 +-
.github/workflows/helm-publish.yml | 2 +-
.github/workflows/performance-tests.yml | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml
index bd633bced7..55c682bc8d 100644
--- a/.github/actions/build-sign-publish-chainlink/action.yml
+++ b/.github/actions/build-sign-publish-chainlink/action.yml
@@ -112,7 +112,7 @@ runs:
registry: ${{ inputs.ecr-hostname }}
- name: Setup Docker Buildx
- uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0
+ uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Generate docker metadata for root image
id: meta-root
@@ -128,7 +128,7 @@ runs:
- name: Build and push root docker image
id: buildpush-root
- uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 # v3.2.0
+ uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
push: ${{ inputs.publish }}
context: .
@@ -161,7 +161,7 @@ runs:
- name: Build and push non-root docker image
id: buildpush-nonroot
- uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 # v3.2.0
+ uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
push: ${{ inputs.publish }}
context: .
diff --git a/.github/actions/goreleaser-build-sign-publish/action.yml b/.github/actions/goreleaser-build-sign-publish/action.yml
index 0cc144564c..845d2443fc 100644
--- a/.github/actions/goreleaser-build-sign-publish/action.yml
+++ b/.github/actions/goreleaser-build-sign-publish/action.yml
@@ -65,7 +65,7 @@ runs:
using: composite
steps:
- name: Setup docker buildx
- uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0
+ uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Set up qemu
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0
- name: Setup go
diff --git a/.github/workflows/helm-publish.yml b/.github/workflows/helm-publish.yml
index 48a7060fc7..6ea46e6a52 100644
--- a/.github/workflows/helm-publish.yml
+++ b/.github/workflows/helm-publish.yml
@@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Configure aws credentials
- uses: aws-actions/configure-aws-credentials@50ac8dd1e1b10d09dac7b8727528b91bed831ac0 # v3.0.2
+ uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN_GATI }}
role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }}
diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml
index 277940dc2d..87fb75beca 100644
--- a/.github/workflows/performance-tests.yml
+++ b/.github/workflows/performance-tests.yml
@@ -29,9 +29,9 @@ jobs:
id: login-ecr
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@ecf95283f03858871ff00b787d79c419715afc34 # v2.7.0
+ uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Build and Push
- uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 # v3.2.0
+ uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: .
file: core/chainlink.Dockerfile
From b6550805131cf86361250eb986e869348b3a490d Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Mon, 30 Oct 2023 07:48:36 -0500
Subject: [PATCH 027/327] skipped test cleanup (#11026)
---
core/internal/testutils/testutils.go | 4 ++++
.../evm21/logprovider/integration_test.go | 20 +++++++++----------
.../internal/ocr2vrf_integration_test.go | 4 ++--
.../uni_client_integration_test.go | 5 +++--
.../vrf/v2/integration_v2_plus_test.go | 4 +---
5 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go
index 938d814b9e..79c86f0c5f 100644
--- a/core/internal/testutils/testutils.go
+++ b/core/internal/testutils/testutils.go
@@ -451,3 +451,7 @@ func MustDecodeBase64(s string) (b []byte) {
}
return
}
+
+func SkipFlakey(t *testing.T, ticketURL string) {
+ t.Skip("Flakey", ticketURL)
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index 506dcb9ea3..811468746e 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -455,9 +455,7 @@ func TestIntegration_LogEventProvider_RateLimit(t *testing.T) {
}
func TestIntegration_LogRecoverer_Backfill(t *testing.T) {
- t.Skip() // TODO: remove skip after removing constant timeouts
- ctx, cancel := context.WithTimeout(testutils.Context(t), time.Second*60)
- defer cancel()
+ ctx := testutils.Context(t)
backend, stopMining, accounts := setupBackend(t)
defer stopMining()
@@ -515,21 +513,21 @@ func TestIntegration_LogRecoverer_Backfill(t *testing.T) {
}()
defer recoverer.Close()
- lctx, lcancel := context.WithTimeout(ctx, time.Second*15)
- defer lcancel()
var allProposals []ocr2keepers.UpkeepPayload
- for lctx.Err() == nil {
+ for {
poll(backend.Commit())
proposals, err := recoverer.GetRecoveryProposals(ctx)
require.NoError(t, err)
allProposals = append(allProposals, proposals...)
- if len(allProposals) < n {
- time.Sleep(100 * time.Millisecond)
- continue
+ if len(allProposals) >= n {
+ break // success
+ }
+ select {
+ case <-ctx.Done():
+ t.Fatalf("could not recover logs before timeout: %s", ctx.Err())
+ case <-time.After(100 * time.Millisecond):
}
- break
}
- require.NoError(t, lctx.Err(), "could not recover logs before timeout")
}
func collectPayloads(ctx context.Context, t *testing.T, logProvider logprovider.LogEventProvider, n, rounds int) []ocr2keepers.UpkeepPayload {
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 b9a4d50002..cf7a408725 100644
--- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
@@ -326,12 +326,12 @@ func setupNodeOCR2(
}
func TestIntegration_OCR2VRF_ForwarderFlow(t *testing.T) {
- t.Skip()
+ testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/VRF-688")
runOCR2VRFTest(t, true)
}
func TestIntegration_OCR2VRF(t *testing.T) {
- t.Skip()
+ testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/VRF-688")
runOCR2VRFTest(t, false)
}
diff --git a/core/services/synchronization/uni_client_integration_test.go b/core/services/synchronization/uni_client_integration_test.go
index 1ad2865669..fcc0dc2371 100644
--- a/core/services/synchronization/uni_client_integration_test.go
+++ b/core/services/synchronization/uni_client_integration_test.go
@@ -6,16 +6,17 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/wsrpc"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/wsrpc"
+
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
)
func TestUniClient(t *testing.T) {
- t.Skip()
+ t.Skip("Incomplete", "https://smartcontract-it.atlassian.net/browse/BCF-2729")
privKey, err := hex.DecodeString("TODO")
require.NoError(t, err)
pubKey, err := hex.DecodeString("TODO")
diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go
index 9adf47f256..f08c10c200 100644
--- a/core/services/vrf/v2/integration_v2_plus_test.go
+++ b/core/services/vrf/v2/integration_v2_plus_test.go
@@ -486,9 +486,7 @@ func TestVRFV2PlusIntegration_SingleConsumer_EOA_Request_Batching_Enabled(t *tes
}
func TestVRFV2PlusIntegration_SingleConsumer_EIP150_HappyPath(t *testing.T) {
- // See: https://smartcontract-it.atlassian.net/browse/VRF-589
- // Temporarily skipping to figure out issue with test
- t.Skip()
+ testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/VRF-589")
t.Parallel()
ownerKey := cltest.MustGenerateRandomKey(t)
uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false)
From db64df96ba3ab987a27d684b8161c35fcaa569b8 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Mon, 30 Oct 2023 14:05:31 +0000
Subject: [PATCH 028/327] [BCF-2630] Add pipeline runner wrapper (#11091)
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
.../generic/pipeline_runner_adapter.go | 94 ++++++++++++
.../generic/pipeline_runner_adapter_test.go | 144 ++++++++++++++++++
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
8 files changed, 247 insertions(+), 9 deletions(-)
create mode 100644 core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
create mode 100644 core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index c8b616a4b6..f097ea89be 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -302,7 +302,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index c4d0575bb2..0461daa25e 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1458,8 +1458,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9 h1:fFD5SgSJtnXvkGLK3CExNKpUIz4sGrNNkKv3Ljw63Hk=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
new file mode 100644
index 0000000000..5c58522f40
--- /dev/null
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
@@ -0,0 +1,94 @@
+package generic
+
+import (
+ "context"
+ "time"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/job"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ "github.com/smartcontractkit/chainlink/v2/core/store/models"
+)
+
+var _ types.PipelineRunnerService = (*PipelineRunnerAdapter)(nil)
+
+type pipelineRunner interface {
+ ExecuteRun(ctx context.Context, spec pipeline.Spec, vars pipeline.Vars, l logger.Logger) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error)
+}
+
+type PipelineRunnerAdapter struct {
+ runner pipelineRunner
+ job job.Job
+ logger logger.Logger
+}
+
+func (p *PipelineRunnerAdapter) ExecuteRun(ctx context.Context, spec string, vars types.Vars, options types.Options) ([]types.TaskResult, error) {
+ s := pipeline.Spec{
+ DotDagSource: spec,
+ CreatedAt: time.Now(),
+ MaxTaskDuration: models.Interval(options.MaxTaskDuration),
+ JobID: p.job.ID,
+ JobName: p.job.Name.ValueOrZero(),
+ JobType: string(p.job.Type),
+ }
+
+ defaultVars := map[string]interface{}{
+ "jb": map[string]interface{}{
+ "databaseID": p.job.ID,
+ "externalJobID": p.job.ExternalJobID,
+ "name": p.job.Name.ValueOrZero(),
+ },
+ }
+
+ err := merge(defaultVars, vars.Vars)
+ if err != nil {
+ return nil, err
+ }
+
+ finalVars := pipeline.NewVarsFrom(defaultVars)
+ _, trrs, err := p.runner.ExecuteRun(ctx, s, finalVars, p.logger)
+ if err != nil {
+ return nil, err
+ }
+
+ taskResults := make([]types.TaskResult, len(trrs))
+ for i, trr := range trrs {
+ taskResults[i] = types.TaskResult{
+ ID: trr.ID.String(),
+ Type: string(trr.Task.Type()),
+ Value: trr.Result.Value,
+ Error: trr.Result.Error,
+ Index: int(trr.TaskRun.Index),
+ }
+ }
+ return taskResults, nil
+}
+
+func NewPipelineRunnerAdapter(logger logger.Logger, job job.Job, runner pipelineRunner) *PipelineRunnerAdapter {
+ return &PipelineRunnerAdapter{
+ logger: logger,
+ job: job,
+ runner: runner,
+ }
+}
+
+// merge merges mapTwo into mapOne, modifying mapOne in the process.
+func merge(mapOne, mapTwo map[string]interface{}) error {
+ for k, v := range mapTwo {
+ // if `mapOne` doesn't have `k`, then nothing to do, just assign v to `mapOne`.
+ if _, ok := mapOne[k]; !ok {
+ mapOne[k] = v
+ } else {
+ vAsMap, vOK := v.(map[string]interface{})
+ mapOneVAsMap, moOK := mapOne[k].(map[string]interface{})
+ if vOK && moOK {
+ merge(mapOneVAsMap, vAsMap)
+ } else {
+ mapOne[k] = v
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
new file mode 100644
index 0000000000..d1f06d8766
--- /dev/null
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
@@ -0,0 +1,144 @@
+package generic
+
+import (
+ "context"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/shopspring/decimal"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "gopkg.in/guregu/null.v4"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "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"
+ "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/utils"
+)
+
+const spec = `
+answer [type=sum values=<[ $(val), 2 ]>]
+answer;
+`
+
+func TestAdapter_Integration(t *testing.T) {
+ logger := logger.TestLogger(t)
+ cfg := configtest.NewTestGeneralConfig(t)
+ url := cfg.Database().URL()
+ db, err := pg.NewConnection(url.String(), cfg.Database().Dialect(), cfg.Database())
+ require.NoError(t, err)
+
+ keystore := keystore.NewInMemory(db, utils.FastScryptParams, logger, cfg.Database())
+ pipelineORM := pipeline.NewORM(db, logger, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
+ bridgesORM := bridges.NewORM(db, logger, cfg.Database())
+ pr := pipeline.NewRunner(
+ pipelineORM,
+ bridgesORM,
+ cfg.JobPipeline(),
+ cfg.WebServer(),
+ nil,
+ keystore.Eth(),
+ keystore.VRF(),
+ logger,
+ http.DefaultClient,
+ http.DefaultClient,
+ )
+ pra := NewPipelineRunnerAdapter(logger, job.Job{}, pr)
+ results, err := pra.ExecuteRun(context.Background(), spec, types.Vars{Vars: map[string]interface{}{"val": 1}}, types.Options{})
+ require.NoError(t, err)
+
+ finalResult := results[0].Value.(decimal.Decimal)
+
+ assert.True(t, decimal.NewFromInt(3).Equal(finalResult))
+}
+
+func newMockPipelineRunner() *mockPipelineRunner {
+ return &mockPipelineRunner{}
+}
+
+type mockPipelineRunner struct {
+ results pipeline.TaskRunResults
+ err error
+ run *pipeline.Run
+ spec pipeline.Spec
+ vars pipeline.Vars
+}
+
+func (m *mockPipelineRunner) ExecuteRun(ctx context.Context, spec pipeline.Spec, vars pipeline.Vars, l logger.Logger) (*pipeline.Run, pipeline.TaskRunResults, error) {
+ m.spec = spec
+ m.vars = vars
+ return m.run, m.results, m.err
+}
+
+func TestAdapter_AddsDefaultVars(t *testing.T) {
+ logger := logger.TestLogger(t)
+ mpr := newMockPipelineRunner()
+ jobID, externalJobID, name := int32(100), uuid.New(), null.StringFrom("job-name")
+ pra := NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name}, mpr)
+
+ _, err := pra.ExecuteRun(context.Background(), spec, types.Vars{}, types.Options{})
+ require.NoError(t, err)
+
+ gotName, err := mpr.vars.Get("jb.name")
+ require.NoError(t, err)
+ assert.Equal(t, name.String, gotName)
+
+ gotID, err := mpr.vars.Get("jb.databaseID")
+ require.NoError(t, err)
+ assert.Equal(t, jobID, gotID)
+
+ gotExternalID, err := mpr.vars.Get("jb.externalJobID")
+ require.NoError(t, err)
+ assert.Equal(t, externalJobID, gotExternalID)
+}
+
+func TestPipelineRunnerAdapter_SetsVarsOnSpec(t *testing.T) {
+ logger := logger.TestLogger(t)
+ mpr := newMockPipelineRunner()
+ jobID, externalJobID, name, jobType := int32(100), uuid.New(), null.StringFrom("job-name"), job.Type("generic")
+ pra := NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name, Type: jobType}, mpr)
+
+ maxDuration := time.Duration(100 * time.Second)
+ _, err := pra.ExecuteRun(context.Background(), spec, types.Vars{}, types.Options{MaxTaskDuration: maxDuration})
+ require.NoError(t, err)
+
+ assert.Equal(t, jobID, mpr.spec.JobID)
+ assert.Equal(t, name.ValueOrZero(), mpr.spec.JobName)
+ assert.Equal(t, string(jobType), mpr.spec.JobType)
+ assert.Equal(t, maxDuration, mpr.spec.MaxTaskDuration.Duration())
+
+}
+
+func TestMerge(t *testing.T) {
+ vars := map[string]interface{}{
+ "jb": map[string]interface{}{
+ "databaseID": "some-job-id",
+ },
+ }
+ addedVars := map[string]interface{}{
+ "jb": map[string]interface{}{
+ "some-other-var": "foo",
+ },
+ "val": 0,
+ }
+
+ err := merge(vars, addedVars)
+ require.NoError(t, err)
+
+ assert.True(t, reflect.DeepEqual(vars, map[string]interface{}{
+ "jb": map[string]interface{}{
+ "databaseID": "some-job-id",
+ "some-other-var": "foo",
+ },
+ "val": 0,
+ }), vars)
+}
diff --git a/go.mod b/go.mod
index df970160ac..3679c79ed0 100644
--- a/go.mod
+++ b/go.mod
@@ -68,7 +68,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index 59286787c2..e2bc661048 100644
--- a/go.sum
+++ b/go.sum
@@ -1459,8 +1459,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9 h1:fFD5SgSJtnXvkGLK3CExNKpUIz4sGrNNkKv3Ljw63Hk=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 7683a96692..d3e09d94d7 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -385,7 +385,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index d280310b9f..725e05914c 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2364,8 +2364,8 @@ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc4
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
github.com/smartcontractkit/chainlink-env v0.38.3 h1:ZtOnwkG622R0VCTxL5V09AnT/QXhlFwkGTjd0Lsfpfg=
github.com/smartcontractkit/chainlink-env v0.38.3/go.mod h1:7z4sw/hN8TxioQCLwFqQdhK3vaOV0a22Qe99z4bRUcg=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9 h1:fFD5SgSJtnXvkGLK3CExNKpUIz4sGrNNkKv3Ljw63Hk=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231020230319-2ede955d1dc9/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From e242dfb9ae44a36ef05bb7b09f75fce0f415e308 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 30 Oct 2023 10:17:18 -0400
Subject: [PATCH 029/327] Every instance of mercury transmitter should not load
reports for all feeds on startup (#10829)
* Every instance of mercury transmitter should not load reports for all feeds on startup
* Fix a few persistence manager bugs
* Bump Migration version
---
core/services/relay/evm/mercury/orm.go | 38 +++++----
core/services/relay/evm/mercury/orm_test.go | 48 +++++++-----
.../relay/evm/mercury/persistence_manager.go | 4 +-
.../evm/mercury/persistence_manager_test.go | 78 ++++++++++++++-----
.../services/relay/evm/mercury/transmitter.go | 2 +-
.../relay/evm/mercury/transmitter_test.go | 4 +
...d_feed_id_to_mercury_transmit_requests.sql | 14 ++++
7 files changed, 130 insertions(+), 58 deletions(-)
create mode 100644 core/store/migrate/migrations/0205_add_feed_id_to_mercury_transmit_requests.sql
diff --git a/core/services/relay/evm/mercury/orm.go b/core/services/relay/evm/mercury/orm.go
index dd7d7b33e7..7273519f6b 100644
--- a/core/services/relay/evm/mercury/orm.go
+++ b/core/services/relay/evm/mercury/orm.go
@@ -23,8 +23,8 @@ import (
type ORM interface {
InsertTransmitRequest(req *pb.TransmitRequest, jobID int32, reportCtx ocrtypes.ReportContext, qopts ...pg.QOpt) error
DeleteTransmitRequests(reqs []*pb.TransmitRequest, qopts ...pg.QOpt) error
- GetTransmitRequests(qopts ...pg.QOpt) ([]*Transmission, error)
- PruneTransmitRequests(maxSize int, qopts ...pg.QOpt) error
+ GetTransmitRequests(jobID int32, qopts ...pg.QOpt) ([]*Transmission, error)
+ PruneTransmitRequests(jobID int32, maxSize int, qopts ...pg.QOpt) error
LatestReport(ctx context.Context, feedID [32]byte, qopts ...pg.QOpt) (report []byte, err error)
}
@@ -49,6 +49,11 @@ func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) ORM {
// InsertTransmitRequest inserts one transmit request if the payload does not exist already.
func (o *orm) InsertTransmitRequest(req *pb.TransmitRequest, jobID int32, reportCtx ocrtypes.ReportContext, qopts ...pg.QOpt) error {
+ feedID, err := FeedIDFromReport(req.Payload)
+ if err != nil {
+ return err
+ }
+
q := o.q.WithOpts(qopts...)
var wg sync.WaitGroup
wg.Add(2)
@@ -57,16 +62,12 @@ func (o *orm) InsertTransmitRequest(req *pb.TransmitRequest, jobID int32, report
go func() {
defer wg.Done()
err1 = q.ExecQ(`
- INSERT INTO mercury_transmit_requests (payload, payload_hash, config_digest, epoch, round, extra_hash, job_id)
- VALUES ($1, $2, $3, $4, $5, $6, $7)
+ INSERT INTO mercury_transmit_requests (payload, payload_hash, config_digest, epoch, round, extra_hash, job_id, feed_id)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (payload_hash) DO NOTHING
- `, req.Payload, hashPayload(req.Payload), reportCtx.ConfigDigest[:], reportCtx.Epoch, reportCtx.Round, reportCtx.ExtraHash[:], jobID)
+ `, req.Payload, hashPayload(req.Payload), reportCtx.ConfigDigest[:], reportCtx.Epoch, reportCtx.Round, reportCtx.ExtraHash[:], jobID, feedID[:])
}()
- feedID, err := FeedIDFromReport(req.Payload)
- if err != nil {
- return err
- }
go func() {
defer wg.Done()
err2 = q.ExecQ(`
@@ -101,15 +102,16 @@ func (o *orm) DeleteTransmitRequests(reqs []*pb.TransmitRequest, qopts ...pg.QOp
}
// GetTransmitRequests returns all transmit requests in chronologically descending order.
-func (o *orm) GetTransmitRequests(qopts ...pg.QOpt) ([]*Transmission, error) {
+func (o *orm) GetTransmitRequests(jobID int32, qopts ...pg.QOpt) ([]*Transmission, error) {
q := o.q.WithOpts(qopts...)
// The priority queue uses epoch and round to sort transmissions so order by
// the same fields here for optimal insertion into the pq.
rows, err := q.QueryContext(q.ParentCtx, `
SELECT payload, config_digest, epoch, round, extra_hash
FROM mercury_transmit_requests
+ WHERE job_id = $1
ORDER BY epoch DESC, round DESC
- `)
+ `, jobID)
if err != nil {
return nil, err
}
@@ -142,20 +144,22 @@ func (o *orm) GetTransmitRequests(qopts ...pg.QOpt) ([]*Transmission, error) {
return transmissions, nil
}
-// PruneTransmitRequests keeps at most maxSize rows in the table, deleting the
-// oldest transactions.
-func (o *orm) PruneTransmitRequests(maxSize int, qopts ...pg.QOpt) error {
+// PruneTransmitRequests keeps at most maxSize rows for the given job ID,
+// deleting the oldest transactions.
+func (o *orm) PruneTransmitRequests(jobID int32, maxSize int, qopts ...pg.QOpt) error {
q := o.q.WithOpts(qopts...)
// Prune the oldest requests by epoch and round.
return q.ExecQ(`
DELETE FROM mercury_transmit_requests
- WHERE payload_hash NOT IN (
+ WHERE job_id = $1 AND
+ payload_hash NOT IN (
SELECT payload_hash
FROM mercury_transmit_requests
+ WHERE job_id = $1
ORDER BY epoch DESC, round DESC
- LIMIT $1
+ LIMIT $2
)
- `, maxSize)
+ `, jobID, maxSize)
}
func (o *orm) LatestReport(ctx context.Context, feedID [32]byte, qopts ...pg.QOpt) (report []byte, err error) {
diff --git a/core/services/relay/evm/mercury/orm_test.go b/core/services/relay/evm/mercury/orm_test.go
index a6a7232767..56dea70417 100644
--- a/core/services/relay/evm/mercury/orm_test.go
+++ b/core/services/relay/evm/mercury/orm_test.go
@@ -3,6 +3,7 @@ package mercury
import (
"testing"
+ "github.com/cometbft/cometbft/libs/rand"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -16,7 +17,7 @@ import (
func TestORM(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- var jobID int32 // foreign key constraints disabled so can leave as 0
+ jobID := rand.Int32() // foreign key constraints disabled so value doesn't matter
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
lggr := logger.TestLogger(t)
@@ -48,7 +49,7 @@ func TestORM(t *testing.T) {
err = orm.InsertTransmitRequest(&pb.TransmitRequest{Payload: reports[2]}, jobID, reportContexts[2])
require.NoError(t, err)
- transmissions, err := orm.GetTransmitRequests()
+ transmissions, err := orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[2]}, ReportCtx: reportContexts[2]},
@@ -65,7 +66,7 @@ func TestORM(t *testing.T) {
err = orm.DeleteTransmitRequests([]*pb.TransmitRequest{{Payload: reports[1]}})
require.NoError(t, err)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[2]}, ReportCtx: reportContexts[2]},
@@ -80,7 +81,7 @@ func TestORM(t *testing.T) {
err = orm.DeleteTransmitRequests([]*pb.TransmitRequest{{Payload: []byte("does-not-exist")}})
require.NoError(t, err)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[2]}, ReportCtx: reportContexts[2]},
@@ -98,7 +99,7 @@ func TestORM(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, reports[2], l)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Empty(t, transmissions)
@@ -106,7 +107,7 @@ func TestORM(t *testing.T) {
err = orm.InsertTransmitRequest(&pb.TransmitRequest{Payload: reports[3]}, jobID, reportContexts[3])
require.NoError(t, err)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[3]}, ReportCtx: reportContexts[3]},
@@ -118,7 +119,7 @@ func TestORM(t *testing.T) {
err = orm.InsertTransmitRequest(&pb.TransmitRequest{Payload: reports[3]}, jobID, reportContexts[3])
require.NoError(t, err)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[3]}, ReportCtx: reportContexts[3]},
@@ -131,7 +132,7 @@ func TestORM(t *testing.T) {
func TestORM_PruneTransmitRequests(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- var jobID int32 // foreign key constraints disabled so can leave as 0
+ jobID := rand.Int32() // foreign key constraints disabled so value doesn't matter
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
@@ -157,10 +158,10 @@ func TestORM_PruneTransmitRequests(t *testing.T) {
require.NoError(t, err)
// Max size greater than table size, expect no-op
- err = orm.PruneTransmitRequests(5)
+ err = orm.PruneTransmitRequests(jobID, 5)
require.NoError(t, err)
- transmissions, err := orm.GetTransmitRequests()
+ transmissions, err := orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[1]}, ReportCtx: makeReportContext(1, 2)},
@@ -168,37 +169,48 @@ func TestORM_PruneTransmitRequests(t *testing.T) {
})
// Max size equal to table size, expect no-op
- err = orm.PruneTransmitRequests(2)
+ err = orm.PruneTransmitRequests(jobID, 2)
require.NoError(t, err)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
require.Equal(t, transmissions, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[1]}, ReportCtx: makeReportContext(1, 2)},
{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: makeReportContext(1, 1)},
})
+ // Max size is table size + 1, but jobID differs, expect no-op
+ err = orm.PruneTransmitRequests(-1, 2)
+ require.NoError(t, err)
+
+ transmissions, err = orm.GetTransmitRequests(jobID)
+ require.NoError(t, err)
+ require.Equal(t, []*Transmission{
+ {Req: &pb.TransmitRequest{Payload: reports[1]}, ReportCtx: makeReportContext(1, 2)},
+ {Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: makeReportContext(1, 1)},
+ }, transmissions)
+
err = orm.InsertTransmitRequest(&pb.TransmitRequest{Payload: reports[2]}, jobID, makeReportContext(2, 1))
require.NoError(t, err)
err = orm.InsertTransmitRequest(&pb.TransmitRequest{Payload: reports[3]}, jobID, makeReportContext(2, 2))
require.NoError(t, err)
- // Max size is table size + 1, expect the oldest row to be pruned.
- err = orm.PruneTransmitRequests(3)
+ // Max size is table size - 1, expect the oldest row to be pruned.
+ err = orm.PruneTransmitRequests(jobID, 3)
require.NoError(t, err)
- transmissions, err = orm.GetTransmitRequests()
+ transmissions, err = orm.GetTransmitRequests(jobID)
require.NoError(t, err)
- require.Equal(t, transmissions, []*Transmission{
+ require.Equal(t, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[3]}, ReportCtx: makeReportContext(2, 2)},
{Req: &pb.TransmitRequest{Payload: reports[2]}, ReportCtx: makeReportContext(2, 1)},
{Req: &pb.TransmitRequest{Payload: reports[1]}, ReportCtx: makeReportContext(1, 2)},
- })
+ }, transmissions)
}
func TestORM_InsertTransmitRequest_LatestReport(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- var jobID int32 // foreign key constraints disabled so can leave as 0
+ jobID := rand.Int32() // foreign key constraints disabled so value doesn't matter
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
diff --git a/core/services/relay/evm/mercury/persistence_manager.go b/core/services/relay/evm/mercury/persistence_manager.go
index 9e8df72a15..1c8dad4530 100644
--- a/core/services/relay/evm/mercury/persistence_manager.go
+++ b/core/services/relay/evm/mercury/persistence_manager.go
@@ -78,7 +78,7 @@ func (pm *PersistenceManager) AsyncDelete(req *pb.TransmitRequest) {
}
func (pm *PersistenceManager) Load(ctx context.Context) ([]*Transmission, error) {
- return pm.orm.GetTransmitRequests(pg.WithParentCtx(ctx))
+ return pm.orm.GetTransmitRequests(pm.jobID, pg.WithParentCtx(ctx))
}
func (pm *PersistenceManager) runFlushDeletesLoop() {
@@ -118,7 +118,7 @@ func (pm *PersistenceManager) runPruneLoop() {
ticker.Stop()
return
case <-ticker.C:
- if err := pm.orm.PruneTransmitRequests(pm.maxTransmitQueueSize, pg.WithParentCtx(ctx), pg.WithLongQueryTimeout()); err != nil {
+ if err := pm.orm.PruneTransmitRequests(pm.jobID, pm.maxTransmitQueueSize, pg.WithParentCtx(ctx), pg.WithLongQueryTimeout()); err != nil {
pm.lggr.Errorw("Failed to prune transmit requests table", "err", err)
} else {
pm.lggr.Debugw("Pruned transmit requests table")
diff --git a/core/services/relay/evm/mercury/persistence_manager_test.go b/core/services/relay/evm/mercury/persistence_manager_test.go
index 97628ed9c2..d185a64a8f 100644
--- a/core/services/relay/evm/mercury/persistence_manager_test.go
+++ b/core/services/relay/evm/mercury/persistence_manager_test.go
@@ -5,7 +5,10 @@ import (
"testing"
"time"
+ "github.com/cometbft/cometbft/libs/rand"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/smartcontractkit/sqlx"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
@@ -16,19 +19,22 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb"
)
-func bootstrapPersistenceManager(t *testing.T) (*PersistenceManager, *observer.ObservedLogs) {
+func bootstrapPersistenceManager(t *testing.T, jobID int32, db *sqlx.DB) (*PersistenceManager, *observer.ObservedLogs) {
t.Helper()
- db := pgtest.NewSqlxDB(t)
- pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
- pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel)
orm := NewORM(db, lggr, pgtest.NewQConfig(true))
- return NewPersistenceManager(lggr, orm, 0, 2, 5*time.Millisecond, 5*time.Millisecond), observedLogs
+ return NewPersistenceManager(lggr, orm, jobID, 2, 5*time.Millisecond, 5*time.Millisecond), observedLogs
}
func TestPersistenceManager(t *testing.T) {
+ jobID1 := rand.Int32()
+ jobID2 := jobID1 + 1
+
ctx := context.Background()
- pm, _ := bootstrapPersistenceManager(t)
+ db := pgtest.NewSqlxDB(t)
+ pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
+ pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
+ pm, _ := bootstrapPersistenceManager(t, jobID1, db)
reports := sampleReports
@@ -52,11 +58,23 @@ func TestPersistenceManager(t *testing.T) {
require.Equal(t, []*Transmission{
{Req: &pb.TransmitRequest{Payload: reports[1]}},
}, transmissions)
+
+ t.Run("scopes load to only transmissions with matching job ID", func(t *testing.T) {
+ pm2, _ := bootstrapPersistenceManager(t, jobID2, db)
+ transmissions, err = pm2.Load(ctx)
+ require.NoError(t, err)
+
+ assert.Len(t, transmissions, 0)
+ })
}
func TestPersistenceManagerAsyncDelete(t *testing.T) {
ctx := context.Background()
- pm, observedLogs := bootstrapPersistenceManager(t)
+ jobID := rand.Int32()
+ db := pgtest.NewSqlxDB(t)
+ pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
+ pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
+ pm, observedLogs := bootstrapPersistenceManager(t, jobID, db)
reports := sampleReports
@@ -96,16 +114,32 @@ func TestPersistenceManagerAsyncDelete(t *testing.T) {
}
func TestPersistenceManagerPrune(t *testing.T) {
+ jobID1 := rand.Int32()
+ jobID2 := jobID1 + 1
+ db := pgtest.NewSqlxDB(t)
+ pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
+ pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
+
ctx := context.Background()
- pm, observedLogs := bootstrapPersistenceManager(t)
- reports := sampleReports
+ reports := make([][]byte, 25)
+ for i := 0; i < 25; i++ {
+ reports[i] = buildSampleV1Report(int64(i))
+ }
- err := pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[0]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 1}})
+ pm2, _ := bootstrapPersistenceManager(t, jobID2, db)
+ for i := 0; i < 20; i++ {
+ err := pm2.Insert(ctx, &pb.TransmitRequest{Payload: reports[i]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: uint32(i)}})
+ require.NoError(t, err)
+ }
+
+ pm, observedLogs := bootstrapPersistenceManager(t, jobID1, db)
+
+ err := pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[21]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 21}})
require.NoError(t, err)
- err = pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[1]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 2}})
+ err = pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[22]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 22}})
require.NoError(t, err)
- err = pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[2]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 3}})
+ err = pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[23]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 23}})
require.NoError(t, err)
err = pm.Start(ctx)
@@ -118,24 +152,28 @@ func TestPersistenceManagerPrune(t *testing.T) {
transmissions, err := pm.Load(ctx)
require.NoError(t, err)
require.Equal(t, []*Transmission{
- {Req: &pb.TransmitRequest{Payload: reports[2]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 3}}},
- {Req: &pb.TransmitRequest{Payload: reports[1]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 2}}},
+ {Req: &pb.TransmitRequest{Payload: reports[23]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 23}}},
+ {Req: &pb.TransmitRequest{Payload: reports[22]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 22}}},
}, transmissions)
// Test pruning stops after Close.
err = pm.Close()
require.NoError(t, err)
- err = pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[3]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 4}})
+ err = pm.Insert(ctx, &pb.TransmitRequest{Payload: reports[24]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 24}})
require.NoError(t, err)
- time.Sleep(15 * time.Millisecond)
-
transmissions, err = pm.Load(ctx)
require.NoError(t, err)
require.Equal(t, []*Transmission{
- {Req: &pb.TransmitRequest{Payload: reports[3]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 4}}},
- {Req: &pb.TransmitRequest{Payload: reports[2]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 3}}},
- {Req: &pb.TransmitRequest{Payload: reports[1]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 2}}},
+ {Req: &pb.TransmitRequest{Payload: reports[24]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 24}}},
+ {Req: &pb.TransmitRequest{Payload: reports[23]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 23}}},
+ {Req: &pb.TransmitRequest{Payload: reports[22]}, ReportCtx: ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: 22}}},
}, transmissions)
+
+ t.Run("prune was scoped to job ID", func(t *testing.T) {
+ transmissions, err = pm2.Load(ctx)
+ require.NoError(t, err)
+ assert.Len(t, transmissions, 20)
+ })
}
diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go
index 0c701e3b4b..0c2721442b 100644
--- a/core/services/relay/evm/mercury/transmitter.go
+++ b/core/services/relay/evm/mercury/transmitter.go
@@ -137,7 +137,7 @@ func NewTransmitter(lggr logger.Logger, cfgTracker ConfigTracker, rpcClient wsrp
jobID,
fmt.Sprintf("%x", fromAccount),
make(chan (struct{})),
- NewTransmitQueue(lggr, feedIDHex, maxTransmitQueueSize, nil, persistenceManager),
+ nil,
sync.WaitGroup{},
transmitSuccessCount.WithLabelValues(feedIDHex),
transmitDuplicateCount.WithLabelValues(feedIDHex),
diff --git a/core/services/relay/evm/mercury/transmitter_test.go b/core/services/relay/evm/mercury/transmitter_test.go
index 6723ffcbca..c8a68d41a1 100644
--- a/core/services/relay/evm/mercury/transmitter_test.go
+++ b/core/services/relay/evm/mercury/transmitter_test.go
@@ -26,6 +26,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) {
var jobID int32
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
+ q := NewTransmitQueue(lggr, "", 0, nil, nil)
t.Run("v1 report transmission successfully enqueued", func(t *testing.T) {
report := sampleV1Report
@@ -40,6 +41,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) {
},
}
mt := NewTransmitter(lggr, nil, c, sampleClientPubKey, jobID, sampleFeedID, db, pgtest.NewQConfig(true), nil)
+ mt.queue = q
err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs)
require.NoError(t, err)
@@ -57,6 +59,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) {
},
}
mt := NewTransmitter(lggr, nil, c, sampleClientPubKey, jobID, sampleFeedID, db, pgtest.NewQConfig(true), nil)
+ mt.queue = q
err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs)
require.NoError(t, err)
@@ -74,6 +77,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) {
},
}
mt := NewTransmitter(lggr, nil, c, sampleClientPubKey, jobID, sampleFeedID, db, pgtest.NewQConfig(true), nil)
+ mt.queue = q
err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs)
require.NoError(t, err)
diff --git a/core/store/migrate/migrations/0205_add_feed_id_to_mercury_transmit_requests.sql b/core/store/migrate/migrations/0205_add_feed_id_to_mercury_transmit_requests.sql
new file mode 100644
index 0000000000..04cf5a2571
--- /dev/null
+++ b/core/store/migrate/migrations/0205_add_feed_id_to_mercury_transmit_requests.sql
@@ -0,0 +1,14 @@
+-- +goose Up
+ALTER TABLE mercury_transmit_requests ADD COLUMN feed_id BYTEA CHECK (feed_id IS NULL OR octet_length(feed_id) = 32);
+DROP INDEX idx_mercury_transmission_requests_epoch_round;
+CREATE INDEX idx_mercury_transmission_requests_job_id_epoch_round ON mercury_transmit_requests (job_id, epoch DESC, round DESC);
+CREATE INDEX idx_mercury_transmit_requests_job_id ON mercury_transmit_requests (job_id);
+CREATE INDEX idx_mercury_transmit_requests_feed_id ON mercury_transmit_requests (feed_id);
+CREATE INDEX idx_mercury_feed_latest_reports_job_id ON feed_latest_reports (job_id);
+
+-- +goose Down
+ALTER TABLE mercury_transmit_requests DROP COLUMN feed_id;
+DROP INDEX idx_mercury_transmit_requests_job_id;
+DROP INDEX idx_mercury_feed_latest_reports_job_id;
+CREATE INDEX idx_mercury_transmission_requests_epoch_round ON mercury_transmit_requests (epoch DESC, round DESC);
+DROP INDEX idx_mercury_transmission_requests_job_id_epoch_round;
From 5e1c3a3f2ddf35ac6e86f9640ba33f71173efadc Mon Sep 17 00:00:00 2001
From: Lukasz <120112546+lukaszcl@users.noreply.github.com>
Date: Mon, 30 Oct 2023 16:22:07 +0100
Subject: [PATCH 030/327] Use CTF instead of chainlink-env in E2E tests
(#11120)
---
integration-tests/actions/actions.go | 2 +-
integration-tests/benchmark/keeper_test.go | 12 ++++++------
integration-tests/chaos/automation_chaos_test.go | 12 ++++++------
integration-tests/chaos/ocr2vrf_chaos_test.go | 10 +++++-----
integration-tests/chaos/ocr_chaos_test.go | 16 ++++++++--------
.../client/chainlink_config_builder.go | 2 +-
integration-tests/client/chainlink_k8s.go | 2 +-
integration-tests/go.mod | 3 +--
integration-tests/go.sum | 6 ++----
integration-tests/performance/cron_test.go | 12 ++++++------
.../performance/directrequest_test.go | 10 +++++-----
integration-tests/performance/flux_test.go | 10 +++++-----
integration-tests/performance/keeper_test.go | 10 +++++-----
integration-tests/performance/ocr_test.go | 10 +++++-----
integration-tests/performance/vrf_test.go | 6 +++---
integration-tests/reorg/automation_reorg_test.go | 8 ++++----
integration-tests/reorg/reorg_confirmer.go | 8 ++++----
integration-tests/reorg/reorg_test.go | 14 +++++++-------
integration-tests/smoke/ocr2_test.go | 10 +++++-----
integration-tests/smoke/ocr2vrf_test.go | 6 +++---
integration-tests/testsetups/don_evm_chain.go | 10 +++++-----
integration-tests/testsetups/keeper_benchmark.go | 2 +-
integration-tests/testsetups/ocr.go | 10 +++++-----
integration-tests/testsetups/profile.go | 2 +-
integration-tests/testsetups/vrfv2.go | 2 +-
25 files changed, 96 insertions(+), 99 deletions(-)
diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go
index dcdca91cc7..010b431b56 100644
--- a/integration-tests/actions/actions.go
+++ b/integration-tests/actions/actions.go
@@ -16,9 +16,9 @@ import (
"github.com/rs/zerolog/log"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/environment"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/testreporters"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index 7f484fc69f..6fbf929e47 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -11,13 +11,13 @@ import (
"github.com/stretchr/testify/require"
- env_client "github.com/smartcontractkit/chainlink-env/client"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/cdk8s/blockscout"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ env_client "github.com/smartcontractkit/chainlink-testing-framework/k8s/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go
index 8697044aa7..a3d4e37406 100644
--- a/integration-tests/chaos/automation_chaos_test.go
+++ b/integration-tests/chaos/automation_chaos_test.go
@@ -11,13 +11,13 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/chaos"
- "github.com/smartcontractkit/chainlink-env/environment"
- a "github.com/smartcontractkit/chainlink-env/pkg/alias"
- "github.com/smartcontractkit/chainlink-env/pkg/cdk8s/blockscout"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go
index cbab1bf9e7..0beccadddd 100644
--- a/integration-tests/chaos/ocr2vrf_chaos_test.go
+++ b/integration-tests/chaos/ocr2vrf_chaos_test.go
@@ -10,12 +10,12 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/chaos"
- "github.com/smartcontractkit/chainlink-env/environment"
- a "github.com/smartcontractkit/chainlink-env/pkg/alias"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go
index 0d72e3932e..b65f8bb74f 100644
--- a/integration-tests/chaos/ocr_chaos_test.go
+++ b/integration-tests/chaos/ocr_chaos_test.go
@@ -11,15 +11,15 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/chaos"
- "github.com/smartcontractkit/chainlink-env/environment"
- a "github.com/smartcontractkit/chainlink-env/pkg/alias"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
@@ -75,7 +75,7 @@ func TestOCRChaos(t *testing.T) {
// and chaos.NewNetworkPartition method (https://chaos-mesh.org/docs/simulate-network-chaos-on-kubernetes/)
// in order to regenerate Go bindings if k8s version will be updated
// you can pull new CRD spec from your current cluster and check README here
- // https://github.com/smartcontractkit/chainlink-env/blob/master/README.md
+ // https://github.com/smartcontractkit/chainlink-testing-framework/k8s/blob/master/README.md
NetworkChaosFailMajorityNetwork: {
ethereum.New(nil),
chainlink.New(0, defaultOCRSettings),
diff --git a/integration-tests/client/chainlink_config_builder.go b/integration-tests/client/chainlink_config_builder.go
index 9c1050300b..13cc1e7fe9 100644
--- a/integration-tests/client/chainlink_config_builder.go
+++ b/integration-tests/client/chainlink_config_builder.go
@@ -4,8 +4,8 @@ import (
"fmt"
"os"
- "github.com/smartcontractkit/chainlink-env/config"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/config"
)
const (
diff --git a/integration-tests/client/chainlink_k8s.go b/integration-tests/client/chainlink_k8s.go
index 4aa7c6d0fe..3fbf9eaf73 100644
--- a/integration-tests/client/chainlink_k8s.go
+++ b/integration-tests/client/chainlink_k8s.go
@@ -8,7 +8,7 @@ import (
"github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink-env/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
)
type ChainlinkK8sClient struct {
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index d3e09d94d7..c1a8cdb61c 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -20,8 +20,7 @@ require (
github.com/rs/zerolog v1.30.0
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-env v0.38.3
- github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231027132403-4898f11e80b6
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.0
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.27
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 725e05914c..77778de9d2 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2362,16 +2362,14 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
-github.com/smartcontractkit/chainlink-env v0.38.3 h1:ZtOnwkG622R0VCTxL5V09AnT/QXhlFwkGTjd0Lsfpfg=
-github.com/smartcontractkit/chainlink-env v0.38.3/go.mod h1:7z4sw/hN8TxioQCLwFqQdhK3vaOV0a22Qe99z4bRUcg=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231027132403-4898f11e80b6 h1:f1nUQ/1eUTMwNbOZK0P7P6OHvTDGQSn2KE+LtwY0rXA=
-github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231027132403-4898f11e80b6/go.mod h1:RWlmjwnjIGbQAnRfKwe02Ife82nNI3rZmdI0zgkfbyk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.0 h1:Ru7odxF0tq0FixJXM58rNZw0PvyQnRroqAInBAM83gs=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.0/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/performance/cron_test.go b/integration-tests/performance/cron_test.go
index 84a4964647..e700a66e1f 100644
--- a/integration-tests/performance/cron_test.go
+++ b/integration-tests/performance/cron_test.go
@@ -12,14 +12,14 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/logging"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go
index faaac5910d..d229f9fb3e 100644
--- a/integration-tests/performance/directrequest_test.go
+++ b/integration-tests/performance/directrequest_test.go
@@ -11,13 +11,13 @@ import (
"github.com/onsi/gomega"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go
index df3022003e..be536450a7 100644
--- a/integration-tests/performance/flux_test.go
+++ b/integration-tests/performance/flux_test.go
@@ -12,13 +12,13 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go
index 7a2cc933de..cd9818f99d 100644
--- a/integration-tests/performance/keeper_test.go
+++ b/integration-tests/performance/keeper_test.go
@@ -12,12 +12,12 @@ import (
"github.com/onsi/gomega"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- eth "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ eth "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go
index 4d875022ed..e81cc91cf7 100644
--- a/integration-tests/performance/ocr_test.go
+++ b/integration-tests/performance/ocr_test.go
@@ -10,13 +10,13 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/performance/vrf_test.go b/integration-tests/performance/vrf_test.go
index c715641692..eeaceffaaf 100644
--- a/integration-tests/performance/vrf_test.go
+++ b/integration-tests/performance/vrf_test.go
@@ -12,10 +12,10 @@ import (
"github.com/onsi/gomega"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go
index 608144eafd..697ae28ce3 100644
--- a/integration-tests/reorg/automation_reorg_test.go
+++ b/integration-tests/reorg/automation_reorg_test.go
@@ -12,11 +12,11 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/cdk8s/blockscout"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
diff --git a/integration-tests/reorg/reorg_confirmer.go b/integration-tests/reorg/reorg_confirmer.go
index 6647816c97..be535d2a6d 100644
--- a/integration-tests/reorg/reorg_confirmer.go
+++ b/integration-tests/reorg/reorg_confirmer.go
@@ -11,11 +11,11 @@ import (
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink-env/chaos"
- "github.com/smartcontractkit/chainlink-env/environment"
- a "github.com/smartcontractkit/chainlink-env/pkg/alias"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
)
// The steps are:
diff --git a/integration-tests/reorg/reorg_test.go b/integration-tests/reorg/reorg_test.go
index 74468b9253..f92becfa50 100644
--- a/integration-tests/reorg/reorg_test.go
+++ b/integration-tests/reorg/reorg_test.go
@@ -13,15 +13,15 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/logging"
- "github.com/smartcontractkit/chainlink-env/pkg/cdk8s/blockscout"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/onsi/gomega"
diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go
index 582ca17f7b..1b33cdce76 100644
--- a/integration-tests/smoke/ocr2_test.go
+++ b/integration-tests/smoke/ocr2_test.go
@@ -11,12 +11,12 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go
index 8c102f6fd2..0d6a77a115 100644
--- a/integration-tests/smoke/ocr2vrf_test.go
+++ b/integration-tests/smoke/ocr2vrf_test.go
@@ -9,10 +9,10 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- eth "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ eth "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils"
diff --git a/integration-tests/testsetups/don_evm_chain.go b/integration-tests/testsetups/don_evm_chain.go
index 545d951580..3ade7f0d69 100644
--- a/integration-tests/testsetups/don_evm_chain.go
+++ b/integration-tests/testsetups/don_evm_chain.go
@@ -6,13 +6,13 @@ import (
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
- e "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ e "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go
index 466eb97fdd..f786cca9bb 100644
--- a/integration-tests/testsetups/keeper_benchmark.go
+++ b/integration-tests/testsetups/keeper_benchmark.go
@@ -21,8 +21,8 @@ import (
"github.com/slack-go/slack"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go
index c4b1fc7ab1..ee8116f3f9 100644
--- a/integration-tests/testsetups/ocr.go
+++ b/integration-tests/testsetups/ocr.go
@@ -26,13 +26,13 @@ import (
"github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
- "github.com/smartcontractkit/chainlink-env/environment"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
+ mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
diff --git a/integration-tests/testsetups/profile.go b/integration-tests/testsetups/profile.go
index 6f978cdebe..14fe3d29ae 100644
--- a/integration-tests/testsetups/profile.go
+++ b/integration-tests/testsetups/profile.go
@@ -7,8 +7,8 @@ import (
. "github.com/onsi/gomega"
"golang.org/x/sync/errgroup"
- "github.com/smartcontractkit/chainlink-env/environment"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
"github.com/smartcontractkit/chainlink/integration-tests/client"
diff --git a/integration-tests/testsetups/vrfv2.go b/integration-tests/testsetups/vrfv2.go
index cfa26e8f27..194c7ff4e6 100644
--- a/integration-tests/testsetups/vrfv2.go
+++ b/integration-tests/testsetups/vrfv2.go
@@ -14,8 +14,8 @@ import (
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-env/environment"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
From c94240344024998e32969b24783430d8b42ab0c9 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 30 Oct 2023 12:36:30 -0400
Subject: [PATCH 031/327] MERC 1388 update telemetry module to address the
multi report structure (#10827)
* w
* Don't warn uselessly on bid/ask missing
* - Update enhancedEAmercury proto file
- Fix tests
* Genereate
* fix foundry deps
---------
Co-authored-by: george-dorin
Co-authored-by: Rens Rooimans
---
core/services/ocr2/delegate.go | 2 +-
core/services/ocrcommon/telemetry.go | 189 +++++++---
core/services/ocrcommon/telemetry_test.go | 211 ++++++++---
.../relay/evm/mercury/v1/data_source.go | 37 +-
.../relay/evm/mercury/v2/data_source.go | 46 +--
.../relay/evm/mercury/v3/data_source.go | 47 +--
.../telem/telem_enhanced_ea_mercury.pb.go | 327 +++++++++++-------
.../telem/telem_enhanced_ea_mercury.proto | 33 +-
tools/flakeytests/coverage.txt | 93 +++++
9 files changed, 698 insertions(+), 287 deletions(-)
create mode 100644 tools/flakeytests/coverage.txt
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index ef1ae7c588..efb6f04fd3 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -551,7 +551,7 @@ func (d *Delegate) newServicesMercury(
mercuryServices, err2 := mercury.NewServices(jb, mercuryProvider, d.pipelineRunner, runResults, lggr, oracleArgsNoPlugin, d.cfg.JobPipeline(), chEnhancedTelem, chain, d.mercuryORM, (mercuryutils.FeedID)(*spec.FeedID))
- if ocrcommon.ShouldCollectEnhancedTelemetryMercury(&jb) {
+ if ocrcommon.ShouldCollectEnhancedTelemetryMercury(jb) {
enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, chEnhancedTelem, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(spec.FeedID.String(), synchronization.EnhancedEAMercury, rid.Network, rid.ChainID), lggr.Named("EnhancedTelemetryMercury"))
mercuryServices = append(mercuryServices, enhancedTelemService)
}
diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go
index 5277143c8b..29d1ad92e4 100644
--- a/core/services/ocrcommon/telemetry.go
+++ b/core/services/ocrcommon/telemetry.go
@@ -7,7 +7,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
-
"github.com/smartcontractkit/libocr/commontypes"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"google.golang.org/protobuf/proto"
@@ -15,10 +14,13 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
"github.com/smartcontractkit/chainlink/v2/core/utils"
relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
)
type eaTelemetry struct {
@@ -36,9 +38,15 @@ type EnhancedTelemetryData struct {
}
type EnhancedTelemetryMercuryData struct {
- TaskRunResults pipeline.TaskRunResults
- Observation relaymercuryv1.Observation
- RepTimestamp ocrtypes.ReportTimestamp
+ V1Observation *relaymercuryv1.Observation
+ V2Observation *relaymercuryv2.Observation
+ V3Observation *relaymercuryv3.Observation
+ TaskRunResults pipeline.TaskRunResults
+ RepTimestamp ocrtypes.ReportTimestamp
+ FeedVersion mercuryutils.FeedVersion
+ FetchMaxFinalizedTimestamp bool
+ IsLinkFeed bool
+ IsNativeFeed bool
}
type EnhancedTelemetryService[T EnhancedTelemetryData | EnhancedTelemetryMercuryData] struct {
@@ -69,13 +77,13 @@ func (e *EnhancedTelemetryService[T]) Start(context.Context) error {
for {
select {
case t := <-e.chTelem:
- switch any(t).(type) {
+ switch v := any(t).(type) {
case EnhancedTelemetryData:
- s := any(t).(EnhancedTelemetryData)
- e.collectEATelemetry(s.TaskRunResults, s.FinalResults, s.RepTimestamp)
+ e.collectEATelemetry(v.TaskRunResults, v.FinalResults, v.RepTimestamp)
case EnhancedTelemetryMercuryData:
- s := any(t).(EnhancedTelemetryMercuryData)
- e.collectMercuryEnhancedTelemetry(s.Observation, s.TaskRunResults, s.RepTimestamp)
+ e.collectMercuryEnhancedTelemetry(v)
+ default:
+ e.lggr.Errorf("unrecognised telemetry data type: %T", t)
}
case <-e.chDone:
return
@@ -224,14 +232,19 @@ func (e *EnhancedTelemetryService[T]) collectAndSend(trrs *pipeline.TaskRunResul
continue
}
+ if trr.Result.Error != nil {
+ e.lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", trr.Result.Error)
+ continue
+ }
bridgeRawResponse, ok := trr.Result.Value.(string)
if !ok {
- e.lggr.Warnf("cannot get bridge response from bridge task, job %d, id %s", e.job.ID, trr.Task.DotID())
+ e.lggr.Warnf("cannot parse bridge response from bridge task, job %d, id %s: expected string, got: %v (type %T)", e.job.ID, trr.Task.DotID(), trr.Result.Value, trr.Result.Value)
continue
}
eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse))
if err != nil {
e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job %d, id %s", e.job.ID, trr.Task.DotID()), "err", err)
+ continue
}
value := e.getParsedValue(trrs, trr)
@@ -254,7 +267,7 @@ func (e *EnhancedTelemetryService[T]) collectAndSend(trrs *pipeline.TaskRunResul
bytes, err := proto.Marshal(t)
if err != nil {
- e.lggr.Warnf("protobuf marshal failed %v", err.Error())
+ e.lggr.Warnw("protobuf marshal failed", "err", err)
continue
}
@@ -264,14 +277,81 @@ func (e *EnhancedTelemetryService[T]) collectAndSend(trrs *pipeline.TaskRunResul
// collectMercuryEnhancedTelemetry checks if enhanced telemetry should be collected, fetches the information needed and
// sends the telemetry
-func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(obs relaymercuryv1.Observation, trrs pipeline.TaskRunResults, repts ocrtypes.ReportTimestamp) {
+func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d EnhancedTelemetryMercuryData) {
if e.monitoringEndpoint == nil {
return
}
- obsBenchmarkPrice, obsBid, obsAsk, obsBlockNum, obsBlockHash, obsBlockTimestamp := e.getFinalValues(obs)
+ // v1 fields
+ var bn int64
+ var bh string
+ var bt uint64
+ // v1+v2+v3 fields
+ bp := big.NewInt(0)
+ //v1+v3 fields
+ bid := big.NewInt(0)
+ ask := big.NewInt(0)
+ // v2+v3 fields
+ var mfts, lp, np int64
+
+ switch {
+ case d.V1Observation != nil:
+ obs := *d.V1Observation
+ if obs.CurrentBlockNum.Err == nil {
+ bn = obs.CurrentBlockNum.Val
+ }
+ if obs.CurrentBlockHash.Err == nil {
+ bh = common.BytesToHash(obs.CurrentBlockHash.Val).Hex()
+ }
+ if obs.CurrentBlockTimestamp.Err == nil {
+ bt = obs.CurrentBlockTimestamp.Val
+ }
+ if obs.BenchmarkPrice.Err == nil && obs.BenchmarkPrice.Val != nil {
+ bp = obs.BenchmarkPrice.Val
+ }
+ if obs.Bid.Err == nil && obs.Bid.Val != nil {
+ bid = obs.Bid.Val
+ }
+ if obs.Ask.Err == nil && obs.Ask.Val != nil {
+ ask = obs.Ask.Val
+ }
+ case d.V2Observation != nil:
+ obs := *d.V2Observation
+ if obs.MaxFinalizedTimestamp.Err == nil {
+ mfts = obs.MaxFinalizedTimestamp.Val
+ }
+ if obs.LinkPrice.Err == nil && obs.LinkPrice.Val != nil {
+ lp = obs.LinkPrice.Val.Int64()
+ }
+ if obs.NativePrice.Err == nil && obs.NativePrice.Val != nil {
+ np = obs.NativePrice.Val.Int64()
+ }
+ if obs.BenchmarkPrice.Err == nil && obs.BenchmarkPrice.Val != nil {
+ bp = obs.BenchmarkPrice.Val
+ }
+ case d.V3Observation != nil:
+ obs := *d.V3Observation
+ if obs.MaxFinalizedTimestamp.Err == nil {
+ mfts = obs.MaxFinalizedTimestamp.Val
+ }
+ if obs.LinkPrice.Err == nil && obs.LinkPrice.Val != nil {
+ lp = obs.LinkPrice.Val.Int64()
+ }
+ if obs.NativePrice.Err == nil && obs.NativePrice.Val != nil {
+ np = obs.NativePrice.Val.Int64()
+ }
+ if obs.BenchmarkPrice.Err == nil && obs.BenchmarkPrice.Val != nil {
+ bp = obs.BenchmarkPrice.Val
+ }
+ if obs.Bid.Err == nil && obs.Bid.Val != nil {
+ bid = obs.Bid.Val
+ }
+ if obs.Ask.Err == nil && obs.Ask.Val != nil {
+ ask = obs.Ask.Val
+ }
+ }
- for _, trr := range trrs {
+ for _, trr := range d.TaskRunResults {
if trr.Task.Type() != pipeline.TaskTypeBridge {
continue
}
@@ -288,16 +368,19 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(obs relaym
}
assetSymbol := e.getAssetSymbolFromRequestData(bridgeTask.RequestData)
- benchmarkPrice, bidPrice, askPrice := e.getPricesFromResults(trr, &trrs)
+
+ benchmarkPrice, bidPrice, askPrice := e.getPricesFromResults(trr, d.TaskRunResults, d.FeedVersion)
t := &telem.EnhancedEAMercury{
DataSource: eaTelem.DataSource,
DpBenchmarkPrice: benchmarkPrice,
DpBid: bidPrice,
DpAsk: askPrice,
- CurrentBlockNumber: obsBlockNum,
- CurrentBlockHash: common.BytesToHash(obsBlockHash).String(),
- CurrentBlockTimestamp: obsBlockTimestamp,
+ CurrentBlockNumber: bn,
+ CurrentBlockHash: bh,
+ CurrentBlockTimestamp: bt,
+ FetchMaxFinalizedTimestamp: d.FetchMaxFinalizedTimestamp,
+ MaxFinalizedTimestamp: mfts,
BridgeTaskRunStartedTimestamp: trr.CreatedAt.UnixMilli(),
BridgeTaskRunEndedTimestamp: trr.FinishedAt.Time.UnixMilli(),
ProviderRequestedTimestamp: eaTelem.ProviderRequestedTimestamp,
@@ -305,16 +388,21 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(obs relaym
ProviderDataStreamEstablished: eaTelem.ProviderDataStreamEstablished,
ProviderIndicatedTime: eaTelem.ProviderIndicatedTime,
Feed: e.job.OCR2OracleSpec.FeedID.Hex(),
- ObservationBenchmarkPrice: obsBenchmarkPrice.Int64(), //Deprecated: observation value will not fit in int64, we will use the string equivalent field ObservationBenchmarkPriceString
- ObservationBid: obsBid.Int64(), //Deprecated: observation value will not fit in int64, we will use the string equivalent field ObservationBidString
- ObservationAsk: obsAsk.Int64(), //Deprecated: observation value will not fit in int64, we will use the string equivalent field ObservationAskString
- ConfigDigest: repts.ConfigDigest.Hex(),
- Round: int64(repts.Round),
- Epoch: int64(repts.Epoch),
+ ObservationBenchmarkPrice: bp.Int64(),
+ ObservationBid: bid.Int64(),
+ ObservationAsk: ask.Int64(),
+ ObservationBenchmarkPriceString: stringOrEmpty(bp),
+ ObservationBidString: stringOrEmpty(bid),
+ ObservationAskString: stringOrEmpty(ask),
+ IsLinkFeed: d.IsLinkFeed,
+ LinkPrice: lp,
+ IsNativeFeed: d.IsNativeFeed,
+ NativePrice: np,
+ ConfigDigest: d.RepTimestamp.ConfigDigest.Hex(),
+ Round: int64(d.RepTimestamp.Round),
+ Epoch: int64(d.RepTimestamp.Epoch),
AssetSymbol: assetSymbol,
- ObservationBenchmarkPriceString: obsBenchmarkPrice.String(),
- ObservationBidString: obsBid.String(),
- ObservationAskString: obsAsk.String(),
+ Version: uint32(d.FeedVersion),
}
bytes, err := proto.Marshal(t)
@@ -347,19 +435,19 @@ func (e *EnhancedTelemetryService[T]) getAssetSymbolFromRequestData(requestData
}
// ShouldCollectEnhancedTelemetryMercury checks if enhanced telemetry should be collected and sent
-func ShouldCollectEnhancedTelemetryMercury(job *job.Job) bool {
- if job.Type.String() == pipeline.OffchainReporting2JobType && job.OCR2OracleSpec != nil {
- return job.OCR2OracleSpec.CaptureEATelemetry
+func ShouldCollectEnhancedTelemetryMercury(jb job.Job) bool {
+ if jb.Type.String() == pipeline.OffchainReporting2JobType && jb.OCR2OracleSpec != nil {
+ return jb.OCR2OracleSpec.CaptureEATelemetry
}
return false
}
// getPricesFromResults parses the pipeline.TaskRunResults for pipeline.TaskTypeJSONParse and gets the benchmarkPrice,
// bid and ask. This functions expects the pipeline.TaskRunResults to be correctly ordered
-func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.TaskRunResult, allTasks *pipeline.TaskRunResults) (float64, float64, float64) {
+func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.TaskRunResult, allTasks pipeline.TaskRunResults, mercuryVersion mercuryutils.FeedVersion) (float64, float64, float64) {
var benchmarkPrice, askPrice, bidPrice float64
var err error
- //We rely on task results to be sorted in the correct order
+ // We rely on task results to be sorted in the correct order
benchmarkPriceTask := allTasks.GetNextTaskOf(startTask)
if benchmarkPriceTask == nil {
e.lggr.Warnf("cannot parse enhanced EA telemetry benchmark price, task is nil, job %d, id %s", e.job.ID)
@@ -376,12 +464,18 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta
}
}
+ // mercury version 2 only supports benchmarkPrice
+ if mercuryVersion == 2 {
+ return benchmarkPrice, 0, 0
+ }
+
bidTask := allTasks.GetNextTaskOf(*benchmarkPriceTask)
if bidTask == nil {
e.lggr.Warnf("cannot parse enhanced EA telemetry bid price, task is nil, job %d, id %s", e.job.ID)
return benchmarkPrice, 0, 0
}
- if bidTask.Task.Type() == pipeline.TaskTypeJSONParse {
+
+ if bidTask != nil && bidTask.Task.Type() == pipeline.TaskTypeJSONParse {
if bidTask.Result.Error != nil {
e.lggr.Warnw(fmt.Sprintf("got error for enhanced EA telemetry bid price, job %d, id %s: %s", e.job.ID, bidTask.Task.DotID(), bidTask.Result.Error), "err", bidTask.Result.Error)
} else {
@@ -397,7 +491,7 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta
e.lggr.Warnf("cannot parse enhanced EA telemetry ask price, task is nil, job %d, id %s", e.job.ID)
return benchmarkPrice, bidPrice, 0
}
- if askTask.Task.Type() == pipeline.TaskTypeJSONParse {
+ if askTask != nil && askTask.Task.Type() == pipeline.TaskTypeJSONParse {
if bidTask.Result.Error != nil {
e.lggr.Warnw(fmt.Sprintf("got error for enhanced EA telemetry ask price, job %d, id %s: %s", e.job.ID, askTask.Task.DotID(), askTask.Result.Error), "err", askTask.Result.Error)
} else {
@@ -411,23 +505,11 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta
return benchmarkPrice, bidPrice, askPrice
}
-// getFinalValues runs a parse on the pipeline.TaskRunResults and returns the values
-func (e *EnhancedTelemetryService[T]) getFinalValues(obs relaymercuryv1.Observation) (*big.Int, *big.Int, *big.Int, int64, []byte, uint64) {
- benchmarkPrice := big.NewInt(0)
- bid := big.NewInt(0)
- ask := big.NewInt(0)
-
- if obs.BenchmarkPrice.Val != nil {
- benchmarkPrice = obs.BenchmarkPrice.Val
- }
- if obs.Bid.Val != nil {
- bid = obs.Bid.Val
- }
- if obs.Ask.Val != nil {
- ask = obs.Ask.Val
+// MaybeEnqueueEnhancedTelem sends data to the telemetry channel for processing
+func MaybeEnqueueEnhancedTelem(jb job.Job, ch chan<- EnhancedTelemetryMercuryData, data EnhancedTelemetryMercuryData) {
+ if ShouldCollectEnhancedTelemetryMercury(jb) {
+ EnqueueEnhancedTelem[EnhancedTelemetryMercuryData](ch, data)
}
-
- return benchmarkPrice, bid, ask, obs.CurrentBlockNum.Val, obs.CurrentBlockHash.Val, obs.CurrentBlockTimestamp.Val
}
// EnqueueEnhancedTelem sends data to the telemetry channel for processing
@@ -447,3 +529,10 @@ func getResultFloat64(task *pipeline.TaskRunResult) (float64, error) {
resultFloat64, _ := result.Float64()
return resultFloat64, nil
}
+
+func stringOrEmpty(n *big.Int) string {
+ if n.Cmp(big.NewInt(0)) == 0 {
+ return ""
+ }
+ return n.String()
+}
diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go
index 5d1494a038..e6a798780b 100644
--- a/core/services/ocrcommon/telemetry_test.go
+++ b/core/services/ocrcommon/telemetry_test.go
@@ -15,6 +15,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
mercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
+ mercury_v2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -361,7 +362,7 @@ func TestCollectAndSend(t *testing.T) {
wg.Wait()
assert.Equal(t, logs.Len(), 2)
- assert.Contains(t, logs.All()[0].Message, "cannot get bridge response from bridge task")
+ assert.Contains(t, logs.All()[0].Message, "cannot parse bridge response from bridge task")
badTrrs = &pipeline.TaskRunResults{
pipeline.TaskRunResult{
@@ -372,20 +373,19 @@ func TestCollectAndSend(t *testing.T) {
Value: "[]",
},
}}
- wg.Add(1)
enhancedTelemChan <- EnhancedTelemetryData{
TaskRunResults: *badTrrs,
FinalResults: *finalResult,
RepTimestamp: observationTimestamp,
}
wg.Wait()
- assert.Equal(t, logs.Len(), 4)
- assert.Contains(t, logs.All()[2].Message, "cannot parse EA telemetry")
- assert.Contains(t, logs.All()[3].Message, "cannot get json parse value")
+ assert.Equal(t, 2, logs.Len())
+ assert.Contains(t, logs.All()[0].Message, "cannot parse bridge response from bridge task")
+ assert.Contains(t, logs.All()[1].Message, "cannot get json parse value")
doneCh <- struct{}{}
}
-var trrsMercury = pipeline.TaskRunResults{
+var trrsMercuryV1 = pipeline.TaskRunResults{
pipeline.TaskRunResult{
Task: &pipeline.BridgeTask{
BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0),
@@ -421,32 +421,24 @@ var trrsMercury = pipeline.TaskRunResults{
},
}
-func TestGetFinalValues(t *testing.T) {
- e := EnhancedTelemetryService[EnhancedTelemetryMercuryData]{}
- o := mercuryv1.Observation{
- BenchmarkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(111111)},
- Bid: mercury.ObsResult[*big.Int]{Val: big.NewInt(222222)},
- Ask: mercury.ObsResult[*big.Int]{Val: big.NewInt(333333)},
- CurrentBlockNum: mercury.ObsResult[int64]{Val: 123456789},
- CurrentBlockHash: mercury.ObsResult[[]byte]{Val: common.HexToHash("0x123321").Bytes()},
- CurrentBlockTimestamp: mercury.ObsResult[uint64]{Val: 987654321},
- }
-
- benchmarkPrice, bid, ask, blockNr, blockHash, blockTimestamp := e.getFinalValues(o)
- require.Equal(t, benchmarkPrice, big.NewInt(111111))
- require.Equal(t, bid, big.NewInt(222222))
- require.Equal(t, ask, big.NewInt(333333))
- require.Equal(t, blockNr, int64(123456789))
- require.Equal(t, blockHash, common.HexToHash("0x123321").Bytes())
- require.Equal(t, blockTimestamp, uint64(987654321))
-
- benchmarkPrice, bid, ask, blockNr, blockHash, blockTimestamp = e.getFinalValues(mercuryv1.Observation{})
- require.Equal(t, benchmarkPrice, big.NewInt(0))
- require.Equal(t, bid, big.NewInt(0))
- require.Equal(t, ask, big.NewInt(0))
- require.Equal(t, blockNr, int64(0))
- require.Nil(t, blockHash)
- require.Equal(t, blockTimestamp, uint64(0))
+var trrsMercuryV2 = pipeline.TaskRunResults{
+ pipeline.TaskRunResult{
+ Task: &pipeline.BridgeTask{
+ BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0),
+ RequestData: `{"data":{"to":"LINK","from":"USD"}}`,
+ },
+ Result: pipeline.Result{
+ Value: bridgeResponse,
+ },
+ },
+ pipeline.TaskRunResult{
+ Task: &pipeline.JSONParseTask{
+ BaseTask: pipeline.NewBaseTask(1, "ds1_benchmark", nil, nil, 1),
+ },
+ Result: pipeline.Result{
+ Value: float64(123456.123456),
+ },
+ },
}
func TestGetPricesFromResults(t *testing.T) {
@@ -458,25 +450,25 @@ func TestGetPricesFromResults(t *testing.T) {
},
}
- benchmarkPrice, bid, ask := e.getPricesFromResults(trrsMercury[0], &trrsMercury)
+ benchmarkPrice, bid, ask := e.getPricesFromResults(trrsMercuryV1[0], trrsMercuryV1, 1)
require.Equal(t, 123456.123456, benchmarkPrice)
require.Equal(t, 1234567.1234567, bid)
require.Equal(t, float64(321123), ask)
- benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercury[0], &pipeline.TaskRunResults{})
+ benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercuryV1[0], pipeline.TaskRunResults{}, 1)
require.Equal(t, float64(0), benchmarkPrice)
require.Equal(t, float64(0), bid)
require.Equal(t, float64(0), ask)
require.Equal(t, 1, logs.Len())
require.Contains(t, logs.All()[0].Message, "cannot parse enhanced EA telemetry")
- tt := trrsMercury[:2]
- e.getPricesFromResults(trrsMercury[0], &tt)
+ tt := trrsMercuryV1[:2]
+ e.getPricesFromResults(trrsMercuryV1[0], tt, 1)
require.Equal(t, 2, logs.Len())
require.Contains(t, logs.All()[1].Message, "cannot parse enhanced EA telemetry bid price, task is nil")
- tt = trrsMercury[:3]
- e.getPricesFromResults(trrsMercury[0], &tt)
+ tt = trrsMercuryV1[:3]
+ e.getPricesFromResults(trrsMercuryV1[0], tt, 1)
require.Equal(t, 3, logs.Len())
require.Contains(t, logs.All()[2].Message, "cannot parse enhanced EA telemetry ask price, task is nil")
@@ -513,7 +505,7 @@ func TestGetPricesFromResults(t *testing.T) {
Value: nil,
},
}}
- benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercury[0], &trrs2)
+ benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercuryV1[0], trrs2, 3)
require.Equal(t, benchmarkPrice, float64(0))
require.Equal(t, bid, float64(0))
require.Equal(t, ask, float64(0))
@@ -521,11 +513,16 @@ func TestGetPricesFromResults(t *testing.T) {
require.Contains(t, logs.All()[3].Message, "cannot parse enhanced EA telemetry benchmark price")
require.Contains(t, logs.All()[4].Message, "cannot parse enhanced EA telemetry bid price")
require.Contains(t, logs.All()[5].Message, "cannot parse enhanced EA telemetry ask price")
+
+ benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercuryV1[0], trrsMercuryV2, 2)
+ require.Equal(t, 123456.123456, benchmarkPrice)
+ require.Equal(t, float64(0), bid)
+ require.Equal(t, float64(0), ask)
}
func TestShouldCollectEnhancedTelemetryMercury(t *testing.T) {
- j := &job.Job{
+ j := job.Job{
Type: job.Type(pipeline.OffchainReporting2JobType),
OCR2OracleSpec: &job.OCR2OracleSpec{
CaptureEATelemetry: true,
@@ -547,7 +544,7 @@ func TestGetAssetSymbolFromRequestData(t *testing.T) {
require.Equal(t, e.getAssetSymbolFromRequestData(reqData), "USD/LINK")
}
-func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
+func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) {
wg := sync.WaitGroup{}
ingressClient := mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
@@ -581,8 +578,8 @@ func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
wg.Add(1)
chTelem <- EnhancedTelemetryMercuryData{
- TaskRunResults: trrsMercury,
- Observation: mercuryv1.Observation{
+ TaskRunResults: trrsMercuryV1,
+ V1Observation: &mercuryv1.Observation{
BenchmarkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(111111)},
Bid: mercury.ObsResult[*big.Int]{Val: big.NewInt(222222)},
Ask: mercury.ObsResult[*big.Int]{Val: big.NewInt(333333)},
@@ -605,8 +602,8 @@ func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
CurrentBlockNumber: 123456789,
CurrentBlockHash: common.HexToHash("0x123321").String(),
CurrentBlockTimestamp: 987654321,
- BridgeTaskRunStartedTimestamp: trrsMercury[0].CreatedAt.UnixMilli(),
- BridgeTaskRunEndedTimestamp: trrsMercury[0].FinishedAt.Time.UnixMilli(),
+ BridgeTaskRunStartedTimestamp: trrsMercuryV1[0].CreatedAt.UnixMilli(),
+ BridgeTaskRunEndedTimestamp: trrsMercuryV1[0].FinishedAt.Time.UnixMilli(),
ProviderRequestedTimestamp: 92233720368547760,
ProviderReceivedTimestamp: -92233720368547760,
ProviderDataStreamEstablished: 1,
@@ -637,7 +634,7 @@ func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
Value: nil,
}},
},
- Observation: mercuryv1.Observation{},
+ V1Observation: &mercuryv1.Observation{},
RepTimestamp: types.ReportTimestamp{
ConfigDigest: types.ConfigDigest{2},
Epoch: 11,
@@ -645,10 +642,10 @@ func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
},
}
wg.Add(1)
- trrsMercury[0].Result.Value = ""
+ trrsMercuryV1[0].Result.Value = ""
chTelem <- EnhancedTelemetryMercuryData{
- TaskRunResults: trrsMercury,
- Observation: mercuryv1.Observation{},
+ TaskRunResults: trrsMercuryV1,
+ V1Observation: &mercuryv1.Observation{},
RepTimestamp: types.ReportTimestamp{
ConfigDigest: types.ConfigDigest{2},
Epoch: 11,
@@ -662,3 +659,119 @@ func TestCollectMercuryEnhancedTelemetry(t *testing.T) {
require.Contains(t, logs.All()[1].Message, "cannot parse EA telemetry")
chDone <- struct{}{}
}
+
+func TestCollectMercuryEnhancedTelemetryV2(t *testing.T) {
+ wg := sync.WaitGroup{}
+ ingressClient := mocks.NewTelemetryService(t)
+ ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
+ monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("0xa", synchronization.EnhancedEAMercury, "test-network", "test-chainID")
+
+ var sentMessage []byte
+ ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) {
+ sentMessage = args[1].([]byte)
+ wg.Done()
+ })
+
+ lggr, logs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ chTelem := make(chan EnhancedTelemetryMercuryData, 100)
+ chDone := make(chan struct{})
+ feedID := common.HexToHash("0x111")
+ e := EnhancedTelemetryService[EnhancedTelemetryMercuryData]{
+ chDone: chDone,
+ chTelem: chTelem,
+ job: &job.Job{
+ Type: job.Type(pipeline.OffchainReporting2JobType),
+ OCR2OracleSpec: &job.OCR2OracleSpec{
+ CaptureEATelemetry: true,
+ FeedID: &feedID,
+ },
+ },
+ lggr: lggr,
+ monitoringEndpoint: monitoringEndpoint,
+ }
+ require.NoError(t, e.Start(testutils.Context(t)))
+
+ wg.Add(1)
+
+ chTelem <- EnhancedTelemetryMercuryData{
+ TaskRunResults: trrsMercuryV2,
+ V2Observation: &mercury_v2.Observation{
+ BenchmarkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(111111)},
+ MaxFinalizedTimestamp: mercury.ObsResult[int64]{Val: 321},
+ LinkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(4321)},
+ NativePrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(54321)},
+ },
+ RepTimestamp: types.ReportTimestamp{
+ ConfigDigest: types.ConfigDigest{2},
+ Epoch: 11,
+ Round: 22,
+ },
+ }
+
+ expectedTelemetry := telem.EnhancedEAMercury{
+ DataSource: "data-source-name",
+ DpBenchmarkPrice: 123456.123456,
+ CurrentBlockNumber: 0,
+ CurrentBlockHash: "",
+ CurrentBlockTimestamp: 0,
+ BridgeTaskRunStartedTimestamp: trrsMercuryV1[0].CreatedAt.UnixMilli(),
+ BridgeTaskRunEndedTimestamp: trrsMercuryV1[0].FinishedAt.Time.UnixMilli(),
+ ProviderRequestedTimestamp: 92233720368547760,
+ ProviderReceivedTimestamp: -92233720368547760,
+ ProviderDataStreamEstablished: 1,
+ ProviderIndicatedTime: -123456789,
+ Feed: common.HexToHash("0x111").String(),
+ ObservationBenchmarkPrice: 111111,
+ ObservationBid: 0,
+ ObservationAsk: 0,
+ ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000",
+ Round: 22,
+ Epoch: 11,
+ AssetSymbol: "USD/LINK",
+ ObservationBenchmarkPriceString: "111111",
+ MaxFinalizedTimestamp: 321,
+ LinkPrice: 4321,
+ NativePrice: 54321,
+ }
+
+ expectedMessage, _ := proto.Marshal(&expectedTelemetry)
+ wg.Wait()
+
+ require.Equal(t, expectedMessage, sentMessage)
+
+ chTelem <- EnhancedTelemetryMercuryData{
+ TaskRunResults: pipeline.TaskRunResults{
+ pipeline.TaskRunResult{Task: &pipeline.BridgeTask{
+ BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0),
+ },
+ Result: pipeline.Result{
+ Value: nil,
+ }},
+ },
+ V2Observation: &mercury_v2.Observation{},
+ RepTimestamp: types.ReportTimestamp{
+ ConfigDigest: types.ConfigDigest{2},
+ Epoch: 11,
+ Round: 22,
+ },
+ }
+ wg.Add(1)
+ trrsMercuryV2[0].Result.Value = ""
+ chTelem <- EnhancedTelemetryMercuryData{
+ TaskRunResults: trrsMercuryV2,
+ V2Observation: &mercury_v2.Observation{},
+ RepTimestamp: types.ReportTimestamp{
+ ConfigDigest: types.ConfigDigest{2},
+ Epoch: 11,
+ Round: 22,
+ },
+ }
+
+ wg.Wait()
+ require.Equal(t, 4, logs.Len())
+ require.Contains(t, logs.All()[0].Message, "cannot parse enhanced EA telemetry bid price")
+ require.Contains(t, logs.All()[1].Message, "cannot get bridge response from bridge task")
+ require.Contains(t, logs.All()[2].Message, "cannot parse EA telemetry")
+ require.Contains(t, logs.All()[3].Message, "cannot parse enhanced EA telemetry bid price")
+ chDone <- struct{}{}
+}
diff --git a/core/services/relay/evm/mercury/v1/data_source.go b/core/services/relay/evm/mercury/v1/data_source.go
index 5c1f55ddab..d225dbee68 100644
--- a/core/services/relay/evm/mercury/v1/data_source.go
+++ b/core/services/relay/evm/mercury/v1/data_source.go
@@ -13,14 +13,14 @@ import (
relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
-
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/types"
+ mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/reportcodec"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -59,7 +59,7 @@ func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec
return &datasource{pr, jb, spec, lggr, rr, orm, reportcodec.ReportCodec{}, feedID, sync.RWMutex{}, enhancedTelemChan, chainHeadTracker, fetcher, initialBlockNumber}
}
-func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedBlockNum bool) (obs relaymercuryv1.Observation, err error) {
+func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedBlockNum bool) (obs relaymercuryv1.Observation, pipelineExecutionErr error) {
// setCurrentBlock must come first, along with observationTimestamp, to
// avoid front-running
ds.setCurrentBlock(ctx, &obs)
@@ -116,9 +116,9 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
go func() {
defer wg.Done()
var run *pipeline.Run
- run, trrs, err = ds.executeRun(ctx)
- if err != nil {
- err = fmt.Errorf("Observe failed while executing run: %w", err)
+ run, trrs, pipelineExecutionErr = ds.executeRun(ctx)
+ if pipelineExecutionErr != nil {
+ pipelineExecutionErr = fmt.Errorf("Observe failed while executing run: %w", pipelineExecutionErr)
return
}
select {
@@ -137,27 +137,30 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}
var parsed parseOutput
- parsed, err = ds.parse(finaltrrs)
- if err != nil {
- err = fmt.Errorf("Observe failed while parsing run results: %w", err)
+ parsed, pipelineExecutionErr = ds.parse(finaltrrs)
+ if pipelineExecutionErr != nil {
+ pipelineExecutionErr = fmt.Errorf("Observe failed while parsing run results: %w", pipelineExecutionErr)
return
}
obs.BenchmarkPrice = parsed.benchmarkPrice
obs.Bid = parsed.bid
obs.Ask = parsed.ask
}()
- wg.Wait()
- if ocrcommon.ShouldCollectEnhancedTelemetryMercury(&ds.jb) {
- ocrcommon.EnqueueEnhancedTelem(ds.chEnhancedTelem, ocrcommon.EnhancedTelemetryMercuryData{
- TaskRunResults: trrs,
- Observation: obs,
- RepTimestamp: repts,
- })
+ wg.Wait()
+ if pipelineExecutionErr != nil {
+ return
}
- return obs, err
+ ocrcommon.MaybeEnqueueEnhancedTelem(ds.jb, ds.chEnhancedTelem, ocrcommon.EnhancedTelemetryMercuryData{
+ V1Observation: &obs,
+ TaskRunResults: trrs,
+ RepTimestamp: repts,
+ FeedVersion: mercuryutils.REPORT_V1,
+ })
+
+ return obs, nil
}
func toBigInt(val interface{}) (*big.Int, error) {
diff --git a/core/services/relay/evm/mercury/v2/data_source.go b/core/services/relay/evm/mercury/v2/data_source.go
index 10c8839a3c..17bc4a6670 100644
--- a/core/services/relay/evm/mercury/v2/data_source.go
+++ b/core/services/relay/evm/mercury/v2/data_source.go
@@ -58,7 +58,7 @@ func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec
return &datasource{pr, jb, spec, feedID, lggr, rr, orm, reportcodec.ReportCodec{}, fetcher, linkFeedID, nativeFeedID, sync.RWMutex{}, enhancedTelemChan}
}
-func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedTimestamp bool) (obs relaymercuryv2.Observation, err error) {
+func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedTimestamp bool) (obs relaymercuryv2.Observation, pipelineExecutionErr error) {
var wg sync.WaitGroup
ctx, cancel := context.WithCancel(ctx)
@@ -80,15 +80,15 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}()
}
+ var trrs pipeline.TaskRunResults
wg.Add(1)
go func() {
defer wg.Done()
- var trrs pipeline.TaskRunResults
var run *pipeline.Run
- run, trrs, err = ds.executeRun(ctx)
- if err != nil {
+ run, trrs, pipelineExecutionErr = ds.executeRun(ctx)
+ if pipelineExecutionErr != nil {
cancel()
- err = fmt.Errorf("Observe failed while executing run: %w", err)
+ pipelineExecutionErr = fmt.Errorf("Observe failed while executing run: %w", pipelineExecutionErr)
return
}
select {
@@ -98,12 +98,12 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}
var parsed parseOutput
- parsed, err = ds.parse(trrs)
- if err != nil {
+ parsed, pipelineExecutionErr = ds.parse(trrs)
+ if pipelineExecutionErr != nil {
cancel()
// This is not expected under normal circumstances
- ds.lggr.Errorw("Observe failed while parsing run results", "err", err)
- err = fmt.Errorf("Observe failed while parsing run results: %w", err)
+ ds.lggr.Errorw("Observe failed while parsing run results", "err", pipelineExecutionErr)
+ pipelineExecutionErr = fmt.Errorf("Observe failed while parsing run results: %w", pipelineExecutionErr)
return
}
obs.BenchmarkPrice = parsed.benchmarkPrice
@@ -149,11 +149,12 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
wg.Wait()
cancel()
+ if pipelineExecutionErr != nil {
+ return
+ }
+
if isLink || isNative {
- // run has now completed so it is safe to use err or benchmark price
- if err != nil {
- return
- }
+ // run has now completed so it is safe to use benchmark price
if isLink {
// This IS the LINK feed, use our observed price
obs.LinkPrice.Val, obs.LinkPrice.Err = obs.BenchmarkPrice.Val, obs.BenchmarkPrice.Err
@@ -164,16 +165,17 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}
}
- // todo: implement telemetry - https://smartcontract-it.atlassian.net/browse/MERC-1388
- // if ocrcommon.ShouldCollectEnhancedTelemetryMercury(&ds.jb) {
- // ocrcommon.EnqueueEnhancedTelem(ds.chEnhancedTelem, ocrcommon.EnhancedTelemetryMercuryData{
- // TaskRunResults: trrs,
- // Observation: obs,
- // RepTimestamp: repts,
- // })
- // }
+ ocrcommon.MaybeEnqueueEnhancedTelem(ds.jb, ds.chEnhancedTelem, ocrcommon.EnhancedTelemetryMercuryData{
+ V2Observation: &obs,
+ TaskRunResults: trrs,
+ RepTimestamp: repts,
+ FeedVersion: mercuryutils.REPORT_V2,
+ FetchMaxFinalizedTimestamp: fetchMaxFinalizedTimestamp,
+ IsLinkFeed: isLink,
+ IsNativeFeed: isNative,
+ })
- return obs, err
+ return obs, nil
}
func toBigInt(val interface{}) (*big.Int, error) {
diff --git a/core/services/relay/evm/mercury/v3/data_source.go b/core/services/relay/evm/mercury/v3/data_source.go
index 4eadfc35c2..6f2b2eb6bd 100644
--- a/core/services/relay/evm/mercury/v3/data_source.go
+++ b/core/services/relay/evm/mercury/v3/data_source.go
@@ -59,7 +59,7 @@ func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec
return &datasource{pr, jb, spec, feedID, lggr, rr, orm, reportcodec.ReportCodec{}, fetcher, linkFeedID, nativeFeedID, sync.RWMutex{}, enhancedTelemChan}
}
-func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedTimestamp bool) (obs relaymercuryv3.Observation, err error) {
+func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedTimestamp bool) (obs relaymercuryv3.Observation, pipelineExecutionErr error) {
var wg sync.WaitGroup
ctx, cancel := context.WithCancel(ctx)
@@ -81,15 +81,15 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}()
}
+ var trrs pipeline.TaskRunResults
wg.Add(1)
go func() {
defer wg.Done()
- var trrs pipeline.TaskRunResults
var run *pipeline.Run
- run, trrs, err = ds.executeRun(ctx)
- if err != nil {
+ run, trrs, pipelineExecutionErr = ds.executeRun(ctx)
+ if pipelineExecutionErr != nil {
cancel()
- err = fmt.Errorf("Observe failed while executing run: %w", err)
+ pipelineExecutionErr = fmt.Errorf("Observe failed while executing run: %w", pipelineExecutionErr)
return
}
select {
@@ -99,12 +99,12 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}
var parsed parseOutput
- parsed, err = ds.parse(trrs)
- if err != nil {
+ parsed, pipelineExecutionErr = ds.parse(trrs)
+ if pipelineExecutionErr != nil {
cancel()
// This is not expected under normal circumstances
- ds.lggr.Errorw("Observe failed while parsing run results", "err", err)
- err = fmt.Errorf("Observe failed while parsing run results: %w", err)
+ ds.lggr.Errorw("Observe failed while parsing run results", "err", pipelineExecutionErr)
+ pipelineExecutionErr = fmt.Errorf("Observe failed while parsing run results: %w", pipelineExecutionErr)
return
}
obs.BenchmarkPrice = parsed.benchmarkPrice
@@ -152,11 +152,12 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
wg.Wait()
cancel()
+ if pipelineExecutionErr != nil {
+ return
+ }
+
if isLink || isNative {
- // run has now completed so it is safe to use err or benchmark price
- if err != nil {
- return
- }
+ // run has now completed so it is safe to use benchmark price
if isLink {
// This IS the LINK feed, use our observed price
obs.LinkPrice.Val, obs.LinkPrice.Err = obs.BenchmarkPrice.Val, obs.BenchmarkPrice.Err
@@ -167,17 +168,17 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}
}
- // todo: implement telemetry https://smartcontract-it.atlassian.net/browse/MERC-1388
- // if ocrcommon.ShouldCollectEnhancedTelemetryMercury(&ds.jb) {
- // ocrcommon.EnqueueEnhancedTelem(ds.chEnhancedTelem, ocrcommon.EnhancedTelemetryMercuryData{
- // TaskRunResults: trrs,
- // Observation: obs,
- // RepTimestamp: repts,
- // })
- // }
+ ocrcommon.MaybeEnqueueEnhancedTelem(ds.jb, ds.chEnhancedTelem, ocrcommon.EnhancedTelemetryMercuryData{
+ V3Observation: &obs,
+ TaskRunResults: trrs,
+ RepTimestamp: repts,
+ FeedVersion: mercuryutils.REPORT_V3,
+ FetchMaxFinalizedTimestamp: fetchMaxFinalizedTimestamp,
+ IsLinkFeed: isLink,
+ IsNativeFeed: isNative,
+ })
- cancel()
- return obs, err
+ return obs, nil
}
func toBigInt(val interface{}) (*big.Int, error) {
diff --git a/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go b/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go
index 32c3061cc4..9cda6ef99a 100644
--- a/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go
+++ b/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go
@@ -25,30 +25,42 @@ type EnhancedEAMercury struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- DataSource string `protobuf:"bytes,1,opt,name=data_source,json=dataSource,proto3" json:"data_source,omitempty"`
- DpBenchmarkPrice float64 `protobuf:"fixed64,2,opt,name=dp_benchmark_price,json=dpBenchmarkPrice,proto3" json:"dp_benchmark_price,omitempty"`
- DpBid float64 `protobuf:"fixed64,3,opt,name=dp_bid,json=dpBid,proto3" json:"dp_bid,omitempty"`
- DpAsk float64 `protobuf:"fixed64,4,opt,name=dp_ask,json=dpAsk,proto3" json:"dp_ask,omitempty"`
- CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=current_block_number,json=currentBlockNumber,proto3" json:"current_block_number,omitempty"`
- CurrentBlockHash string `protobuf:"bytes,6,opt,name=current_block_hash,json=currentBlockHash,proto3" json:"current_block_hash,omitempty"`
- CurrentBlockTimestamp uint64 `protobuf:"varint,7,opt,name=current_block_timestamp,json=currentBlockTimestamp,proto3" json:"current_block_timestamp,omitempty"`
- BridgeTaskRunStartedTimestamp int64 `protobuf:"varint,8,opt,name=bridge_task_run_started_timestamp,json=bridgeTaskRunStartedTimestamp,proto3" json:"bridge_task_run_started_timestamp,omitempty"`
- BridgeTaskRunEndedTimestamp int64 `protobuf:"varint,9,opt,name=bridge_task_run_ended_timestamp,json=bridgeTaskRunEndedTimestamp,proto3" json:"bridge_task_run_ended_timestamp,omitempty"`
- ProviderRequestedTimestamp int64 `protobuf:"varint,10,opt,name=provider_requested_timestamp,json=providerRequestedTimestamp,proto3" json:"provider_requested_timestamp,omitempty"`
- ProviderReceivedTimestamp int64 `protobuf:"varint,11,opt,name=provider_received_timestamp,json=providerReceivedTimestamp,proto3" json:"provider_received_timestamp,omitempty"`
- ProviderDataStreamEstablished int64 `protobuf:"varint,12,opt,name=provider_data_stream_established,json=providerDataStreamEstablished,proto3" json:"provider_data_stream_established,omitempty"`
- ProviderIndicatedTime int64 `protobuf:"varint,13,opt,name=provider_indicated_time,json=providerIndicatedTime,proto3" json:"provider_indicated_time,omitempty"`
- Feed string `protobuf:"bytes,14,opt,name=feed,proto3" json:"feed,omitempty"`
- ObservationBenchmarkPrice int64 `protobuf:"varint,15,opt,name=observation_benchmark_price,json=observationBenchmarkPrice,proto3" json:"observation_benchmark_price,omitempty"`
- ObservationBid int64 `protobuf:"varint,16,opt,name=observation_bid,json=observationBid,proto3" json:"observation_bid,omitempty"`
- ObservationAsk int64 `protobuf:"varint,17,opt,name=observation_ask,json=observationAsk,proto3" json:"observation_ask,omitempty"`
- ConfigDigest string `protobuf:"bytes,18,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"`
- Round int64 `protobuf:"varint,19,opt,name=round,proto3" json:"round,omitempty"`
- Epoch int64 `protobuf:"varint,20,opt,name=epoch,proto3" json:"epoch,omitempty"`
- AssetSymbol string `protobuf:"bytes,21,opt,name=asset_symbol,json=assetSymbol,proto3" json:"asset_symbol,omitempty"`
- ObservationBenchmarkPriceString string `protobuf:"bytes,22,opt,name=observation_benchmark_price_string,json=observationBenchmarkPriceString,proto3" json:"observation_benchmark_price_string,omitempty"`
- ObservationBidString string `protobuf:"bytes,23,opt,name=observation_bid_string,json=observationBidString,proto3" json:"observation_bid_string,omitempty"`
- ObservationAskString string `protobuf:"bytes,24,opt,name=observation_ask_string,json=observationAskString,proto3" json:"observation_ask_string,omitempty"`
+ Version uint32 `protobuf:"varint,32,opt,name=version,proto3" json:"version,omitempty"`
+ DataSource string `protobuf:"bytes,1,opt,name=data_source,json=dataSource,proto3" json:"data_source,omitempty"`
+ DpBenchmarkPrice float64 `protobuf:"fixed64,2,opt,name=dp_benchmark_price,json=dpBenchmarkPrice,proto3" json:"dp_benchmark_price,omitempty"`
+ DpBid float64 `protobuf:"fixed64,3,opt,name=dp_bid,json=dpBid,proto3" json:"dp_bid,omitempty"`
+ DpAsk float64 `protobuf:"fixed64,4,opt,name=dp_ask,json=dpAsk,proto3" json:"dp_ask,omitempty"`
+ // v1 fields (block range)
+ CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=current_block_number,json=currentBlockNumber,proto3" json:"current_block_number,omitempty"`
+ CurrentBlockHash string `protobuf:"bytes,6,opt,name=current_block_hash,json=currentBlockHash,proto3" json:"current_block_hash,omitempty"`
+ CurrentBlockTimestamp uint64 `protobuf:"varint,7,opt,name=current_block_timestamp,json=currentBlockTimestamp,proto3" json:"current_block_timestamp,omitempty"`
+ // v2+v3 fields (timestamp range)
+ FetchMaxFinalizedTimestamp bool `protobuf:"varint,25,opt,name=fetch_max_finalized_timestamp,json=fetchMaxFinalizedTimestamp,proto3" json:"fetch_max_finalized_timestamp,omitempty"`
+ MaxFinalizedTimestamp int64 `protobuf:"varint,26,opt,name=max_finalized_timestamp,json=maxFinalizedTimestamp,proto3" json:"max_finalized_timestamp,omitempty"`
+ ObservationTimestamp uint32 `protobuf:"varint,27,opt,name=observation_timestamp,json=observationTimestamp,proto3" json:"observation_timestamp,omitempty"`
+ IsLinkFeed bool `protobuf:"varint,28,opt,name=is_link_feed,json=isLinkFeed,proto3" json:"is_link_feed,omitempty"`
+ LinkPrice int64 `protobuf:"varint,29,opt,name=link_price,json=linkPrice,proto3" json:"link_price,omitempty"`
+ IsNativeFeed bool `protobuf:"varint,30,opt,name=is_native_feed,json=isNativeFeed,proto3" json:"is_native_feed,omitempty"`
+ NativePrice int64 `protobuf:"varint,31,opt,name=native_price,json=nativePrice,proto3" json:"native_price,omitempty"`
+ BridgeTaskRunStartedTimestamp int64 `protobuf:"varint,8,opt,name=bridge_task_run_started_timestamp,json=bridgeTaskRunStartedTimestamp,proto3" json:"bridge_task_run_started_timestamp,omitempty"`
+ BridgeTaskRunEndedTimestamp int64 `protobuf:"varint,9,opt,name=bridge_task_run_ended_timestamp,json=bridgeTaskRunEndedTimestamp,proto3" json:"bridge_task_run_ended_timestamp,omitempty"`
+ ProviderRequestedTimestamp int64 `protobuf:"varint,10,opt,name=provider_requested_timestamp,json=providerRequestedTimestamp,proto3" json:"provider_requested_timestamp,omitempty"`
+ ProviderReceivedTimestamp int64 `protobuf:"varint,11,opt,name=provider_received_timestamp,json=providerReceivedTimestamp,proto3" json:"provider_received_timestamp,omitempty"`
+ ProviderDataStreamEstablished int64 `protobuf:"varint,12,opt,name=provider_data_stream_established,json=providerDataStreamEstablished,proto3" json:"provider_data_stream_established,omitempty"`
+ ProviderIndicatedTime int64 `protobuf:"varint,13,opt,name=provider_indicated_time,json=providerIndicatedTime,proto3" json:"provider_indicated_time,omitempty"`
+ Feed string `protobuf:"bytes,14,opt,name=feed,proto3" json:"feed,omitempty"`
+ // v1+v2+v3
+ ObservationBenchmarkPrice int64 `protobuf:"varint,15,opt,name=observation_benchmark_price,json=observationBenchmarkPrice,proto3" json:"observation_benchmark_price,omitempty"` // This value overflows, will be reserved and removed in future versions
+ ObservationBenchmarkPriceString string `protobuf:"bytes,22,opt,name=observation_benchmark_price_string,json=observationBenchmarkPriceString,proto3" json:"observation_benchmark_price_string,omitempty"`
+ // v1+v3
+ ObservationBid int64 `protobuf:"varint,16,opt,name=observation_bid,json=observationBid,proto3" json:"observation_bid,omitempty"` // This value overflows, will be reserved and removed in future versions
+ ObservationAsk int64 `protobuf:"varint,17,opt,name=observation_ask,json=observationAsk,proto3" json:"observation_ask,omitempty"` // This value overflows, will be reserved and removed in future versions
+ ObservationBidString string `protobuf:"bytes,23,opt,name=observation_bid_string,json=observationBidString,proto3" json:"observation_bid_string,omitempty"`
+ ObservationAskString string `protobuf:"bytes,24,opt,name=observation_ask_string,json=observationAskString,proto3" json:"observation_ask_string,omitempty"`
+ ConfigDigest string `protobuf:"bytes,18,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"`
+ Round int64 `protobuf:"varint,19,opt,name=round,proto3" json:"round,omitempty"`
+ Epoch int64 `protobuf:"varint,20,opt,name=epoch,proto3" json:"epoch,omitempty"`
+ AssetSymbol string `protobuf:"bytes,21,opt,name=asset_symbol,json=assetSymbol,proto3" json:"asset_symbol,omitempty"`
}
func (x *EnhancedEAMercury) Reset() {
@@ -83,6 +95,13 @@ func (*EnhancedEAMercury) Descriptor() ([]byte, []int) {
return file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDescGZIP(), []int{0}
}
+func (x *EnhancedEAMercury) GetVersion() uint32 {
+ if x != nil {
+ return x.Version
+ }
+ return 0
+}
+
func (x *EnhancedEAMercury) GetDataSource() string {
if x != nil {
return x.DataSource
@@ -132,6 +151,55 @@ func (x *EnhancedEAMercury) GetCurrentBlockTimestamp() uint64 {
return 0
}
+func (x *EnhancedEAMercury) GetFetchMaxFinalizedTimestamp() bool {
+ if x != nil {
+ return x.FetchMaxFinalizedTimestamp
+ }
+ return false
+}
+
+func (x *EnhancedEAMercury) GetMaxFinalizedTimestamp() int64 {
+ if x != nil {
+ return x.MaxFinalizedTimestamp
+ }
+ return 0
+}
+
+func (x *EnhancedEAMercury) GetObservationTimestamp() uint32 {
+ if x != nil {
+ return x.ObservationTimestamp
+ }
+ return 0
+}
+
+func (x *EnhancedEAMercury) GetIsLinkFeed() bool {
+ if x != nil {
+ return x.IsLinkFeed
+ }
+ return false
+}
+
+func (x *EnhancedEAMercury) GetLinkPrice() int64 {
+ if x != nil {
+ return x.LinkPrice
+ }
+ return 0
+}
+
+func (x *EnhancedEAMercury) GetIsNativeFeed() bool {
+ if x != nil {
+ return x.IsNativeFeed
+ }
+ return false
+}
+
+func (x *EnhancedEAMercury) GetNativePrice() int64 {
+ if x != nil {
+ return x.NativePrice
+ }
+ return 0
+}
+
func (x *EnhancedEAMercury) GetBridgeTaskRunStartedTimestamp() int64 {
if x != nil {
return x.BridgeTaskRunStartedTimestamp
@@ -188,6 +256,13 @@ func (x *EnhancedEAMercury) GetObservationBenchmarkPrice() int64 {
return 0
}
+func (x *EnhancedEAMercury) GetObservationBenchmarkPriceString() string {
+ if x != nil {
+ return x.ObservationBenchmarkPriceString
+ }
+ return ""
+}
+
func (x *EnhancedEAMercury) GetObservationBid() int64 {
if x != nil {
return x.ObservationBid
@@ -202,6 +277,20 @@ func (x *EnhancedEAMercury) GetObservationAsk() int64 {
return 0
}
+func (x *EnhancedEAMercury) GetObservationBidString() string {
+ if x != nil {
+ return x.ObservationBidString
+ }
+ return ""
+}
+
+func (x *EnhancedEAMercury) GetObservationAskString() string {
+ if x != nil {
+ return x.ObservationAskString
+ }
+ return ""
+}
+
func (x *EnhancedEAMercury) GetConfigDigest() string {
if x != nil {
return x.ConfigDigest
@@ -230,27 +319,6 @@ func (x *EnhancedEAMercury) GetAssetSymbol() string {
return ""
}
-func (x *EnhancedEAMercury) GetObservationBenchmarkPriceString() string {
- if x != nil {
- return x.ObservationBenchmarkPriceString
- }
- return ""
-}
-
-func (x *EnhancedEAMercury) GetObservationBidString() string {
- if x != nil {
- return x.ObservationBidString
- }
- return ""
-}
-
-func (x *EnhancedEAMercury) GetObservationAskString() string {
- if x != nil {
- return x.ObservationAskString
- }
- return ""
-}
-
var File_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto protoreflect.FileDescriptor
var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_rawDesc = []byte{
@@ -258,86 +326,107 @@ var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_raw
0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f,
0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x65, 0x6e, 0x68, 0x61,
0x6e, 0x63, 0x65, 0x64, 0x5f, 0x65, 0x61, 0x5f, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0x8e, 0x09, 0x0a,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0xe2, 0x0b, 0x0a,
0x11, 0x45, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x45, 0x41, 0x4d, 0x65, 0x72, 0x63, 0x75,
- 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x70, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d,
- 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x10, 0x64, 0x70, 0x42, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63,
- 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x70, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x01, 0x52, 0x05, 0x64, 0x70, 0x42, 0x69, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x70, 0x5f, 0x61,
- 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x64, 0x70, 0x41, 0x73, 0x6b, 0x12,
- 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
- 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65,
- 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f,
- 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12,
- 0x36, 0x0a, 0x17, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
- 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x15, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69,
- 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x48, 0x0a, 0x21, 0x62, 0x72, 0x69, 0x64, 0x67,
- 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
- 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x1d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x75,
- 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
- 0x70, 0x12, 0x44, 0x0a, 0x1f, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b,
- 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73,
- 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x62, 0x72, 0x69, 0x64,
- 0x67, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x75, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x69,
- 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x40, 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69,
- 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x70,
- 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64,
- 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3e, 0x0a, 0x1b, 0x70, 0x72, 0x6f,
- 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
- 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x47, 0x0a, 0x20, 0x70, 0x72, 0x6f,
- 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
- 0x6d, 0x5f, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x0c, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x44, 0x61, 0x74,
- 0x61, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68,
- 0x65, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69,
- 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0d, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x64,
- 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x65,
- 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x65, 0x65, 0x64, 0x12, 0x3e,
- 0x0a, 0x1b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x65,
- 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0f, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x42, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x27,
- 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69,
- 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72,
- 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b,
- 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73,
- 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44,
- 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x13,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65,
- 0x70, 0x6f, 0x63, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63,
- 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f,
- 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x65, 0x74, 0x53, 0x79,
- 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x4b, 0x0a, 0x22, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72,
- 0x69, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x1f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x6e,
- 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e,
- 0x67, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x20, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b,
+ 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a,
+ 0x12, 0x64, 0x70, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72,
+ 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x64, 0x70, 0x42, 0x65, 0x6e,
+ 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64,
+ 0x70, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x64, 0x70, 0x42,
+ 0x69, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x70, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x01, 0x52, 0x05, 0x64, 0x70, 0x41, 0x73, 0x6b, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72,
+ 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65,
+ 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
+ 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x63,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73,
+ 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
+ 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x75, 0x72,
+ 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x63, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x12, 0x41, 0x0a, 0x1d, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x66,
+ 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+ 0x6d, 0x70, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x66, 0x65, 0x74, 0x63, 0x68, 0x4d,
+ 0x61, 0x78, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x69, 0x6e, 0x61,
+ 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
+ 0x1a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69,
+ 0x7a, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33, 0x0a, 0x15,
+ 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6f, 0x62, 0x73,
+ 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x66, 0x65, 0x65,
+ 0x64, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x46,
+ 0x65, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63,
+ 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x50, 0x72, 0x69,
+ 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f,
+ 0x66, 0x65, 0x65, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x4e, 0x61,
+ 0x74, 0x69, 0x76, 0x65, 0x46, 0x65, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x61, 0x74, 0x69,
+ 0x76, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
+ 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x21, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x61,
+ 0x73, 0x6b, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x44, 0x0a, 0x1f, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f,
+ 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74,
+ 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x75, 0x6e, 0x45, 0x6e, 0x64,
+ 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x40, 0x0a, 0x1c, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65,
+ 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x1a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3e, 0x0a,
+ 0x1b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76,
+ 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x19, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x63, 0x65,
+ 0x69, 0x76, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x47, 0x0a,
+ 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73,
+ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65,
+ 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x44, 0x61, 0x74, 0x61, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x73, 0x74, 0x61, 0x62,
+ 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
+ 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d,
+ 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12,
+ 0x0a, 0x04, 0x66, 0x65, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x65,
+ 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63,
+ 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69,
+ 0x63, 0x65, 0x12, 0x4b, 0x0a, 0x22, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63,
+ 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f,
+ 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x6e, 0x63, 0x68,
+ 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, 0x63, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12,
+ 0x27, 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62,
+ 0x69, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x62, 0x73, 0x65,
+ 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x0e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73,
+ 0x6b, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x62, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28,
0x09, 0x52, 0x14, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69,
0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x62, 0x73, 0x65, 0x72,
0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x4e, 0x5a,
- 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72,
- 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61,
- 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73,
- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e,
- 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a,
+ 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x12,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65,
+ 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63,
+ 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x21,
+ 0x0a, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x15,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x65, 0x74, 0x53, 0x79, 0x6d, 0x62, 0x6f,
+ 0x6c, 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x73, 0x6d, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74,
+ 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f,
+ 0x72, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63,
+ 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65,
+ 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto b/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
index 92242fd2a1..a527552bb6 100644
--- a/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
+++ b/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto
@@ -5,28 +5,49 @@ option go_package = "github.com/smartcontractkit/chainlink/v2/core/services/sync
package telem;
message EnhancedEAMercury {
+ uint32 version = 32;
+
string data_source=1;
double dp_benchmark_price=2;
double dp_bid=3;
double dp_ask=4;
+
+ // v1 fields (block range)
int64 current_block_number=5;
string current_block_hash=6;
uint64 current_block_timestamp=7;
+
+ // v2+v3 fields (timestamp range)
+ bool fetch_max_finalized_timestamp = 25;
+ int64 max_finalized_timestamp=26;
+ uint32 observation_timestamp=27;
+ bool is_link_feed=28;
+ int64 link_price=29;
+ bool is_native_feed=30;
+ int64 native_price=31;
+
int64 bridge_task_run_started_timestamp=8;
int64 bridge_task_run_ended_timestamp=9;
int64 provider_requested_timestamp=10;
int64 provider_received_timestamp=11;
int64 provider_data_stream_established=12;
int64 provider_indicated_time=13;
+
string feed=14;
- int64 observation_benchmark_price=15;
- int64 observation_bid=16;
- int64 observation_ask=17;
+
+ // v1+v2+v3
+ int64 observation_benchmark_price=15; // This value overflows, will be reserved and removed in future versions
+ string observation_benchmark_price_string = 22;
+ // v1+v3
+ int64 observation_bid=16; // This value overflows, will be reserved and removed in future versions
+ int64 observation_ask=17; // This value overflows, will be reserved and removed in future versions
+ string observation_bid_string = 23;
+ string observation_ask_string = 24;
+
string config_digest = 18;
int64 round=19;
int64 epoch=20;
string asset_symbol=21;
- string observation_benchmark_price_string = 22;
- string observation_bid_string = 23;
- string observation_ask_string = 24;
+
+
}
diff --git a/tools/flakeytests/coverage.txt b/tools/flakeytests/coverage.txt
new file mode 100644
index 0000000000..91640016fe
--- /dev/null
+++ b/tools/flakeytests/coverage.txt
@@ -0,0 +1,93 @@
+mode: atomic
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:50.103,54.38 4 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:54.38,55.24 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:55.24,62.18 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:62.18,64.5 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:65.4,65.46 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:72.2,73.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:73.16,75.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:77.2,90.16 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:93.63,95.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:95.16,97.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:99.2,101.16 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:101.16,103.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:104.2,110.16 4 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:110.16,112.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:112.8,112.52 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:112.52,114.18 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:114.18,116.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:117.3,117.83 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:119.2,119.12 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:122.81,124.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:124.16,126.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:128.2,128.31 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:131.77,133.2 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:40.79,44.30 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:44.31,44.32 0 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:46.2,52.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:61.75,70.2 8 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:81.45,85.2 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:87.75,89.28 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:89.28,91.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:91.16,93.19 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:93.19,94.13 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:99.4,99.42 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:99.42,100.13 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:103.4,104.18 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:104.18,106.5 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:110.4,110.39 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:110.39,111.13 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:114.4,114.20 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:115.16,116.32 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:116.32,118.6 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:119.5,119.31 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:120.18,121.38 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:121.38,122.33 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:122.33,124.7 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:125.6,125.32 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:130.3,130.33 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:130.33,132.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:134.2,134.19 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:141.106,144.38 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:144.38,146.27 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:146.27,148.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:150.3,151.36 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:151.36,155.18 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:155.18,161.55 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:161.55,162.14 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:164.5,164.32 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:167.4,168.18 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:168.18,170.5 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:172.4,172.25 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:172.25,174.22 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:174.22,175.37 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:175.37,177.7 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:178.6,178.42 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:184.2,184.29 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:187.30,189.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:189.16,191.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:193.2,194.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:194.16,196.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:198.2,198.30 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:198.30,200.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:200.8,202.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:204.2,204.43 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:12.74,15.25 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:15.25,17.10 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:17.10,19.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:21.3,21.10 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:24.2,25.9 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:25.9,27.3 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:29.2,29.16 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:32.88,34.16 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:34.16,36.17 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:36.17,38.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:40.3,41.17 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:41.17,43.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:45.3,46.17 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:46.17,48.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:51.2,52.19 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:53.22,56.17 3 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:56.17,58.4 1 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:60.3,61.19 2 0
+github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:62.10,63.19 1 0
From 67a79f134e516b51ebf597e2eda0ff587c14d37d Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Mon, 30 Oct 2023 12:40:19 -0500
Subject: [PATCH 032/327] core/utils: deprecate StartStopOnce in favor of
services.StateMachine (#11117)
---
common/headtracker/head_broadcaster.go | 26 ++-
common/headtracker/head_tracker.go | 4 +-
common/txmgr/broadcaster.go | 3 +-
common/txmgr/confirmer.go | 3 +-
common/txmgr/txmgr.go | 2 +-
core/chains/cosmos/chain.go | 5 +-
core/chains/cosmos/cosmostxm/txm.go | 23 +--
core/chains/evm/chain.go | 4 +-
core/chains/evm/client/node.go | 3 +-
core/chains/evm/client/pool.go | 6 +-
core/chains/evm/client/send_only_node.go | 3 +-
.../evm/forwarders/forwarder_manager.go | 7 +-
core/chains/evm/gas/arbitrum_estimator.go | 5 +-
.../chains/evm/gas/block_history_estimator.go | 3 +-
core/chains/evm/gas/l2_suggested_estimator.go | 3 +-
core/chains/evm/gas/models.go | 3 +-
.../evm/gas/rollups/l1_gas_price_oracle.go | 3 +-
core/chains/evm/log/broadcaster.go | 7 +-
core/chains/evm/logpoller/log_poller.go | 7 +-
core/chains/evm/monitor/balance.go | 9 +-
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
core/services/blockhashstore/delegate.go | 3 +-
core/services/blockheaderfeeder/delegate.go | 3 +-
core/services/directrequest/delegate.go | 5 +-
core/services/feeds/service.go | 3 +-
core/services/fluxmonitorv2/flux_monitor.go | 4 +-
core/services/functions/connector_handler.go | 9 +-
core/services/functions/listener.go | 8 +-
core/services/gateway/connectionmanager.go | 2 +-
core/services/gateway/connector/connector.go | 2 +-
core/services/gateway/gateway.go | 3 +-
.../gateway/handlers/functions/allowlist.go | 3 +-
.../handlers/functions/handler.functions.go | 3 +-
.../handlers/functions/subscriptions.go | 3 +-
core/services/gateway/network/httpserver.go | 4 +-
core/services/gateway/network/wsconnection.go | 3 +-
core/services/gateway/network/wsserver.go | 4 +-
core/services/job/spawner.go | 2 +-
.../keeper/registry_synchronizer_core.go | 3 +-
core/services/keeper/upkeep_executer.go | 3 +-
core/services/nurse.go | 3 +-
core/services/ocr/config_overrider.go | 6 +-
core/services/ocr/contract_tracker.go | 3 +-
core/services/ocr2/plugins/median/plugin.go | 3 +-
.../plugins/ocr2keeper/evm20/log_provider.go | 5 +-
.../ocr2/plugins/ocr2keeper/evm20/registry.go | 7 +-
.../ocr2keeper/evm21/block_subscriber.go | 4 +-
.../ocr2keeper/evm21/logprovider/provider.go | 4 +-
.../ocr2keeper/evm21/logprovider/recoverer.go | 4 +-
.../ocr2/plugins/ocr2keeper/evm21/registry.go | 3 +-
.../evm21/transmit/event_provider.go | 5 +-
.../ocr2keeper/evm21/upkeepstate/store.go | 3 +-
core/services/ocrcommon/peer_wrapper.go | 11 +-
core/services/ocrcommon/peerstore.go | 6 +-
core/services/ocrcommon/run_saver.go | 4 +-
core/services/ocrcommon/telemetry.go | 7 +-
core/services/periodicbackup/backup.go | 12 +-
core/services/pg/event_broadcaster.go | 7 +-
core/services/pipeline/orm.go | 14 +-
core/services/pipeline/runner.go | 10 +-
core/services/promreporter/prom_reporter.go | 6 +-
core/services/relay/evm/config_poller.go | 5 +-
core/services/relay/evm/evm.go | 7 +-
core/services/relay/evm/functions.go | 8 +-
.../relay/evm/functions/logpoller_wrapper.go | 3 +-
.../relay/evm/mercury/persistence_manager.go | 3 +-
core/services/relay/evm/mercury/queue.go | 9 +-
.../services/relay/evm/mercury/transmitter.go | 4 +-
.../relay/evm/mercury/wsrpc/client.go | 10 +-
.../relay/evm/request_round_tracker.go | 5 +-
.../telemetry_ingress_batch_client.go | 4 +-
.../telemetry_ingress_client.go | 3 +-
core/services/telemetry/manager.go | 11 +-
core/services/telemetry/manager_test.go | 10 +-
core/services/vrf/v1/listener_v1.go | 3 +-
core/services/vrf/v2/listener_v2.go | 3 +-
core/utils/helpers_test.go | 5 -
core/utils/mailbox_prom.go | 4 +-
core/utils/sleeper_task.go | 15 +-
core/utils/utils.go | 181 +-----------------
core/utils/utils_test.go | 105 ----------
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
86 files changed, 254 insertions(+), 488 deletions(-)
delete mode 100644 core/utils/helpers_test.go
diff --git a/common/headtracker/head_broadcaster.go b/common/headtracker/head_broadcaster.go
index 17d50ef562..e9ae93419b 100644
--- a/common/headtracker/head_broadcaster.go
+++ b/common/headtracker/head_broadcaster.go
@@ -7,6 +7,7 @@ import (
"sync"
"time"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -25,13 +26,13 @@ func (set callbackSet[H, BLOCK_HASH]) values() []types.HeadTrackable[H, BLOCK_HA
}
type HeadBroadcaster[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] struct {
- logger logger.Logger
- callbacks callbackSet[H, BLOCK_HASH]
- mailbox *utils.Mailbox[H]
- mutex *sync.Mutex
- chClose utils.StopChan
- wgDone sync.WaitGroup
- utils.StartStopOnce
+ services.StateMachine
+ logger logger.Logger
+ callbacks callbackSet[H, BLOCK_HASH]
+ mailbox *utils.Mailbox[H]
+ mutex sync.Mutex
+ chClose utils.StopChan
+ wgDone sync.WaitGroup
latest H
lastCallbackID int
}
@@ -44,13 +45,10 @@ func NewHeadBroadcaster[
lggr logger.Logger,
) *HeadBroadcaster[H, BLOCK_HASH] {
return &HeadBroadcaster[H, BLOCK_HASH]{
- logger: lggr.Named("HeadBroadcaster"),
- callbacks: make(callbackSet[H, BLOCK_HASH]),
- mailbox: utils.NewSingleMailbox[H](),
- mutex: &sync.Mutex{},
- chClose: make(chan struct{}),
- wgDone: sync.WaitGroup{},
- StartStopOnce: utils.StartStopOnce{},
+ logger: lggr.Named("HeadBroadcaster"),
+ callbacks: make(callbackSet[H, BLOCK_HASH]),
+ mailbox: utils.NewSingleMailbox[H](),
+ chClose: make(chan struct{}),
}
}
diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go
index 1978b281d4..c24dde595c 100644
--- a/common/headtracker/head_tracker.go
+++ b/common/headtracker/head_tracker.go
@@ -40,6 +40,7 @@ type HeadTracker[
ID types.ID,
BLOCK_HASH types.Hashable,
] struct {
+ services.StateMachine
log logger.Logger
headBroadcaster types.HeadBroadcaster[HTH, BLOCK_HASH]
headSaver types.HeadSaver[HTH, BLOCK_HASH]
@@ -54,8 +55,7 @@ type HeadTracker[
headListener types.HeadListener[HTH, BLOCK_HASH]
chStop utils.StopChan
wgDone sync.WaitGroup
- utils.StartStopOnce
- getNilHead func() HTH
+ getNilHead func() HTH
}
// NewHeadTracker instantiates a new HeadTracker using HeadSaver to persist new block numbers.
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index 6512f67fe0..011866bf39 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -14,6 +14,7 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
@@ -105,6 +106,7 @@ type Broadcaster[
SEQ types.Sequence,
FEE feetypes.Fee,
] struct {
+ services.StateMachine
logger logger.Logger
txStore txmgrtypes.TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE]
client txmgrtypes.TransactionClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
@@ -140,7 +142,6 @@ type Broadcaster[
initSync sync.Mutex
isStarted bool
- utils.StartStopOnce
parseAddr func(string) (ADDR, error)
diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go
index 31bba77141..c22a159457 100644
--- a/common/txmgr/confirmer.go
+++ b/common/txmgr/confirmer.go
@@ -14,6 +14,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
@@ -112,7 +113,7 @@ type Confirmer[
SEQ types.Sequence,
FEE feetypes.Fee,
] struct {
- utils.StartStopOnce
+ services.StateMachine
txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]
lggr logger.Logger
client txmgrtypes.TxmClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]
diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go
index 980067b5fb..0c7117afab 100644
--- a/common/txmgr/txmgr.go
+++ b/common/txmgr/txmgr.go
@@ -69,7 +69,7 @@ type Txm[
SEQ types.Sequence,
FEE feetypes.Fee,
] struct {
- utils.StartStopOnce
+ services.StateMachine
logger logger.Logger
txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]
config txmgrtypes.TransactionManagerChainConfig
diff --git a/core/chains/cosmos/chain.go b/core/chains/cosmos/chain.go
index 43ba5a4e79..bb44c4bee6 100644
--- a/core/chains/cosmos/chain.go
+++ b/core/chains/cosmos/chain.go
@@ -27,7 +27,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// DefaultRequestTimeout is the default Cosmos client timeout.
@@ -93,7 +92,7 @@ func NewChain(cfg *CosmosConfig, opts ChainOpts) (adapters.Chain, error) {
var _ adapters.Chain = (*chain)(nil)
type chain struct {
- utils.StartStopOnce
+ services.StateMachine
id string
cfg *CosmosConfig
txm *cosmostxm.Txm
@@ -197,7 +196,7 @@ func (c *chain) Close() error {
func (c *chain) Ready() error {
return multierr.Combine(
- c.StartStopOnce.Ready(),
+ c.StateMachine.Ready(),
c.txm.Ready(),
)
}
diff --git a/core/chains/cosmos/cosmostxm/txm.go b/core/chains/cosmos/cosmostxm/txm.go
index e9fb2f6aca..8806d97a9f 100644
--- a/core/chains/cosmos/cosmostxm/txm.go
+++ b/core/chains/cosmos/cosmostxm/txm.go
@@ -28,20 +28,20 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
var (
- _ services.ServiceCtx = (*Txm)(nil)
- _ adapters.TxManager = (*Txm)(nil)
+ _ services.Service = (*Txm)(nil)
+ _ adapters.TxManager = (*Txm)(nil)
)
// Txm manages transactions for the cosmos blockchain.
type Txm struct {
- starter utils.StartStopOnce
+ services.StateMachine
eb pg.EventBroadcaster
sub pg.Subscription
orm *ORM
@@ -58,7 +58,6 @@ func NewTxm(db *sqlx.DB, tc func() (cosmosclient.ReaderWriter, error), gpe cosmo
lggr = logger.Named(lggr, "Txm")
keystoreAdapter := NewKeystoreAdapter(ks, cfg.Bech32Prefix())
return &Txm{
- starter: utils.StartStopOnce{},
eb: eb,
orm: NewORM(chainID, db, lggr, logCfg),
lggr: lggr,
@@ -73,7 +72,7 @@ func NewTxm(db *sqlx.DB, tc func() (cosmosclient.ReaderWriter, error), gpe cosmo
// Start subscribes to pg notifications about cosmos msg inserts and processes them.
func (txm *Txm) Start(context.Context) error {
- return txm.starter.StartOnce("cosmostxm", func() error {
+ return txm.StartOnce("Txm", func() error {
sub, err := txm.eb.Subscribe(pg.ChannelInsertOnCosmosMsg, "")
if err != nil {
return err
@@ -520,13 +519,15 @@ func (txm *Txm) GasPrice() (sdk.DecCoin, error) {
// Close close service
func (txm *Txm) Close() error {
- txm.sub.Close()
- close(txm.stop)
- <-txm.done
- return nil
+ return txm.StopOnce("Txm", func() error {
+ txm.sub.Close()
+ close(txm.stop)
+ <-txm.done
+ return nil
+ })
}
-func (txm *Txm) Name() string { return "cosmostxm" }
+func (txm *Txm) Name() string { return txm.lggr.Name() }
// Healthy service is healthy
func (txm *Txm) Healthy() error {
diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go
index 2646d25867..6eed13271e 100644
--- a/core/chains/evm/chain.go
+++ b/core/chains/evm/chain.go
@@ -108,7 +108,7 @@ func (c *LegacyChains) Get(id string) (Chain, error) {
}
type chain struct {
- utils.StartStopOnce
+ services.StateMachine
id *big.Int
cfg *evmconfig.ChainScoped
client evmclient.Client
@@ -366,7 +366,7 @@ func (c *chain) Close() error {
func (c *chain) Ready() (merr error) {
merr = multierr.Combine(
- c.StartStopOnce.Ready(),
+ c.StateMachine.Ready(),
c.txm.Ready(),
c.headBroadcaster.Ready(),
c.headTracker.Ready(),
diff --git a/core/chains/evm/client/node.go b/core/chains/evm/client/node.go
index 4f7132a6cc..80bac25448 100644
--- a/core/chains/evm/client/node.go
+++ b/core/chains/evm/client/node.go
@@ -19,6 +19,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -132,7 +133,7 @@ type rawclient struct {
// Node represents one ethereum node.
// It must have a ws url and may have a http url
type node struct {
- utils.StartStopOnce
+ services.StateMachine
lfcLog logger.Logger
rpcLog logger.Logger
name string
diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go
index 7e4667623d..2d679ab3d7 100644
--- a/core/chains/evm/client/pool.go
+++ b/core/chains/evm/client/pool.go
@@ -15,11 +15,11 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -57,7 +57,7 @@ type PoolConfig interface {
// Pool represents an abstraction over one or more primary nodes
// It is responsible for liveness checking and balancing queries across live nodes
type Pool struct {
- utils.StartStopOnce
+ services.StateMachine
nodes []Node
sendonlys []SendOnlyNode
chainID *big.Int
diff --git a/core/chains/evm/client/send_only_node.go b/core/chains/evm/client/send_only_node.go
index a085ec4753..3f2481c189 100644
--- a/core/chains/evm/client/send_only_node.go
+++ b/core/chains/evm/client/send_only_node.go
@@ -14,6 +14,7 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -56,7 +57,7 @@ var _ SendOnlyNode = &sendOnlyNode{}
// It only supports sending transactions
// It must a http(s) url
type sendOnlyNode struct {
- utils.StartStopOnce
+ services.StateMachine
stateMu sync.RWMutex // protects state* fields
state NodeState
diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go
index 0c470e76d8..46bca95ba3 100644
--- a/core/chains/evm/forwarders/forwarder_manager.go
+++ b/core/chains/evm/forwarders/forwarder_manager.go
@@ -9,8 +9,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/sqlx"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmlogpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -30,7 +32,7 @@ type Config interface {
}
type FwdMgr struct {
- utils.StartStopOnce
+ services.StateMachine
ORM ORM
evmClient evmclient.Client
cfg Config
@@ -61,9 +63,6 @@ func NewFwdMgr(db *sqlx.DB, client evmclient.Client, logpoller evmlogpoller.LogP
ORM: NewORM(db, lggr, dbConfig),
logpoller: logpoller,
sendersCache: make(map[common.Address][]common.Address),
- cacheMu: sync.RWMutex{},
- wg: sync.WaitGroup{},
- latestBlock: 0,
}
fwdMgr.ctx, fwdMgr.cancel = context.WithCancel(context.Background())
return &fwdMgr
diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go
index 6c2b5e8b87..17934bfa07 100644
--- a/core/chains/evm/gas/arbitrum_estimator.go
+++ b/core/chains/evm/gas/arbitrum_estimator.go
@@ -33,6 +33,7 @@ type ethClient interface {
// arbitrumEstimator is an Estimator which extends l2SuggestedPriceEstimator to use getPricesInArbGas() for gas limit estimation.
type arbitrumEstimator struct {
+ services.StateMachine
cfg ArbConfig
EvmEstimator // *l2SuggestedPriceEstimator
@@ -49,8 +50,6 @@ type arbitrumEstimator struct {
chInitialised chan struct{}
chStop utils.StopChan
chDone chan struct{}
-
- utils.StartStopOnce
}
func NewArbitrumEstimator(lggr logger.Logger, cfg ArbConfig, rpcClient rpcClient, ethClient ethClient) EvmEstimator {
@@ -91,7 +90,7 @@ func (a *arbitrumEstimator) Close() error {
})
}
-func (a *arbitrumEstimator) Ready() error { return a.StartStopOnce.Ready() }
+func (a *arbitrumEstimator) Ready() error { return a.StateMachine.Ready() }
func (a *arbitrumEstimator) HealthReport() map[string]error {
hp := map[string]error{a.Name(): a.Healthy()}
diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go
index 14b18ad66b..42c8f05153 100644
--- a/core/chains/evm/gas/block_history_estimator.go
+++ b/core/chains/evm/gas/block_history_estimator.go
@@ -15,6 +15,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
@@ -96,7 +97,7 @@ type estimatorGasEstimatorConfig interface {
//go:generate mockery --quiet --name Config --output ./mocks/ --case=underscore
type (
BlockHistoryEstimator struct {
- utils.StartStopOnce
+ services.StateMachine
ethClient evmclient.Client
chainID big.Int
config chainConfig
diff --git a/core/chains/evm/gas/l2_suggested_estimator.go b/core/chains/evm/gas/l2_suggested_estimator.go
index 1782e34930..8e6c06a128 100644
--- a/core/chains/evm/gas/l2_suggested_estimator.go
+++ b/core/chains/evm/gas/l2_suggested_estimator.go
@@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
@@ -28,7 +29,7 @@ type rpcClient interface {
// l2SuggestedPriceEstimator is an Estimator which uses the L2 suggested gas price from eth_gasPrice.
type l2SuggestedPriceEstimator struct {
- utils.StartStopOnce
+ services.StateMachine
client rpcClient
pollPeriod time.Duration
diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go
index bd3106c2ad..7bd88d7543 100644
--- a/core/chains/evm/gas/models.go
+++ b/core/chains/evm/gas/models.go
@@ -22,7 +22,6 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math"
)
@@ -150,10 +149,10 @@ func (fee EvmFee) ValidDynamic() bool {
// WrappedEvmEstimator provides a struct that wraps the EVM specific dynamic and legacy estimators into one estimator that conforms to the generic FeeEstimator
type WrappedEvmEstimator struct {
+ services.StateMachine
EvmEstimator
EIP1559Enabled bool
l1Oracle rollups.L1Oracle
- utils.StartStopOnce
}
var _ EvmFeeEstimator = (*WrappedEvmEstimator)(nil)
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
index 8cf10325d4..c15aa23c79 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/config"
@@ -26,6 +27,7 @@ type ethClient interface {
// Reads L2-specific precompiles and caches the l1GasPrice set by the L2.
type l1GasPriceOracle struct {
+ services.StateMachine
client ethClient
pollPeriod time.Duration
logger logger.Logger
@@ -38,7 +40,6 @@ type l1GasPriceOracle struct {
chInitialised chan struct{}
chStop utils.StopChan
chDone chan struct{}
- utils.StartStopOnce
}
const (
diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go
index bc9ba1cf6c..9c4050fd79 100644
--- a/core/chains/evm/log/broadcaster.go
+++ b/core/chains/evm/log/broadcaster.go
@@ -12,13 +12,14 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/null"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -44,7 +45,7 @@ type (
// Of course, these backfilled logs + any new logs will only be sent after the NumConfirmations for given subscriber.
Broadcaster interface {
utils.DependentAwaiter
- services.ServiceCtx
+ services.Service
httypes.HeadTrackable
// ReplayFromBlock enqueues a replay from the provided block number. If forceBroadcast is
@@ -88,6 +89,7 @@ type (
}
broadcaster struct {
+ services.StateMachine
orm ORM
config Config
connected atomic.Bool
@@ -106,7 +108,6 @@ type (
changeSubscriberStatus *utils.Mailbox[changeSubscriberStatus]
newHeads *utils.Mailbox[*evmtypes.Head]
- utils.StartStopOnce
utils.DependentAwaiter
chStop utils.StopChan
diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go
index 54999cbdfb..6cda8f5b46 100644
--- a/core/chains/evm/logpoller/log_poller.go
+++ b/core/chains/evm/logpoller/log_poller.go
@@ -20,10 +20,11 @@ import (
"github.com/pkg/errors"
"golang.org/x/exp/maps"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/utils/mathutil"
@@ -31,7 +32,7 @@ import (
//go:generate mockery --quiet --name LogPoller --output ./mocks/ --case=underscore --structname LogPoller --filename log_poller.go
type LogPoller interface {
- services.ServiceCtx
+ services.Service
Replay(ctx context.Context, fromBlock int64) error
ReplayAsync(fromBlock int64)
RegisterFilter(filter Filter, qopts ...pg.QOpt) error
@@ -92,7 +93,7 @@ var (
)
type logPoller struct {
- utils.StartStopOnce
+ services.StateMachine
ec Client
orm ORM
lggr logger.Logger
diff --git a/core/chains/evm/monitor/balance.go b/core/chains/evm/monitor/balance.go
index 94434b733e..5f5b8a243b 100644
--- a/core/chains/evm/monitor/balance.go
+++ b/core/chains/evm/monitor/balance.go
@@ -13,12 +13,13 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -29,11 +30,11 @@ type (
BalanceMonitor interface {
httypes.HeadTrackable
GetEthBalance(gethCommon.Address) *assets.Eth
- services.ServiceCtx
+ services.Service
}
balanceMonitor struct {
- utils.StartStopOnce
+ services.StateMachine
logger logger.Logger
ethClient evmclient.Client
chainID *big.Int
@@ -53,7 +54,7 @@ var _ BalanceMonitor = (*balanceMonitor)(nil)
func NewBalanceMonitor(ethClient evmclient.Client, ethKeyStore keystore.Eth, logger logger.Logger) *balanceMonitor {
chainId := ethClient.ConfiguredChainID()
bm := &balanceMonitor{
- utils.StartStopOnce{},
+ services.StateMachine{},
logger.Named("BalanceMonitor"),
ethClient,
chainId,
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index f097ea89be..7c0161a066 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -302,7 +302,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 0461daa25e..e0e5e07ecf 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1458,8 +1458,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/blockhashstore/delegate.go b/core/services/blockhashstore/delegate.go
index 90819f27a1..123052550b 100644
--- a/core/services/blockhashstore/delegate.go
+++ b/core/services/blockhashstore/delegate.go
@@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
v1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
@@ -197,7 +198,7 @@ func (d *Delegate) OnDeleteJob(spec job.Job, q pg.Queryer) error { return nil }
// service is a job.Service that runs the BHS feeder every pollPeriod.
type service struct {
- utils.StartStopOnce
+ services.StateMachine
feeder *Feeder
wg sync.WaitGroup
pollPeriod time.Duration
diff --git a/core/services/blockheaderfeeder/delegate.go b/core/services/blockheaderfeeder/delegate.go
index 02ab34821f..971a691d77 100644
--- a/core/services/blockheaderfeeder/delegate.go
+++ b/core/services/blockheaderfeeder/delegate.go
@@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
@@ -211,7 +212,7 @@ func (d *Delegate) OnDeleteJob(spec job.Job, q pg.Queryer) error { return nil }
// service is a job.Service that runs the BHS feeder every pollPeriod.
type service struct {
- utils.StartStopOnce
+ services.StateMachine
feeder *BlockHeaderFeeder
done chan struct{}
pollPeriod time.Duration
diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go
index 75cebb7a74..174dca062a 100644
--- a/core/services/directrequest/delegate.go
+++ b/core/services/directrequest/delegate.go
@@ -9,13 +9,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
@@ -119,6 +120,7 @@ var (
)
type listener struct {
+ services.StateMachine
logger logger.Logger
config Config
logBroadcaster log.Broadcaster
@@ -135,7 +137,6 @@ type listener struct {
requesters models.AddressCollection
minContractPayment *assets.Link
chStop chan struct{}
- utils.StartStopOnce
}
func (l *listener) HealthReport() map[string]error {
diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go
index 4c3647fde4..20919606fa 100644
--- a/core/services/feeds/service.go
+++ b/core/services/feeds/service.go
@@ -17,6 +17,7 @@ import (
"github.com/smartcontractkit/sqlx"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto"
@@ -98,7 +99,7 @@ type Service interface {
}
type service struct {
- utils.StartStopOnce
+ services.StateMachine
orm ORM
jobORM job.ORM
diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go
index fe8a22d417..99d33c4239 100644
--- a/core/services/fluxmonitorv2/flux_monitor.go
+++ b/core/services/fluxmonitorv2/flux_monitor.go
@@ -15,6 +15,7 @@ import (
"github.com/smartcontractkit/sqlx"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
@@ -55,6 +56,7 @@ const DefaultHibernationPollPeriod = 24 * time.Hour
// FluxMonitor polls external price adapters via HTTP to check for price swings.
type FluxMonitor struct {
+ services.StateMachine
contractAddress common.Address
oracleAddress common.Address
jobSpec job.Job
@@ -80,7 +82,6 @@ type FluxMonitor struct {
backlog *utils.BoundedPriorityQueue[log.Broadcast]
chProcessLogs chan struct{}
- utils.StartStopOnce
chStop chan struct{}
waitOnStop chan struct{}
}
@@ -134,7 +135,6 @@ func NewFluxMonitor(
PriorityAnswerUpdatedLog: 1,
PriorityFlagChangedLog: 2,
}),
- StartStopOnce: utils.StartStopOnce{},
chProcessLogs: make(chan struct{}, 1),
chStop: make(chan struct{}),
waitOnStop: make(chan struct{}),
diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go
index c32bf56f0c..a018157a37 100644
--- a/core/services/functions/connector_handler.go
+++ b/core/services/functions/connector_handler.go
@@ -8,6 +8,10 @@ import (
"go.uber.org/multierr"
+ ethCommon "github.com/ethereum/go-ethereum/common"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
@@ -16,13 +20,10 @@ import (
hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions"
"github.com/smartcontractkit/chainlink/v2/core/services/s4"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- ethCommon "github.com/ethereum/go-ethereum/common"
)
type functionsConnectorHandler struct {
- utils.StartStopOnce
+ services.StateMachine
connector connector.GatewayConnector
signerKey *ecdsa.PrivateKey
diff --git a/core/services/functions/listener.go b/core/services/functions/listener.go
index b76eb0a1c0..773ae61040 100644
--- a/core/services/functions/listener.go
+++ b/core/services/functions/listener.go
@@ -13,6 +13,9 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"google.golang.org/protobuf/proto"
+ "github.com/smartcontractkit/libocr/commontypes"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/cbor"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -23,9 +26,6 @@ import (
evmrelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/services/s4"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- "github.com/smartcontractkit/libocr/commontypes"
)
var (
@@ -116,7 +116,7 @@ const (
)
type FunctionsListener struct {
- utils.StartStopOnce
+ services.StateMachine
client client.Client
contractAddressHex string
job job.Job
diff --git a/core/services/gateway/connectionmanager.go b/core/services/gateway/connectionmanager.go
index ae2ade6511..278c4beaaa 100644
--- a/core/services/gateway/connectionmanager.go
+++ b/core/services/gateway/connectionmanager.go
@@ -42,7 +42,7 @@ type ConnectionManager interface {
}
type connectionManager struct {
- utils.StartStopOnce
+ services.StateMachine
config *config.ConnectionManagerConfig
dons map[string]*donConnectionManager
diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go
index dd8dce473b..5578681944 100644
--- a/core/services/gateway/connector/connector.go
+++ b/core/services/gateway/connector/connector.go
@@ -46,7 +46,7 @@ type GatewayConnectorHandler interface {
}
type gatewayConnector struct {
- utils.StartStopOnce
+ services.StateMachine
config *ConnectorConfig
codec api.Codec
diff --git a/core/services/gateway/gateway.go b/core/services/gateway/gateway.go
index fb38ae10de..42e03107f3 100644
--- a/core/services/gateway/gateway.go
+++ b/core/services/gateway/gateway.go
@@ -13,6 +13,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/config"
@@ -42,7 +43,7 @@ type HandlerFactory interface {
}
type gateway struct {
- utils.StartStopOnce
+ services.StateMachine
codec api.Codec
httpServer gw_net.HttpServer
diff --git a/core/services/gateway/handlers/functions/allowlist.go b/core/services/gateway/handlers/functions/allowlist.go
index d3619d9071..914a933eb1 100644
--- a/core/services/gateway/handlers/functions/allowlist.go
+++ b/core/services/gateway/handlers/functions/allowlist.go
@@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_allow_list"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router"
@@ -45,7 +46,7 @@ type OnchainAllowlist interface {
}
type onchainAllowlist struct {
- utils.StartStopOnce
+ services.StateMachine
config OnchainAllowlistConfig
allowlist atomic.Pointer[map[common.Address]struct{}]
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index 7eb15ef6ff..01f450a4ea 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -12,6 +12,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -68,7 +69,7 @@ type FunctionsHandlerConfig struct {
}
type functionsHandler struct {
- utils.StartStopOnce
+ services.StateMachine
handlerConfig FunctionsHandlerConfig
donConfig *config.DONConfig
diff --git a/core/services/gateway/handlers/functions/subscriptions.go b/core/services/gateway/handlers/functions/subscriptions.go
index 181a98009f..79233b1031 100644
--- a/core/services/gateway/handlers/functions/subscriptions.go
+++ b/core/services/gateway/handlers/functions/subscriptions.go
@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -38,7 +39,7 @@ type OnchainSubscriptions interface {
}
type onchainSubscriptions struct {
- utils.StartStopOnce
+ services.StateMachine
config OnchainSubscriptionsConfig
subscriptions UserSubscriptions
diff --git a/core/services/gateway/network/httpserver.go b/core/services/gateway/network/httpserver.go
index d9d3e5ee7e..3cae8dc276 100644
--- a/core/services/gateway/network/httpserver.go
+++ b/core/services/gateway/network/httpserver.go
@@ -8,9 +8,9 @@ import (
"net/http"
"time"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
//go:generate mockery --quiet --name HttpServer --output ./mocks/ --case=underscore
@@ -44,7 +44,7 @@ type HTTPServerConfig struct {
}
type httpServer struct {
- utils.StartStopOnce
+ services.StateMachine
config *HTTPServerConfig
listener net.Listener
server *http.Server
diff --git a/core/services/gateway/network/wsconnection.go b/core/services/gateway/network/wsconnection.go
index 345d951ed4..9215d183d1 100644
--- a/core/services/gateway/network/wsconnection.go
+++ b/core/services/gateway/network/wsconnection.go
@@ -11,7 +11,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// WSConnectionWrapper is a websocket connection abstraction that supports re-connects.
@@ -42,7 +41,7 @@ type WSConnectionWrapper interface {
}
type wsConnectionWrapper struct {
- utils.StartStopOnce
+ services.StateMachine
lggr logger.Logger
conn atomic.Pointer[websocket.Conn]
diff --git a/core/services/gateway/network/wsserver.go b/core/services/gateway/network/wsserver.go
index 2fed4a9df4..86812a313e 100644
--- a/core/services/gateway/network/wsserver.go
+++ b/core/services/gateway/network/wsserver.go
@@ -10,9 +10,9 @@ import (
"github.com/gorilla/websocket"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
//go:generate mockery --quiet --name WebSocketServer --output ./mocks/ --case=underscore
@@ -29,7 +29,7 @@ type WebSocketServerConfig struct {
}
type webSocketServer struct {
- utils.StartStopOnce
+ services.StateMachine
config *WebSocketServerConfig
listener net.Listener
server *http.Server
diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go
index 200c25deb3..b2a8dad68f 100644
--- a/core/services/job/spawner.go
+++ b/core/services/job/spawner.go
@@ -43,6 +43,7 @@ type (
}
spawner struct {
+ relayservices.StateMachine
orm ORM
config Config
checker services.Checker
@@ -52,7 +53,6 @@ type (
q pg.Q
lggr logger.Logger
- utils.StartStopOnce
chStop utils.StopChan
lbDependentAwaiters []utils.DependentAwaiter
}
diff --git a/core/services/keeper/registry_synchronizer_core.go b/core/services/keeper/registry_synchronizer_core.go
index dea24f1a3b..761958ce19 100644
--- a/core/services/keeper/registry_synchronizer_core.go
+++ b/core/services/keeper/registry_synchronizer_core.go
@@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -36,7 +37,7 @@ type RegistrySynchronizerOptions struct {
}
type RegistrySynchronizer struct {
- utils.StartStopOnce
+ services.StateMachine
chStop chan struct{}
registryWrapper RegistryWrapper
interval time.Duration
diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go
index 435b245792..33ad8b7d77 100644
--- a/core/services/keeper/upkeep_executer.go
+++ b/core/services/keeper/upkeep_executer.go
@@ -12,6 +12,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
@@ -53,6 +54,7 @@ type UpkeepExecuterConfig interface {
// UpkeepExecuter implements the logic to communicate with KeeperRegistry
type UpkeepExecuter struct {
+ services.StateMachine
chStop utils.StopChan
ethClient evmclient.Client
config UpkeepExecuterConfig
@@ -66,7 +68,6 @@ type UpkeepExecuter struct {
logger logger.Logger
wgDone sync.WaitGroup
effectiveKeeperAddress common.Address
- utils.StartStopOnce
}
// NewUpkeepExecuter is the constructor of UpkeepExecuter
diff --git a/core/services/nurse.go b/core/services/nurse.go
index 33230ddae0..e414ca280e 100644
--- a/core/services/nurse.go
+++ b/core/services/nurse.go
@@ -17,13 +17,14 @@ import (
"github.com/google/pprof/profile"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
type Nurse struct {
- utils.StartStopOnce
+ services.StateMachine
cfg Config
log logger.Logger
diff --git a/core/services/ocr/config_overrider.go b/core/services/ocr/config_overrider.go
index 35d8e2a4c8..5b2ac20c00 100644
--- a/core/services/ocr/config_overrider.go
+++ b/core/services/ocr/config_overrider.go
@@ -9,15 +9,17 @@ import (
"time"
"github.com/pkg/errors"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
type ConfigOverriderImpl struct {
- utils.StartStopOnce
+ services.StateMachine
logger logger.Logger
flags *ContractFlags
contractAddress ethkey.EIP55Address
@@ -56,7 +58,7 @@ func NewConfigOverriderImpl(
ctx, cancel := context.WithCancel(context.Background())
co := ConfigOverriderImpl{
- utils.StartStopOnce{},
+ services.StateMachine{},
logger,
flags,
contractAddress,
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index a7df28e1c7..c5f3e431e4 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -20,6 +20,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting/confighelper"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
@@ -52,7 +53,7 @@ type (
// OCRContractTracker complies with ContractConfigTracker interface and
// handles log events related to the contract more generally
OCRContractTracker struct {
- utils.StartStopOnce
+ services.StateMachine
ethClient evmclient.Client
contract *offchain_aggregator_wrapper.OffchainAggregator
diff --git a/core/services/ocr2/plugins/median/plugin.go b/core/services/ocr2/plugins/median/plugin.go
index b78b75cbfc..f8517386b3 100644
--- a/core/services/ocr2/plugins/median/plugin.go
+++ b/core/services/ocr2/plugins/median/plugin.go
@@ -8,6 +8,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -48,7 +49,7 @@ func (p *Plugin) NewMedianFactory(ctx context.Context, provider types.MedianProv
}
type reportingPluginFactoryService struct {
- utils.StartStopOnce
+ services.StateMachine
lggr logger.Logger
ocrtypes.ReportingPluginFactory
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
index e32c4a0662..856e508fc5 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
@@ -10,16 +10,17 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
+
pluginutils "github.com/smartcontractkit/ocr2keepers/pkg/util"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
"github.com/smartcontractkit/ocr2keepers/pkg/v2/encoding"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type TransmitUnpacker interface {
@@ -27,7 +28,7 @@ type TransmitUnpacker interface {
}
type LogProvider struct {
- sync utils.StartStopOnce
+ sync services.StateMachine
mu sync.RWMutex
runState int
runError error
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
index 7d1de17a5b..49cab7b5a4 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
@@ -15,9 +15,11 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
"go.uber.org/multierr"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -25,7 +27,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
const (
@@ -135,7 +136,7 @@ type activeUpkeep struct {
type EvmRegistry struct {
HeadProvider
- sync utils.StartStopOnce
+ sync services.StateMachine
lggr logger.Logger
poller logpoller.LogPoller
addr common.Address
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
index 9766d98876..2d524e6f6c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
@@ -8,8 +8,10 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -34,7 +36,7 @@ var (
)
type BlockSubscriber struct {
- utils.StartStopOnce
+ services.StateMachine
threadCtrl utils.ThreadControl
mu sync.RWMutex
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
index b62fb37084..729bf4ade5 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
@@ -15,8 +15,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -81,7 +83,7 @@ var _ LogEventProviderTest = &logEventProvider{}
// logEventProvider manages log filters for upkeeps and enables to read the log events.
type logEventProvider struct {
- utils.StartStopOnce
+ services.StateMachine
threadCtrl utils.ThreadControl
lggr logger.Logger
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
index 3994f1d841..b74160ae91 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
@@ -15,9 +15,11 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+
"github.com/smartcontractkit/ocr2keepers/pkg/v3/random"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -63,7 +65,7 @@ type visitedRecord struct {
}
type logRecoverer struct {
- utils.StartStopOnce
+ services.StateMachine
threadCtrl utils.ThreadControl
lggr logger.Logger
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
index 1cad587e63..5d180c05b8 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
@@ -19,6 +19,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -128,7 +129,7 @@ type MercuryConfig struct {
}
type EvmRegistry struct {
- utils.StartStopOnce
+ services.StateMachine
threadCtrl utils.ThreadControl
lggr logger.Logger
poller logpoller.LogPoller
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
index b0ae2a7bf6..5fd320df8e 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
@@ -7,15 +7,16 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
+
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
var _ ocr2keepers.TransmitEventProvider = &EventProvider{}
@@ -23,7 +24,7 @@ var _ ocr2keepers.TransmitEventProvider = &EventProvider{}
type logParser func(registry *iregistry21.IKeeperRegistryMaster, log logpoller.Log) (transmitEventLog, error)
type EventProvider struct {
- sync utils.StartStopOnce
+ sync services.StateMachine
mu sync.RWMutex
runState int
runError error
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
index 34bd6822d6..6c5f767bd3 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
@@ -10,6 +10,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
@@ -59,7 +60,7 @@ type upkeepStateRecord struct {
// It stores the state of ineligible upkeeps in a local, in-memory cache.
// In addition, performed events are fetched by the scanner on demand.
type upkeepStateStore struct {
- utils.StartStopOnce
+ services.StateMachine
threadCtrl utils.ThreadControl
orm ORM
diff --git a/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go
index 1d2eca4666..0781303275 100644
--- a/core/services/ocrcommon/peer_wrapper.go
+++ b/core/services/ocrcommon/peer_wrapper.go
@@ -9,21 +9,22 @@ import (
p2ppeer "github.com/libp2p/go-libp2p-core/peer"
p2ppeerstore "github.com/libp2p/go-libp2p-core/peerstore"
"github.com/pkg/errors"
+ "go.uber.org/multierr"
+
ocrnetworking "github.com/smartcontractkit/libocr/networking"
ocrnetworkingtypes "github.com/smartcontractkit/libocr/networking/types"
ocr1types "github.com/smartcontractkit/libocr/offchainreporting/types"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/sqlx"
- "go.uber.org/multierr"
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"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"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type PeerWrapperOCRConfig interface {
@@ -43,7 +44,7 @@ type (
// SingletonPeerWrapper manages all libocr peers for the application
SingletonPeerWrapper struct {
- utils.StartStopOnce
+ services.StateMachine
keyStore keystore.Master
p2pCfg config.P2P
ocrCfg PeerWrapperOCRConfig
@@ -97,9 +98,7 @@ func NewSingletonPeerWrapper(keyStore keystore.Master, p2pCfg config.P2P, ocrCfg
}
}
-func (p *SingletonPeerWrapper) IsStarted() bool {
- return p.State() == utils.StartStopOnce_Started
-}
+func (p *SingletonPeerWrapper) IsStarted() bool { return p.Ready() == nil }
// Start starts SingletonPeerWrapper.
func (p *SingletonPeerWrapper) Start(context.Context) error {
diff --git a/core/services/ocrcommon/peerstore.go b/core/services/ocrcommon/peerstore.go
index 6bad2db4ee..f1c318a3bf 100644
--- a/core/services/ocrcommon/peerstore.go
+++ b/core/services/ocrcommon/peerstore.go
@@ -11,8 +11,10 @@ import (
"github.com/libp2p/go-libp2p-peerstore/pstoremem"
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/sqlx"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/recovery"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
@@ -30,7 +32,7 @@ type (
}
Pstorewrapper struct {
- utils.StartStopOnce
+ services.StateMachine
Peerstore p2ppeerstore.Peerstore
peerID string
q pg.Q
@@ -50,7 +52,7 @@ func NewPeerstoreWrapper(db *sqlx.DB, writeInterval time.Duration, peerID p2pkey
q := pg.NewQ(db, namedLogger, cfg)
return &Pstorewrapper{
- utils.StartStopOnce{},
+ services.StateMachine{},
pstoremem.NewPeerstore(),
peerID.Raw(),
q,
diff --git a/core/services/ocrcommon/run_saver.go b/core/services/ocrcommon/run_saver.go
index 3aa3aff876..d8dcc34358 100644
--- a/core/services/ocrcommon/run_saver.go
+++ b/core/services/ocrcommon/run_saver.go
@@ -3,13 +3,13 @@ package ocrcommon
import (
"context"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type RunResultSaver struct {
- utils.StartStopOnce
+ services.StateMachine
maxSuccessfulRuns uint64
runResults <-chan *pipeline.Run
diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go
index 29d1ad92e4..be139723ef 100644
--- a/core/services/ocrcommon/telemetry.go
+++ b/core/services/ocrcommon/telemetry.go
@@ -7,10 +7,13 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
+
+ "google.golang.org/protobuf/proto"
+
"github.com/smartcontractkit/libocr/commontypes"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "google.golang.org/protobuf/proto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
@@ -50,7 +53,7 @@ type EnhancedTelemetryMercuryData struct {
}
type EnhancedTelemetryService[T EnhancedTelemetryData | EnhancedTelemetryMercuryData] struct {
- utils.StartStopOnce
+ services.StateMachine
chTelem <-chan T
chDone chan struct{}
diff --git a/core/services/periodicbackup/backup.go b/core/services/periodicbackup/backup.go
index 8b9ff89cf4..f43698bbdb 100644
--- a/core/services/periodicbackup/backup.go
+++ b/core/services/periodicbackup/backup.go
@@ -11,11 +11,11 @@ import (
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/static"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
var (
@@ -37,18 +37,18 @@ type backupResult struct {
type (
DatabaseBackup interface {
- services.ServiceCtx
+ services.Service
RunBackup(version string) error
}
databaseBackup struct {
+ services.StateMachine
logger logger.Logger
databaseURL url.URL
mode config.DatabaseBackupMode
frequency time.Duration
outputParentDir string
done chan bool
- utils.StartStopOnce
}
BackupConfig interface {
@@ -77,13 +77,13 @@ func NewDatabaseBackup(dbUrl url.URL, rootDir string, backupConfig BackupConfig,
}
return &databaseBackup{
+ services.StateMachine{},
lggr,
dbUrl,
backupConfig.Mode(),
backupConfig.Frequency(),
outputParentDir,
make(chan bool),
- utils.StartStopOnce{},
}, nil
}
@@ -129,7 +129,7 @@ func (backup *databaseBackup) Name() string {
}
func (backup *databaseBackup) HealthReport() map[string]error {
- return map[string]error{backup.Name(): backup.StartStopOnce.Healthy()}
+ return map[string]error{backup.Name(): backup.Healthy()}
}
func (backup *databaseBackup) frequencyIsTooSmall() bool {
diff --git a/core/services/pg/event_broadcaster.go b/core/services/pg/event_broadcaster.go
index 3c74df6d74..f18ac3251a 100644
--- a/core/services/pg/event_broadcaster.go
+++ b/core/services/pg/event_broadcaster.go
@@ -11,8 +11,9 @@ import (
"github.com/lib/pq"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/static"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -23,12 +24,13 @@ import (
// EventBroadcaster opaquely manages a collection of Postgres event listeners
// and broadcasts events to subscribers (with an optional payload filter).
type EventBroadcaster interface {
- services.ServiceCtx
+ services.Service
Subscribe(channel, payloadFilter string) (Subscription, error)
Notify(channel string, payload string) error
}
type eventBroadcaster struct {
+ services.StateMachine
uri string
minReconnectInterval time.Duration
maxReconnectDuration time.Duration
@@ -39,7 +41,6 @@ type eventBroadcaster struct {
chStop chan struct{}
chDone chan struct{}
lggr logger.Logger
- utils.StartStopOnce
}
var _ EventBroadcaster = (*eventBroadcaster)(nil)
diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go
index f4e69df1ec..148901bb36 100644
--- a/core/services/pipeline/orm.go
+++ b/core/services/pipeline/orm.go
@@ -11,13 +11,13 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/sqlx"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- "github.com/smartcontractkit/sqlx"
)
// KeepersObservationSource is the same for all keeper jobs and it is not persisted in DB
@@ -74,7 +74,7 @@ const KeepersObservationSource = `
//go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore
type ORM interface {
- services.ServiceCtx
+ services.Service
CreateSpec(pipeline Pipeline, maxTaskTimeout models.Interval, qopts ...pg.QOpt) (int32, error)
CreateRun(run *Run, qopts ...pg.QOpt) (err error)
InsertRun(run *Run, qopts ...pg.QOpt) error
@@ -95,7 +95,7 @@ type ORM interface {
}
type orm struct {
- utils.StartStopOnce
+ services.StateMachine
q pg.Q
lggr logger.Logger
maxSuccessfulRuns uint64
@@ -111,7 +111,7 @@ var _ ORM = (*orm)(nil)
func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, jobPipelineMaxSuccessfulRuns uint64) *orm {
ctx, cancel := context.WithCancel(context.Background())
return &orm{
- utils.StartStopOnce{},
+ services.StateMachine{},
pg.NewQ(db, lggr, cfg),
lggr.Named("PipelineORM"),
jobPipelineMaxSuccessfulRuns,
diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go
index 20319682ef..3dbe94747e 100644
--- a/core/services/pipeline/runner.go
+++ b/core/services/pipeline/runner.go
@@ -14,13 +14,13 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/recovery"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
-
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -28,7 +28,7 @@ import (
//go:generate mockery --quiet --name Runner --output ./mocks/ --case=underscore
type Runner interface {
- services.ServiceCtx
+ services.Service
// Run is a blocking call that will execute the run until no further progress can be made.
// If `incomplete` is true, the run is only partially complete and is suspended, awaiting to be resumed when more data comes in.
@@ -52,6 +52,7 @@ type Runner interface {
}
type runner struct {
+ services.StateMachine
orm ORM
btORM bridges.ORM
config Config
@@ -67,7 +68,6 @@ type runner struct {
// test helper
runFinished func(*Run)
- utils.StartStopOnce
chStop utils.StopChan
wgDone sync.WaitGroup
}
@@ -150,7 +150,7 @@ func (r *runner) Name() string {
}
func (r *runner) HealthReport() map[string]error {
- return map[string]error{r.Name(): r.StartStopOnce.Healthy()}
+ return map[string]error{r.Name(): r.Healthy()}
}
func (r *runner) destroy() {
diff --git a/core/services/promreporter/prom_reporter.go b/core/services/promreporter/prom_reporter.go
index c0b48b46e3..fd6afeeb8e 100644
--- a/core/services/promreporter/prom_reporter.go
+++ b/core/services/promreporter/prom_reporter.go
@@ -13,6 +13,7 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -21,6 +22,7 @@ import (
//go:generate mockery --quiet --name PrometheusBackend --output ../../internal/mocks/ --case=underscore
type (
promReporter struct {
+ services.StateMachine
db *sql.DB
lggr logger.Logger
backend PrometheusBackend
@@ -28,8 +30,6 @@ type (
chStop utils.StopChan
wgDone sync.WaitGroup
reportPeriod time.Duration
-
- utils.StartStopOnce
}
PrometheusBackend interface {
@@ -130,7 +130,7 @@ func (pr *promReporter) Name() string {
}
func (pr *promReporter) HealthReport() map[string]error {
- return map[string]error{pr.Name(): pr.StartStopOnce.Healthy()}
+ return map[string]error{pr.Name(): pr.Healthy()}
}
func (pr *promReporter) OnNewLongestChain(ctx context.Context, head *evmtypes.Head) {
diff --git a/core/services/relay/evm/config_poller.go b/core/services/relay/evm/config_poller.go
index 504155bf1e..1cf2318b29 100644
--- a/core/services/relay/evm/config_poller.go
+++ b/core/services/relay/evm/config_poller.go
@@ -11,16 +11,17 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/gethwrappers2/ocrconfigurationstoreevmsimple"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
var (
@@ -89,7 +90,7 @@ func configFromLog(logData []byte) (ocrtypes.ContractConfig, error) {
}
type configPoller struct {
- utils.StartStopOnce
+ services.StateMachine
lggr logger.Logger
filterName string
diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go
index e7a2bca344..3f45b41f46 100644
--- a/core/services/relay/evm/evm.go
+++ b/core/services/relay/evm/evm.go
@@ -42,7 +42,6 @@ import (
reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
var _ relaytypes.Relayer = &Relayer{} //nolint:staticcheck
@@ -238,7 +237,7 @@ func FilterNamesFromRelayArgs(args relaytypes.RelayArgs) (filterNames []string,
}
type configWatcher struct {
- utils.StartStopOnce
+ services.StateMachine
lggr logger.Logger
contractAddress common.Address
contractABI abi.ABI
@@ -263,7 +262,6 @@ func newConfigWatcher(lggr logger.Logger,
) *configWatcher {
replayCtx, replayCancel := context.WithCancel(context.Background())
return &configWatcher{
- StartStopOnce: utils.StartStopOnce{},
lggr: lggr.Named("ConfigWatcher").Named(contractAddress.String()),
contractAddress: contractAddress,
contractABI: contractABI,
@@ -274,7 +272,6 @@ func newConfigWatcher(lggr logger.Logger,
fromBlock: fromBlock,
replayCtx: replayCtx,
replayCancel: replayCancel,
- wg: sync.WaitGroup{},
}
}
@@ -312,7 +309,7 @@ func (c *configWatcher) Close() error {
}
func (c *configWatcher) HealthReport() map[string]error {
- return map[string]error{c.Name(): c.StartStopOnce.Healthy()}
+ return map[string]error{c.Name(): c.Healthy()}
}
func (c *configWatcher) OffchainConfigDigester() ocrtypes.OffchainConfigDigester {
diff --git a/core/services/relay/evm/functions.go b/core/services/relay/evm/functions.go
index 43a3d2ff86..fdd6201c69 100644
--- a/core/services/relay/evm/functions.go
+++ b/core/services/relay/evm/functions.go
@@ -9,11 +9,14 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"go.uber.org/multierr"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -24,11 +27,10 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
functionsRelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions"
evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type functionsProvider struct {
- utils.StartStopOnce
+ services.StateMachine
configWatcher *configWatcher
contractTransmitter ContractTransmitter
logPollerWrapper evmRelayTypes.LogPollerWrapper
diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go
index db2c7fd68c..777717d01c 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper.go
@@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator"
@@ -21,7 +22,7 @@ import (
)
type logPollerWrapper struct {
- utils.StartStopOnce
+ services.StateMachine
routerContract *functions_router.FunctionsRouter
pluginConfig config.PluginConfig
diff --git a/core/services/relay/evm/mercury/persistence_manager.go b/core/services/relay/evm/mercury/persistence_manager.go
index 1c8dad4530..9de1f80c6b 100644
--- a/core/services/relay/evm/mercury/persistence_manager.go
+++ b/core/services/relay/evm/mercury/persistence_manager.go
@@ -7,6 +7,7 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb"
@@ -22,7 +23,7 @@ type PersistenceManager struct {
lggr logger.Logger
orm ORM
- once utils.StartStopOnce
+ once services.StateMachine
stopCh utils.StopChan
wg sync.WaitGroup
diff --git a/core/services/relay/evm/mercury/queue.go b/core/services/relay/evm/mercury/queue.go
index 44042c5772..3d20b3f2b0 100644
--- a/core/services/relay/evm/mercury/queue.go
+++ b/core/services/relay/evm/mercury/queue.go
@@ -13,8 +13,9 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -24,7 +25,7 @@ type asyncDeleter interface {
AsyncDelete(req *pb.TransmitRequest)
}
-var _ services.ServiceCtx = (*TransmitQueue)(nil)
+var _ services.Service = (*TransmitQueue)(nil)
var transmitQueueLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "mercury_transmit_queue_load",
@@ -40,7 +41,7 @@ const promInterval = 6500 * time.Millisecond
// TransmitQueue is the high-level package that everything outside of this file should be using
// It stores pending transmissions, yielding the latest (highest priority) first to the caller
type TransmitQueue struct {
- utils.StartStopOnce
+ services.StateMachine
cond sync.Cond
lggr logger.Logger
@@ -68,7 +69,7 @@ func NewTransmitQueue(lggr logger.Logger, feedID string, maxlen int, transmissio
heap.Init(&pq) // ensure the heap is ordered
mu := new(sync.RWMutex)
return &TransmitQueue{
- utils.StartStopOnce{},
+ services.StateMachine{},
sync.Cond{L: mu},
lggr.Named("TransmitQueue"),
asyncDeleter,
diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go
index 0c2721442b..88c3113abc 100644
--- a/core/services/relay/evm/mercury/transmitter.go
+++ b/core/services/relay/evm/mercury/transmitter.go
@@ -84,7 +84,7 @@ type TransmitterReportDecoder interface {
var _ Transmitter = (*mercuryTransmitter)(nil)
type mercuryTransmitter struct {
- utils.StartStopOnce
+ services.StateMachine
lggr logger.Logger
rpcClient wsrpc.Client
cfgTracker ConfigTracker
@@ -127,7 +127,7 @@ func NewTransmitter(lggr logger.Logger, cfgTracker ConfigTracker, rpcClient wsrp
feedIDHex := fmt.Sprintf("0x%x", feedID[:])
persistenceManager := NewPersistenceManager(lggr, NewORM(db, lggr, cfg), jobID, maxTransmitQueueSize, flushDeletesFrequency, pruneFrequency)
return &mercuryTransmitter{
- utils.StartStopOnce{},
+ services.StateMachine{},
lggr.Named("MercuryTransmitter").With("feedID", feedIDHex),
rpcClient,
cfgTracker,
diff --git a/core/services/relay/evm/mercury/wsrpc/client.go b/core/services/relay/evm/mercury/wsrpc/client.go
index fb9a57d9a2..f6ed1d0db8 100644
--- a/core/services/relay/evm/mercury/wsrpc/client.go
+++ b/core/services/relay/evm/mercury/wsrpc/client.go
@@ -11,11 +11,13 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+
"github.com/smartcontractkit/wsrpc"
"github.com/smartcontractkit/wsrpc/connectivity"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -59,7 +61,7 @@ var (
)
type Client interface {
- services.ServiceCtx
+ services.Service
pb.MercuryClient
}
@@ -70,7 +72,7 @@ type Conn interface {
}
type client struct {
- utils.StartStopOnce
+ services.StateMachine
csaKey csakey.KeyV2
serverPubKey []byte
@@ -211,7 +213,7 @@ func (w *client) HealthReport() map[string]error {
// Healthy if connected
func (w *client) Healthy() (err error) {
- if err = w.StartStopOnce.Healthy(); err != nil {
+ if err = w.StateMachine.Healthy(); err != nil {
return err
}
state := w.conn.GetState()
diff --git a/core/services/relay/evm/request_round_tracker.go b/core/services/relay/evm/request_round_tracker.go
index 3507f1dfa8..4e065f2dfd 100644
--- a/core/services/relay/evm/request_round_tracker.go
+++ b/core/services/relay/evm/request_round_tracker.go
@@ -8,22 +8,23 @@ import (
gethCommon "github.com/ethereum/go-ethereum/common"
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/sqlx"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// RequestRoundTracker subscribes to new request round logs.
type RequestRoundTracker struct {
- utils.StartStopOnce
+ services.StateMachine
ethClient evmclient.Client
contract *offchain_aggregator_wrapper.OffchainAggregator
diff --git a/core/services/synchronization/telemetry_ingress_batch_client.go b/core/services/synchronization/telemetry_ingress_batch_client.go
index 4924bb2cd5..26abda65d3 100644
--- a/core/services/synchronization/telemetry_ingress_batch_client.go
+++ b/core/services/synchronization/telemetry_ingress_batch_client.go
@@ -12,10 +12,10 @@ import (
"github.com/smartcontractkit/wsrpc"
"github.com/smartcontractkit/wsrpc/examples/simple/keys"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// NoopTelemetryIngressBatchClient is a no-op interface for TelemetryIngressBatchClient
@@ -37,7 +37,7 @@ func (NoopTelemetryIngressBatchClient) Name() string { return
func (NoopTelemetryIngressBatchClient) Ready() error { return nil }
type telemetryIngressBatchClient struct {
- utils.StartStopOnce
+ services.StateMachine
url *url.URL
ks keystore.CSA
serverPubKeyHex string
diff --git a/core/services/synchronization/telemetry_ingress_client.go b/core/services/synchronization/telemetry_ingress_client.go
index 1db4f69afd..9458b7627c 100644
--- a/core/services/synchronization/telemetry_ingress_client.go
+++ b/core/services/synchronization/telemetry_ingress_client.go
@@ -11,6 +11,7 @@ import (
"github.com/smartcontractkit/wsrpc"
"github.com/smartcontractkit/wsrpc/examples/simple/keys"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
@@ -35,7 +36,7 @@ func (NoopTelemetryIngressClient) Name() string { return "Noop
func (NoopTelemetryIngressClient) Ready() error { return nil }
type telemetryIngressClient struct {
- utils.StartStopOnce
+ services.StateMachine
url *url.URL
ks keystore.CSA
serverPubKeyHex string
diff --git a/core/services/telemetry/manager.go b/core/services/telemetry/manager.go
index 3818341f5b..2931ec71a1 100644
--- a/core/services/telemetry/manager.go
+++ b/core/services/telemetry/manager.go
@@ -8,14 +8,15 @@ import (
"time"
"github.com/pkg/errors"
- "github.com/smartcontractkit/libocr/commontypes"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/libocr/commontypes"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"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/synchronization"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
//// Client encapsulates all the functionality needed to
@@ -26,7 +27,7 @@ import (
//}
type Manager struct {
- utils.StartStopOnce
+ services.StateMachine
bufferSize uint
endpoints []*telemetryEndpoint
ks keystore.CSA
@@ -67,7 +68,7 @@ func (l *legacyEndpointConfig) URL() *url.URL {
}
type telemetryEndpoint struct {
- utils.StartStopOnce
+ services.StateMachine
ChainID string
Network string
URL *url.URL
@@ -143,7 +144,7 @@ func (m *Manager) HealthReport() map[string]error {
hr[m.lggr.Name()] = m.Healthy()
for _, e := range m.endpoints {
name := fmt.Sprintf("%s.%s.%s", m.lggr.Name(), e.Network, e.ChainID)
- hr[name] = e.StartStopOnce.Healthy()
+ hr[name] = e.Healthy()
}
return hr
}
diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go
index 4aaf328015..69746625dd 100644
--- a/core/services/telemetry/manager_test.go
+++ b/core/services/telemetry/manager_test.go
@@ -15,6 +15,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/config/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
@@ -24,7 +25,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization"
mocks2 "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/mocks"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
func setupMockConfig(t *testing.T, useBatchSend bool) *mocks.TelemetryIngress {
@@ -246,10 +246,10 @@ func TestCorrectEndpointRouting(t *testing.T) {
})
tm.endpoints[i] = &telemetryEndpoint{
- StartStopOnce: utils.StartStopOnce{},
- ChainID: e.chainID,
- Network: e.network,
- client: clientMock,
+ StateMachine: services.StateMachine{},
+ ChainID: e.chainID,
+ Network: e.network,
+ client: clientMock,
}
}
diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go
index 03b92bc15c..613c0d124d 100644
--- a/core/services/vrf/v1/listener_v1.go
+++ b/core/services/vrf/v1/listener_v1.go
@@ -13,6 +13,7 @@ import (
heaps "github.com/theodesp/go-heaps"
"github.com/theodesp/go-heaps/pairing"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
@@ -43,7 +44,7 @@ type request struct {
}
type Listener struct {
- utils.StartStopOnce
+ services.StateMachine
Cfg vrfcommon.Config
FeeCfg vrfcommon.FeeConfig
diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go
index 31e76b48fd..7560baad3a 100644
--- a/core/services/vrf/v2/listener_v2.go
+++ b/core/services/vrf/v2/listener_v2.go
@@ -23,6 +23,7 @@ import (
"github.com/theodesp/go-heaps/pairing"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
@@ -191,7 +192,7 @@ type vrfPipelineResult struct {
}
type listenerV2 struct {
- utils.StartStopOnce
+ services.StateMachine
cfg vrfcommon.Config
feeCfg vrfcommon.FeeConfig
l logger.SugaredLogger
diff --git a/core/utils/helpers_test.go b/core/utils/helpers_test.go
deleted file mode 100644
index d317994cde..0000000000
--- a/core/utils/helpers_test.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package utils
-
-func (once *StartStopOnce) LoadState() StartStopOnceState {
- return StartStopOnceState(once.state.Load())
-}
diff --git a/core/utils/mailbox_prom.go b/core/utils/mailbox_prom.go
index 0291a51d2c..dc20db84d9 100644
--- a/core/utils/mailbox_prom.go
+++ b/core/utils/mailbox_prom.go
@@ -9,6 +9,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
)
var mailboxLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{
@@ -21,7 +23,7 @@ var mailboxLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{
const mailboxPromInterval = 5 * time.Second
type MailboxMonitor struct {
- StartStopOnce
+ services.StateMachine
appID string
mailboxes sync.Map
diff --git a/core/utils/sleeper_task.go b/core/utils/sleeper_task.go
index 0b45507a82..fcec254249 100644
--- a/core/utils/sleeper_task.go
+++ b/core/utils/sleeper_task.go
@@ -3,6 +3,8 @@ package utils
import (
"fmt"
"time"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
)
// SleeperTask represents a task that waits in the background to process some work.
@@ -19,12 +21,12 @@ type Worker interface {
}
type sleeperTask struct {
+ services.StateMachine
worker Worker
chQueue chan struct{}
chStop chan struct{}
chDone chan struct{}
chWorkDone chan struct{}
- StartStopOnce
}
// NewSleeperTask takes a worker and returns a SleeperTask.
@@ -76,13 +78,14 @@ func (s *sleeperTask) WakeUpIfStarted() {
// WakeUp wakes up the sleeper task, asking it to execute its Worker.
func (s *sleeperTask) WakeUp() {
- if s.StartStopOnce.State() == StartStopOnce_Stopped {
+ if !s.IfStarted(func() {
+ select {
+ case s.chQueue <- struct{}{}:
+ default:
+ }
+ }) {
panic("cannot wake up stopped sleeper task")
}
- select {
- case s.chQueue <- struct{}{}:
- default:
- }
}
func (s *sleeperTask) workDone() {
diff --git a/core/utils/utils.go b/core/utils/utils.go
index d96546b3e1..b8515f3362 100644
--- a/core/utils/utils.go
+++ b/core/utils/utils.go
@@ -31,6 +31,8 @@ import (
"github.com/robfig/cron/v3"
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/sha3"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
)
const (
@@ -819,14 +821,6 @@ func EVMBytesToUint64(buf []byte) uint64 {
return result
}
-type errNotStarted struct {
- state StartStopOnceState
-}
-
-func (e *errNotStarted) Error() string {
- return fmt.Sprintf("service is %q, not started", e.state)
-}
-
var (
ErrAlreadyStopped = errors.New("already stopped")
ErrCannotStopUnstarted = errors.New("cannot stop unstarted service")
@@ -834,176 +828,7 @@ var (
// StartStopOnce contains a StartStopOnceState integer
// Deprecated: use services.StateMachine
-type StartStopOnce struct {
- state atomic.Int32
- sync.RWMutex // lock is held during startup/shutdown, RLock is held while executing functions dependent on a particular state
-
- // SvcErrBuffer is an ErrorBuffer that let service owners track critical errors happening in the service.
- //
- // SvcErrBuffer.SetCap(int) Overrides buffer limit from defaultErrorBufferCap
- // SvcErrBuffer.Append(error) Appends an error to the buffer
- // SvcErrBuffer.Flush() error returns all tracked errors as a single joined error
- SvcErrBuffer ErrorBuffer
-}
-
-// StartStopOnceState holds the state for StartStopOnce
-type StartStopOnceState int32
-
-// nolint
-const (
- StartStopOnce_Unstarted StartStopOnceState = iota
- StartStopOnce_Started
- StartStopOnce_Starting
- StartStopOnce_StartFailed
- StartStopOnce_Stopping
- StartStopOnce_Stopped
- StartStopOnce_StopFailed
-)
-
-func (s StartStopOnceState) String() string {
- switch s {
- case StartStopOnce_Unstarted:
- return "Unstarted"
- case StartStopOnce_Started:
- return "Started"
- case StartStopOnce_Starting:
- return "Starting"
- case StartStopOnce_StartFailed:
- return "StartFailed"
- case StartStopOnce_Stopping:
- return "Stopping"
- case StartStopOnce_Stopped:
- return "Stopped"
- case StartStopOnce_StopFailed:
- return "StopFailed"
- default:
- return fmt.Sprintf("unrecognized state: %d", s)
- }
-}
-
-// StartOnce sets the state to Started
-func (once *StartStopOnce) StartOnce(name string, fn func() error) error {
- // SAFETY: We do this compare-and-swap outside of the lock so that
- // concurrent StartOnce() calls return immediately.
- success := once.state.CompareAndSwap(int32(StartStopOnce_Unstarted), int32(StartStopOnce_Starting))
-
- if !success {
- return pkgerrors.Errorf("%v has already been started once; state=%v", name, StartStopOnceState(once.state.Load()))
- }
-
- once.Lock()
- defer once.Unlock()
-
- // Setting cap before calling startup fn in case of crits in startup
- once.SvcErrBuffer.SetCap(defaultErrorBufferCap)
- err := fn()
-
- if err == nil {
- success = once.state.CompareAndSwap(int32(StartStopOnce_Starting), int32(StartStopOnce_Started))
- } else {
- success = once.state.CompareAndSwap(int32(StartStopOnce_Starting), int32(StartStopOnce_StartFailed))
- }
-
- if !success {
- // SAFETY: If this is reached, something must be very wrong: once.state
- // was tampered with outside of the lock.
- panic(fmt.Sprintf("%v entered unreachable state, unable to set state to started", name))
- }
-
- return err
-}
-
-// StopOnce sets the state to Stopped
-func (once *StartStopOnce) StopOnce(name string, fn func() error) error {
- // SAFETY: We hold the lock here so that Stop blocks until StartOnce
- // executes. This ensures that a very fast call to Stop will wait for the
- // code to finish starting up before teardown.
- once.Lock()
- defer once.Unlock()
-
- success := once.state.CompareAndSwap(int32(StartStopOnce_Started), int32(StartStopOnce_Stopping))
-
- if !success {
- state := once.state.Load()
- switch state {
- case int32(StartStopOnce_Stopped):
- return pkgerrors.Wrapf(ErrAlreadyStopped, "%s has already been stopped", name)
- case int32(StartStopOnce_Unstarted):
- return pkgerrors.Wrapf(ErrCannotStopUnstarted, "%s has not been started", name)
- default:
- return pkgerrors.Errorf("%v cannot be stopped from this state; state=%v", name, StartStopOnceState(state))
- }
- }
-
- err := fn()
-
- if err == nil {
- success = once.state.CompareAndSwap(int32(StartStopOnce_Stopping), int32(StartStopOnce_Stopped))
- } else {
- success = once.state.CompareAndSwap(int32(StartStopOnce_Stopping), int32(StartStopOnce_StopFailed))
- }
-
- if !success {
- // SAFETY: If this is reached, something must be very wrong: once.state
- // was tampered with outside of the lock.
- panic(fmt.Sprintf("%v entered unreachable state, unable to set state to stopped", name))
- }
-
- return err
-}
-
-// State retrieves the current state
-func (once *StartStopOnce) State() StartStopOnceState {
- state := once.state.Load()
- return StartStopOnceState(state)
-}
-
-// IfStarted runs the func and returns true only if started, otherwise returns false
-func (once *StartStopOnce) IfStarted(f func()) (ok bool) {
- once.RLock()
- defer once.RUnlock()
-
- state := once.state.Load()
-
- if StartStopOnceState(state) == StartStopOnce_Started {
- f()
- return true
- }
- return false
-}
-
-// IfNotStopped runs the func and returns true if in any state other than Stopped
-func (once *StartStopOnce) IfNotStopped(f func()) (ok bool) {
- once.RLock()
- defer once.RUnlock()
-
- state := once.state.Load()
-
- if StartStopOnceState(state) == StartStopOnce_Stopped {
- return false
- }
- f()
- return true
-}
-
-// Ready returns ErrNotStarted if the state is not started.
-func (once *StartStopOnce) Ready() error {
- state := once.State()
- if state == StartStopOnce_Started {
- return nil
- }
- return &errNotStarted{state: state}
-}
-
-// Healthy returns ErrNotStarted if the state is not started.
-// Override this per-service with more specific implementations.
-func (once *StartStopOnce) Healthy() error {
- state := once.State()
- if state == StartStopOnce_Started {
- return once.SvcErrBuffer.Flush()
- }
- return &errNotStarted{state: state}
-}
+type StartStopOnce = services.StateMachine
// EnsureClosed closes the io.Closer, returning nil if it was already
// closed or not started yet
diff --git a/core/utils/utils_test.go b/core/utils/utils_test.go
index 5d728d14f4..04802feb3a 100644
--- a/core/utils/utils_test.go
+++ b/core/utils/utils_test.go
@@ -724,111 +724,6 @@ func TestContextFromChanWithTimeout(t *testing.T) {
})
}
-func TestStartStopOnceState_String(t *testing.T) {
- t.Parallel()
-
- assert.Equal(t, "Unstarted", utils.StartStopOnce_Unstarted.String())
- assert.Equal(t, "Started", utils.StartStopOnce_Started.String())
- assert.Equal(t, "Starting", utils.StartStopOnce_Starting.String())
- assert.Equal(t, "Stopping", utils.StartStopOnce_Stopping.String())
- assert.Equal(t, "Stopped", utils.StartStopOnce_Stopped.String())
- assert.Equal(t, "unrecognized state: 123", utils.StartStopOnceState(123).String())
-}
-
-func TestStartStopOnce(t *testing.T) {
- t.Parallel()
-
- var callsCount atomic.Int32
- incCount := func() {
- callsCount.Add(1)
- }
-
- var s utils.StartStopOnce
- ok := s.IfStarted(incCount)
- assert.False(t, ok)
- ok = s.IfNotStopped(incCount)
- assert.True(t, ok)
- assert.Equal(t, int32(1), callsCount.Load())
-
- err := s.StartOnce("foo", func() error { return nil })
- assert.NoError(t, err)
-
- assert.True(t, s.IfStarted(incCount))
- assert.Equal(t, int32(2), callsCount.Load())
-
- err = s.StopOnce("foo", func() error { return nil })
- assert.NoError(t, err)
- ok = s.IfNotStopped(incCount)
- assert.False(t, ok)
- assert.Equal(t, int32(2), callsCount.Load())
-}
-
-func TestStartStopOnce_StartErrors(t *testing.T) {
- var s utils.StartStopOnce
-
- err := s.StartOnce("foo", func() error { return errors.New("foo") })
- assert.Error(t, err)
-
- var callsCount atomic.Int32
- incCount := func() {
- callsCount.Add(1)
- }
-
- assert.False(t, s.IfStarted(incCount))
- assert.Equal(t, int32(0), callsCount.Load())
-
- err = s.StartOnce("foo", func() error { return nil })
- require.Error(t, err)
- assert.Contains(t, err.Error(), "foo has already been started once")
- err = s.StopOnce("foo", func() error { return nil })
- require.Error(t, err)
- assert.Contains(t, err.Error(), "foo cannot be stopped from this state; state=StartFailed")
-
- assert.Equal(t, utils.StartStopOnce_StartFailed, s.LoadState())
-}
-
-func TestStartStopOnce_StopErrors(t *testing.T) {
- var s utils.StartStopOnce
-
- err := s.StartOnce("foo", func() error { return nil })
- require.NoError(t, err)
-
- var callsCount atomic.Int32
- incCount := func() {
- callsCount.Add(1)
- }
-
- err = s.StopOnce("foo", func() error { return errors.New("explodey mcsplode") })
- assert.Error(t, err)
-
- assert.False(t, s.IfStarted(incCount))
- assert.Equal(t, int32(0), callsCount.Load())
- assert.True(t, s.IfNotStopped(incCount))
- assert.Equal(t, int32(1), callsCount.Load())
-
- err = s.StartOnce("foo", func() error { return nil })
- require.Error(t, err)
- assert.Contains(t, err.Error(), "foo has already been started once")
- err = s.StopOnce("foo", func() error { return nil })
- require.Error(t, err)
- assert.Contains(t, err.Error(), "foo cannot be stopped from this state; state=StopFailed")
-
- assert.Equal(t, utils.StartStopOnce_StopFailed, s.LoadState())
-}
-
-func TestStartStopOnce_Ready_Healthy(t *testing.T) {
- t.Parallel()
-
- var s utils.StartStopOnce
- assert.Error(t, s.Ready())
- assert.Error(t, s.Healthy())
-
- err := s.StartOnce("foo", func() error { return nil })
- assert.NoError(t, err)
- assert.NoError(t, s.Ready())
- assert.NoError(t, s.Healthy())
-}
-
func TestLeftPadBitString(t *testing.T) {
t.Parallel()
diff --git a/go.mod b/go.mod
index 3679c79ed0..14f195d495 100644
--- a/go.mod
+++ b/go.mod
@@ -68,7 +68,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index e2bc661048..c9700330fa 100644
--- a/go.sum
+++ b/go.sum
@@ -1459,8 +1459,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index c1a8cdb61c..21ce192126 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -384,7 +384,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 77778de9d2..64305ddc24 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2362,8 +2362,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04 h1:QFMxPq7AqU4qXeW7UBv0eP/mpLt2pG2QkASUyFjKoIE=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231027131428-7dc07d302a04/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From e3caf761e9f036b351d5f4ab686892c4f7d7da42 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Mon, 30 Oct 2023 13:15:35 -0500
Subject: [PATCH 033/327] core/chains/cosmos/cosmostxm: simplifications
(#11101)
---
core/chains/cosmos/chain.go | 102 +++++--
core/chains/cosmos/config.go | 272 ------------------
core/chains/cosmos/config_test.go | 96 -------
core/chains/cosmos/cosmostxm/helpers_test.go | 32 +--
core/chains/cosmos/cosmostxm/key_wrapper.go | 6 +-
.../cosmos/cosmostxm/keystore_adapter.go | 16 +-
core/chains/cosmos/cosmostxm/orm_test.go | 5 +-
core/chains/cosmos/cosmostxm/txm.go | 4 +-
.../cosmos/cosmostxm/txm_internal_test.go | 122 ++++----
core/chains/cosmos/cosmostxm/txm_test.go | 265 ++++++++---------
core/cmd/cosmos_chains_commands_test.go | 4 +-
core/cmd/cosmos_node_commands_test.go | 13 +-
core/cmd/cosmos_transaction_commands_test.go | 61 +---
core/cmd/shell.go | 2 +-
core/config/docs/docs_test.go | 4 +-
core/internal/cltest/cltest.go | 2 +-
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
core/services/chainlink/config.go | 6 +-
core/services/chainlink/config_general.go | 4 +-
core/services/chainlink/config_test.go | 7 +-
.../chainlink/mocks/general_config.go | 10 +-
.../relayer_chain_interoperators_test.go | 15 +-
core/services/chainlink/relayer_factory.go | 7 +-
core/services/chainlink/types.go | 4 +-
core/web/cosmos_chains_controller_test.go | 9 +-
core/web/cosmos_transfer_controller.go | 108 +++----
core/web/presenters/cosmos_msg.go | 4 +-
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
32 files changed, 377 insertions(+), 821 deletions(-)
delete mode 100644 core/chains/cosmos/config.go
delete mode 100644 core/chains/cosmos/config_test.go
diff --git a/core/chains/cosmos/chain.go b/core/chains/cosmos/chain.go
index bb44c4bee6..e11f95d356 100644
--- a/core/chains/cosmos/chain.go
+++ b/core/chains/cosmos/chain.go
@@ -7,35 +7,38 @@ import (
"math/big"
"time"
+ "github.com/pelletier/go-toml/v2"
"github.com/pkg/errors"
"go.uber.org/multierr"
sdk "github.com/cosmos/cosmos-sdk/types"
+ bank "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/smartcontractkit/sqlx"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
- cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
relaychains "github.com/smartcontractkit/chainlink-relay/pkg/chains"
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/smartcontractkit/chainlink/v2/core/services/relay"
)
-// DefaultRequestTimeout is the default Cosmos client timeout.
+// defaultRequestTimeout is the default Cosmos client timeout.
// Note that while the cosmos node is processing a heavy block,
// requests can be delayed significantly (https://github.com/tendermint/tendermint/issues/6899),
// however there's nothing we can do but wait until the block is processed.
// So we set a fairly high timeout here.
// TODO(BCI-979): Remove this, or make this configurable with the updated client.
-const DefaultRequestTimeout = 30 * time.Second
+const defaultRequestTimeout = 30 * time.Second
var (
// ErrChainIDEmpty is returned when chain is required but was empty.
@@ -78,7 +81,7 @@ func (o *ChainOpts) Validate() (err error) {
return
}
-func NewChain(cfg *CosmosConfig, opts ChainOpts) (adapters.Chain, error) {
+func NewChain(cfg *coscfg.TOMLConfig, opts ChainOpts) (adapters.Chain, error) {
if !cfg.IsEnabled() {
return nil, fmt.Errorf("cannot create new chain with ID %s, the chain is disabled", *cfg.ChainID)
}
@@ -94,23 +97,23 @@ var _ adapters.Chain = (*chain)(nil)
type chain struct {
services.StateMachine
id string
- cfg *CosmosConfig
+ cfg *coscfg.TOMLConfig
txm *cosmostxm.Txm
lggr logger.Logger
}
-func newChain(id string, cfg *CosmosConfig, db *sqlx.DB, ks loop.Keystore, logCfg pg.QConfig, eb pg.EventBroadcaster, lggr logger.Logger) (*chain, error) {
+func newChain(id string, cfg *coscfg.TOMLConfig, db *sqlx.DB, ks loop.Keystore, logCfg pg.QConfig, eb pg.EventBroadcaster, lggr logger.Logger) (*chain, error) {
lggr = logger.With(lggr, "cosmosChainID", id)
var ch = chain{
id: id,
cfg: cfg,
lggr: logger.Named(lggr, "Chain"),
}
- tc := func() (cosmosclient.ReaderWriter, error) {
+ tc := func() (client.ReaderWriter, error) {
return ch.getClient("")
}
- gpe := cosmosclient.NewMustGasPriceEstimator([]cosmosclient.GasPricesEstimator{
- cosmosclient.NewClosureGasPriceEstimator(func() (map[string]sdk.DecCoin, error) {
+ gpe := client.NewMustGasPriceEstimator([]client.GasPricesEstimator{
+ client.NewClosureGasPriceEstimator(func() (map[string]sdk.DecCoin, error) {
return map[string]sdk.DecCoin{
cfg.GasToken(): sdk.NewDecCoinFromDec(cfg.GasToken(), cfg.FallbackGasPrice()),
}, nil
@@ -141,12 +144,12 @@ func (c *chain) TxManager() adapters.TxManager {
return c.txm
}
-func (c *chain) Reader(name string) (cosmosclient.Reader, error) {
+func (c *chain) Reader(name string) (client.Reader, error) {
return c.getClient(name)
}
// getClient returns a client, optionally requiring a specific node by name.
-func (c *chain) getClient(name string) (cosmosclient.ReaderWriter, error) {
+func (c *chain) getClient(name string) (client.ReaderWriter, error) {
var node db.Node
if name == "" { // Any node
nodes, err := c.cfg.ListNodes()
@@ -171,7 +174,7 @@ func (c *chain) getClient(name string) (cosmosclient.ReaderWriter, error) {
return nil, fmt.Errorf("failed to create client for chain %s with node %s: wrong chain id %s", c.id, name, node.CosmosChainID)
}
}
- client, err := cosmosclient.NewClient(c.id, node.TendermintURL, DefaultRequestTimeout, logger.Named(c.lggr, "Client."+name))
+ client, err := client.NewClient(c.id, node.TendermintURL, defaultRequestTimeout, logger.Named(c.lggr, "Client."+name))
if err != nil {
return nil, fmt.Errorf("failed to create client: %w", err)
}
@@ -224,7 +227,41 @@ func (c *chain) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken
}
func (c *chain) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error {
- return chains.ErrLOOPPUnsupported
+ fromAcc, err := sdk.AccAddressFromBech32(from)
+ if err != nil {
+ return fmt.Errorf("failed to parse from account: %s", fromAcc)
+ }
+ toAcc, err := sdk.AccAddressFromBech32(to)
+ if err != nil {
+ return fmt.Errorf("failed to parse from account: %s", toAcc)
+ }
+ coin := sdk.Coin{Amount: sdk.NewIntFromBigInt(amount), Denom: c.Config().GasToken()}
+
+ txm := c.TxManager()
+
+ if balanceCheck {
+ var reader client.Reader
+ reader, err = c.Reader("")
+ if err != nil {
+ return fmt.Errorf("chain unreachable: %v", err)
+ }
+ gasPrice, err2 := txm.GasPrice()
+ if err2 != nil {
+ return fmt.Errorf("gas price unavailable: %v", err2)
+ }
+
+ err = validateBalance(reader, gasPrice, fromAcc, coin)
+ if err != nil {
+ return fmt.Errorf("failed to validate balance: %v", err)
+ }
+ }
+
+ sendMsg := bank.NewMsgSend(fromAcc, toAcc, sdk.Coins{coin})
+ _, err = txm.Enqueue("", sendMsg)
+ if err != nil {
+ return fmt.Errorf("failed to enqueue tx: %w", err)
+ }
+ return nil
}
// TODO BCF-2602 statuses are static for non-evm chain and should be dynamic
@@ -247,3 +284,34 @@ func (c *chain) listNodeStatuses(start, end int) ([]relaytypes.NodeStatus, int,
}
return stats, total, nil
}
+
+func nodeStatus(n *coscfg.Node, id relay.ChainID) (relaytypes.NodeStatus, error) {
+ var s relaytypes.NodeStatus
+ s.ChainID = id
+ s.Name = *n.Name
+ b, err := toml.Marshal(n)
+ if err != nil {
+ return relaytypes.NodeStatus{}, err
+ }
+ s.Config = string(b)
+ return s, nil
+}
+
+// maxGasUsedTransfer is an upper bound on how much gas we expect a MsgSend for a single coin to use.
+const maxGasUsedTransfer = 100_000
+
+// validateBalance validates that fromAddr's balance can cover coin, including fees at gasPrice.
+func validateBalance(reader client.Reader, gasPrice sdk.DecCoin, fromAddr sdk.AccAddress, coin sdk.Coin) error {
+ balance, err := reader.Balance(fromAddr, coin.GetDenom())
+ if err != nil {
+ return err
+ }
+
+ fee := gasPrice.Amount.MulInt64(maxGasUsedTransfer).RoundInt()
+ need := coin.Amount.Add(fee)
+
+ if balance.Amount.LT(need) {
+ return errors.Errorf("balance %q is too low for this transaction to be executed: need %s total, including %s fee", balance, need, fee)
+ }
+ return nil
+}
diff --git a/core/chains/cosmos/config.go b/core/chains/cosmos/config.go
deleted file mode 100644
index 8b4c8c13f3..0000000000
--- a/core/chains/cosmos/config.go
+++ /dev/null
@@ -1,272 +0,0 @@
-package cosmos
-
-import (
- "fmt"
- "net/url"
- "slices"
- "time"
-
- sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/pelletier/go-toml/v2"
- "github.com/shopspring/decimal"
- "go.uber.org/multierr"
-
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
-
- "github.com/smartcontractkit/chainlink/v2/core/chains"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay"
- "github.com/smartcontractkit/chainlink/v2/core/utils/config"
-)
-
-type CosmosConfigs []*CosmosConfig
-
-func (cs CosmosConfigs) validateKeys() (err error) {
- // Unique chain IDs
- chainIDs := config.UniqueStrings{}
- for i, c := range cs {
- if chainIDs.IsDupe(c.ChainID) {
- err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID))
- }
- }
-
- // Unique node names
- names := config.UniqueStrings{}
- for i, c := range cs {
- for j, n := range c.Nodes {
- if names.IsDupe(n.Name) {
- err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name))
- }
- }
- }
-
- // Unique TendermintURLs
- urls := config.UniqueStrings{}
- for i, c := range cs {
- for j, n := range c.Nodes {
- u := (*url.URL)(n.TendermintURL)
- if urls.IsDupeFmt(u) {
- err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.TendermintURL", i, j), u.String()))
- }
- }
- }
- return
-
-}
-
-func (cs CosmosConfigs) ValidateConfig() (err error) {
- return cs.validateKeys()
-}
-
-func (cs *CosmosConfigs) SetFrom(fs *CosmosConfigs) (err error) {
- if err1 := fs.validateKeys(); err1 != nil {
- return err1
- }
- for _, f := range *fs {
- if f.ChainID == nil {
- *cs = append(*cs, f)
- } else if i := slices.IndexFunc(*cs, func(c *CosmosConfig) bool {
- return c.ChainID != nil && *c.ChainID == *f.ChainID
- }); i == -1 {
- *cs = append(*cs, f)
- } else {
- (*cs)[i].SetFrom(f)
- }
- }
- return
-}
-
-func nodeStatus(n *coscfg.Node, id relay.ChainID) (relaytypes.NodeStatus, error) {
- var s relaytypes.NodeStatus
- s.ChainID = id
- s.Name = *n.Name
- b, err := toml.Marshal(n)
- if err != nil {
- return relaytypes.NodeStatus{}, err
- }
- s.Config = string(b)
- return s, nil
-}
-
-type CosmosNodes []*coscfg.Node
-
-func (ns *CosmosNodes) SetFrom(fs *CosmosNodes) {
- for _, f := range *fs {
- if f.Name == nil {
- *ns = append(*ns, f)
- } else if i := slices.IndexFunc(*ns, func(n *coscfg.Node) bool {
- return n.Name != nil && *n.Name == *f.Name
- }); i == -1 {
- *ns = append(*ns, f)
- } else {
- setFromNode((*ns)[i], f)
- }
- }
-}
-
-func setFromNode(n, f *coscfg.Node) {
- if f.Name != nil {
- n.Name = f.Name
- }
- if f.TendermintURL != nil {
- n.TendermintURL = f.TendermintURL
- }
-}
-
-func legacyNode(n *coscfg.Node, id string) db.Node {
- return db.Node{
- Name: *n.Name,
- CosmosChainID: id,
- TendermintURL: (*url.URL)(n.TendermintURL).String(),
- }
-}
-
-type CosmosConfig struct {
- ChainID *string
- // Do not access directly. Use [IsEnabled]
- Enabled *bool
- coscfg.Chain
- Nodes CosmosNodes
-}
-
-func (c *CosmosConfig) IsEnabled() bool {
- return c.Enabled == nil || *c.Enabled
-}
-
-func (c *CosmosConfig) SetFrom(f *CosmosConfig) {
- if f.ChainID != nil {
- c.ChainID = f.ChainID
- }
- if f.Enabled != nil {
- c.Enabled = f.Enabled
- }
- setFromChain(&c.Chain, &f.Chain)
- c.Nodes.SetFrom(&f.Nodes)
-}
-
-func setFromChain(c, f *coscfg.Chain) {
- if f.Bech32Prefix != nil {
- c.Bech32Prefix = f.Bech32Prefix
- }
- if f.BlockRate != nil {
- c.BlockRate = f.BlockRate
- }
- if f.BlocksUntilTxTimeout != nil {
- c.BlocksUntilTxTimeout = f.BlocksUntilTxTimeout
- }
- if f.ConfirmPollPeriod != nil {
- c.ConfirmPollPeriod = f.ConfirmPollPeriod
- }
- if f.FallbackGasPrice != nil {
- c.FallbackGasPrice = f.FallbackGasPrice
- }
- if f.GasToken != nil {
- c.GasToken = f.GasToken
- }
- if f.GasLimitMultiplier != nil {
- c.GasLimitMultiplier = f.GasLimitMultiplier
- }
- if f.MaxMsgsPerBatch != nil {
- c.MaxMsgsPerBatch = f.MaxMsgsPerBatch
- }
- if f.OCR2CachePollPeriod != nil {
- c.OCR2CachePollPeriod = f.OCR2CachePollPeriod
- }
- if f.OCR2CacheTTL != nil {
- c.OCR2CacheTTL = f.OCR2CacheTTL
- }
- if f.TxMsgTimeout != nil {
- c.TxMsgTimeout = f.TxMsgTimeout
- }
-}
-
-func (c *CosmosConfig) ValidateConfig() (err error) {
- if c.ChainID == nil {
- err = multierr.Append(err, config.ErrMissing{Name: "ChainID", Msg: "required for all chains"})
- } else if *c.ChainID == "" {
- err = multierr.Append(err, config.ErrEmpty{Name: "ChainID", Msg: "required for all chains"})
- }
-
- if len(c.Nodes) == 0 {
- err = multierr.Append(err, config.ErrMissing{Name: "Nodes", Msg: "must have at least one node"})
- }
-
- return
-}
-
-func (c *CosmosConfig) TOMLString() (string, error) {
- b, err := toml.Marshal(c)
- if err != nil {
- return "", err
- }
- return string(b), nil
-}
-
-var _ coscfg.Config = &CosmosConfig{}
-
-func (c *CosmosConfig) Bech32Prefix() string {
- return *c.Chain.Bech32Prefix
-}
-
-func (c *CosmosConfig) BlockRate() time.Duration {
- return c.Chain.BlockRate.Duration()
-}
-
-func (c *CosmosConfig) BlocksUntilTxTimeout() int64 {
- return *c.Chain.BlocksUntilTxTimeout
-}
-
-func (c *CosmosConfig) ConfirmPollPeriod() time.Duration {
- return c.Chain.ConfirmPollPeriod.Duration()
-}
-
-func (c *CosmosConfig) FallbackGasPrice() sdk.Dec {
- return sdkDecFromDecimal(c.Chain.FallbackGasPrice)
-}
-
-func (c *CosmosConfig) GasToken() string {
- return *c.Chain.GasToken
-}
-
-func (c *CosmosConfig) GasLimitMultiplier() float64 {
- return c.Chain.GasLimitMultiplier.InexactFloat64()
-}
-
-func (c *CosmosConfig) MaxMsgsPerBatch() int64 {
- return *c.Chain.MaxMsgsPerBatch
-}
-
-func (c *CosmosConfig) OCR2CachePollPeriod() time.Duration {
- return c.Chain.OCR2CachePollPeriod.Duration()
-}
-
-func (c *CosmosConfig) OCR2CacheTTL() time.Duration {
- return c.Chain.OCR2CacheTTL.Duration()
-}
-
-func (c *CosmosConfig) TxMsgTimeout() time.Duration {
- return c.Chain.TxMsgTimeout.Duration()
-}
-
-func sdkDecFromDecimal(d *decimal.Decimal) sdk.Dec {
- i := d.Shift(sdk.Precision)
- return sdk.NewDecFromBigIntWithPrec(i.BigInt(), sdk.Precision)
-}
-
-func (c *CosmosConfig) GetNode(name string) (db.Node, error) {
- for _, n := range c.Nodes {
- if *n.Name == name {
- return legacyNode(n, *c.ChainID), nil
- }
- }
- return db.Node{}, fmt.Errorf("%w: node %q", chains.ErrNotFound, name)
-}
-
-func (c *CosmosConfig) ListNodes() ([]db.Node, error) {
- var allNodes []db.Node
- for _, n := range c.Nodes {
- allNodes = append(allNodes, legacyNode(n, *c.ChainID))
- }
- return allNodes, nil
-}
diff --git a/core/chains/cosmos/config_test.go b/core/chains/cosmos/config_test.go
deleted file mode 100644
index 54f91a1362..0000000000
--- a/core/chains/cosmos/config_test.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package cosmos
-
-import (
- "reflect"
- "testing"
-
- sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/shopspring/decimal"
- "github.com/stretchr/testify/assert"
-
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
-)
-
-func Test_sdkDecFromDecimal(t *testing.T) {
- tests := []string{
- "0.0",
- "0.1",
- "1.0",
- "0.000000000000000001",
- }
- for _, tt := range tests {
- t.Run(tt, func(t *testing.T) {
- val := decimal.RequireFromString(tt)
- exp := sdk.MustNewDecFromStr(tt)
- assert.Equal(t, exp, sdkDecFromDecimal(&val))
- })
- }
-}
-
-func TestCosmosConfig_GetNode(t *testing.T) {
- type fields struct {
- ChainID *string
- Nodes CosmosNodes
- }
- type args struct {
- name string
- }
- tests := []struct {
- name string
- fields fields
- args args
- want db.Node
- wantErr bool
- }{
- {
- name: "not found",
- args: args{
- name: "not a node",
- },
- fields: fields{Nodes: CosmosNodes{}},
- want: db.Node{},
- wantErr: true,
- },
- {
- name: "success",
- args: args{
- name: "node",
- },
- fields: fields{
- ChainID: ptr("chainID"),
- Nodes: []*coscfg.Node{
- &coscfg.Node{
- Name: ptr("node"),
- TendermintURL: &utils.URL{},
- },
- }},
- want: db.Node{
- CosmosChainID: "chainID",
- Name: "node",
- TendermintURL: "",
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- c := &CosmosConfig{
- Nodes: tt.fields.Nodes,
- ChainID: tt.fields.ChainID,
- }
- got, err := c.GetNode(tt.args.name)
- if (err != nil) != tt.wantErr {
- t.Errorf("CosmosConfig.GetNode() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("CosmosConfig.GetNode() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func ptr[T any](t T) *T {
- return &t
-}
diff --git a/core/chains/cosmos/cosmostxm/helpers_test.go b/core/chains/cosmos/cosmostxm/helpers_test.go
index ad93189082..a2dfbbeed8 100644
--- a/core/chains/cosmos/cosmostxm/helpers_test.go
+++ b/core/chains/cosmos/cosmostxm/helpers_test.go
@@ -1,36 +1,8 @@
package cosmostxm
-import (
- "context"
- "time"
+import "golang.org/x/exp/maps"
- sdk "github.com/cosmos/cosmos-sdk/types"
- "golang.org/x/exp/maps"
-
- cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
-)
-
-func (txm *Txm) ORM() *ORM {
- return txm.orm
-}
-
-func (txm *Txm) ConfirmTx(ctx context.Context, tc cosmosclient.Reader, txHash string, broadcasted []int64, maxPolls int, pollPeriod time.Duration) error {
- return txm.confirmTx(ctx, tc, txHash, broadcasted, maxPolls, pollPeriod)
-}
-
-func (txm *Txm) ConfirmAnyUnconfirmed(ctx context.Context) {
- txm.confirmAnyUnconfirmed(ctx)
-}
-
-func (txm *Txm) MarshalMsg(msg sdk.Msg) (string, []byte, error) {
- return txm.marshalMsg(msg)
-}
-
-func (txm *Txm) SendMsgBatch(ctx context.Context) {
- txm.sendMsgBatch(ctx)
-}
-
-func (ka *KeystoreAdapter) Accounts(ctx context.Context) ([]string, error) {
+func (ka *keystoreAdapter) Accounts() ([]string, error) {
ka.mutex.Lock()
defer ka.mutex.Unlock()
err := ka.updateMappingLocked()
diff --git a/core/chains/cosmos/cosmostxm/key_wrapper.go b/core/chains/cosmos/cosmostxm/key_wrapper.go
index 1d2d686c8c..e03dfd89b8 100644
--- a/core/chains/cosmos/cosmostxm/key_wrapper.go
+++ b/core/chains/cosmos/cosmostxm/key_wrapper.go
@@ -8,15 +8,15 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)
-// KeyWrapper uses a KeystoreAdapter to implement the cosmos-sdk PrivKey interface for a specific key.
+// KeyWrapper uses a keystoreAdapter to implement the cosmos-sdk PrivKey interface for a specific key.
type KeyWrapper struct {
- adapter *KeystoreAdapter
+ adapter *keystoreAdapter
account string
}
var _ cryptotypes.PrivKey = &KeyWrapper{}
-func NewKeyWrapper(adapter *KeystoreAdapter, account string) *KeyWrapper {
+func NewKeyWrapper(adapter *keystoreAdapter, account string) *KeyWrapper {
return &KeyWrapper{
adapter: adapter,
account: account,
diff --git a/core/chains/cosmos/cosmostxm/keystore_adapter.go b/core/chains/cosmos/cosmostxm/keystore_adapter.go
index c8556015c6..6b360dde98 100644
--- a/core/chains/cosmos/cosmostxm/keystore_adapter.go
+++ b/core/chains/cosmos/cosmostxm/keystore_adapter.go
@@ -21,23 +21,23 @@ type accountInfo struct {
PubKey *secp256k1.PubKey
}
-// An adapter for a Cosmos loop.Keystore to translate public keys into bech32-prefixed account addresses.
-type KeystoreAdapter struct {
+// keystoreAdapter adapts a Cosmos loop.Keystore to translate public keys into bech32-prefixed account addresses.
+type keystoreAdapter struct {
keystore loop.Keystore
accountPrefix string
mutex sync.RWMutex
addressToPubKey map[string]*accountInfo
}
-func NewKeystoreAdapter(keystore loop.Keystore, accountPrefix string) *KeystoreAdapter {
- return &KeystoreAdapter{
+func newKeystoreAdapter(keystore loop.Keystore, accountPrefix string) *keystoreAdapter {
+ return &keystoreAdapter{
keystore: keystore,
accountPrefix: accountPrefix,
addressToPubKey: make(map[string]*accountInfo),
}
}
-func (ka *KeystoreAdapter) updateMappingLocked() error {
+func (ka *keystoreAdapter) updateMappingLocked() error {
accounts, err := ka.keystore.Accounts(context.Background())
if err != nil {
return err
@@ -90,7 +90,7 @@ func (ka *KeystoreAdapter) updateMappingLocked() error {
return nil
}
-func (ka *KeystoreAdapter) lookup(id string) (*accountInfo, error) {
+func (ka *keystoreAdapter) lookup(id string) (*accountInfo, error) {
ka.mutex.RLock()
ai, ok := ka.addressToPubKey[id]
ka.mutex.RUnlock()
@@ -111,7 +111,7 @@ func (ka *KeystoreAdapter) lookup(id string) (*accountInfo, error) {
return ai, nil
}
-func (ka *KeystoreAdapter) Sign(ctx context.Context, id string, hash []byte) ([]byte, error) {
+func (ka *keystoreAdapter) Sign(ctx context.Context, id string, hash []byte) ([]byte, error) {
accountInfo, err := ka.lookup(id)
if err != nil {
return nil, err
@@ -120,7 +120,7 @@ func (ka *KeystoreAdapter) Sign(ctx context.Context, id string, hash []byte) ([]
}
// Returns the cosmos PubKey associated with the prefixed address.
-func (ka *KeystoreAdapter) PubKey(address string) (cryptotypes.PubKey, error) {
+func (ka *keystoreAdapter) PubKey(address string) (cryptotypes.PubKey, error) {
accountInfo, err := ka.lookup(address)
if err != nil {
return nil, err
diff --git a/core/chains/cosmos/cosmostxm/orm_test.go b/core/chains/cosmos/cosmostxm/orm_test.go
index c741874936..3cee25bac1 100644
--- a/core/chains/cosmos/cosmostxm/orm_test.go
+++ b/core/chains/cosmos/cosmostxm/orm_test.go
@@ -1,4 +1,4 @@
-package cosmostxm_test
+package cosmostxm
import (
"testing"
@@ -8,7 +8,6 @@ import (
cosmosdb "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -19,7 +18,7 @@ func TestORM(t *testing.T) {
lggr := logger.TestLogger(t)
logCfg := pgtest.NewQConfig(true)
chainID := cosmostest.RandomChainID()
- o := cosmostxm.NewORM(chainID, db, lggr, logCfg)
+ o := NewORM(chainID, db, lggr, logCfg)
// Create
mid, err := o.InsertMsg("0x123", "", []byte("hello"))
diff --git a/core/chains/cosmos/cosmostxm/txm.go b/core/chains/cosmos/cosmostxm/txm.go
index 8806d97a9f..712e1b8fc7 100644
--- a/core/chains/cosmos/cosmostxm/txm.go
+++ b/core/chains/cosmos/cosmostxm/txm.go
@@ -47,7 +47,7 @@ type Txm struct {
orm *ORM
lggr logger.Logger
tc func() (cosmosclient.ReaderWriter, error)
- keystoreAdapter *KeystoreAdapter
+ keystoreAdapter *keystoreAdapter
stop, done chan struct{}
cfg coscfg.Config
gpe cosmosclient.ComposedGasPriceEstimator
@@ -56,7 +56,7 @@ type Txm struct {
// NewTxm creates a txm. Uses simulation so should only be used to send txes to trusted contracts i.e. OCR.
func NewTxm(db *sqlx.DB, tc func() (cosmosclient.ReaderWriter, error), gpe cosmosclient.ComposedGasPriceEstimator, chainID string, cfg coscfg.Config, ks loop.Keystore, lggr logger.Logger, logCfg pg.QConfig, eb pg.EventBroadcaster) *Txm {
lggr = logger.Named(lggr, "Txm")
- keystoreAdapter := NewKeystoreAdapter(ks, cfg.Bech32Prefix())
+ keystoreAdapter := newKeystoreAdapter(ks, cfg.Bech32Prefix())
return &Txm{
eb: eb,
orm: NewORM(chainID, db, lggr, logCfg),
diff --git a/core/chains/cosmos/cosmostxm/txm_internal_test.go b/core/chains/cosmos/cosmostxm/txm_internal_test.go
index 66a8c98b63..f29f130cae 100644
--- a/core/chains/cosmos/cosmostxm/txm_internal_test.go
+++ b/core/chains/cosmos/cosmostxm/txm_internal_test.go
@@ -1,4 +1,4 @@
-package cosmostxm_test
+package cosmostxm
import (
"fmt"
@@ -21,8 +21,6 @@ import (
cosmosdb "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
relayutils "github.com/smartcontractkit/chainlink-relay/pkg/utils"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
@@ -31,7 +29,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
-func generateExecuteMsg(t *testing.T, msg []byte, from, to cosmostypes.AccAddress) cosmostypes.Msg {
+func generateExecuteMsg(msg []byte, from, to cosmostypes.AccAddress) cosmostypes.Msg {
return &wasmtypes.MsgExecuteContract{
Sender: from.String(),
Contract: to.String(),
@@ -59,8 +57,8 @@ func TestTxm(t *testing.T) {
}
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- adapter := cosmostxm.NewKeystoreAdapter(loopKs, "wasm")
- accounts, err := adapter.Accounts(testutils.Context(t))
+ adapter := newKeystoreAdapter(loopKs, "wasm")
+ accounts, err := adapter.Accounts()
require.NoError(t, err)
require.Equal(t, len(accounts), 4)
@@ -77,7 +75,7 @@ func TestTxm(t *testing.T) {
chainID := cosmostest.RandomChainID()
two := int64(2)
gasToken := "ucosm"
- cfg := &cosmos.CosmosConfig{Chain: coscfg.Chain{
+ cfg := &coscfg.TOMLConfig{Chain: coscfg.Chain{
MaxMsgsPerBatch: &two,
GasToken: &gasToken,
}}
@@ -94,10 +92,10 @@ func TestTxm(t *testing.T) {
tc := newReaderWriterMock(t)
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, logCfg, nil)
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, logCfg, nil)
// Enqueue a single msg, then send it in a batch
- id1, err := txm.Enqueue(contract.String(), generateExecuteMsg(t, []byte(`1`), sender1, contract))
+ id1, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`1`), sender1, contract))
require.NoError(t, err)
tc.On("Account", mock.Anything).Return(uint64(0), uint64(0), nil)
tc.On("BatchSimulateUnsigned", mock.Anything, mock.Anything).Return(&cosmosclient.BatchSimResults{
@@ -118,10 +116,10 @@ func TestTxm(t *testing.T) {
txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil)
tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil)
- txm.SendMsgBatch(testutils.Context(t))
+ txm.sendMsgBatch(testutils.Context(t))
// Should be in completed state
- completed, err := txm.ORM().GetMsgs(id1)
+ completed, err := txm.orm.GetMsgs(id1)
require.NoError(t, err)
require.Equal(t, 1, len(completed))
assert.Equal(t, completed[0].State, cosmosdb.Confirmed)
@@ -131,11 +129,11 @@ func TestTxm(t *testing.T) {
tc := newReaderWriterMock(t)
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
- id1, err := txm.Enqueue(contract.String(), generateExecuteMsg(t, []byte(`0`), sender1, contract))
+ id1, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`0`), sender1, contract))
require.NoError(t, err)
- id2, err := txm.Enqueue(contract.String(), generateExecuteMsg(t, []byte(`1`), sender2, contract))
+ id2, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`1`), sender2, contract))
require.NoError(t, err)
tc.On("Account", mock.Anything).Return(uint64(0), uint64(0), nil).Once()
@@ -173,10 +171,10 @@ func TestTxm(t *testing.T) {
txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil).Once()
tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil).Once()
- txm.SendMsgBatch(testutils.Context(t))
+ txm.sendMsgBatch(testutils.Context(t))
// Should be in completed state
- completed, err := txm.ORM().GetMsgs(id1, id2)
+ completed, err := txm.orm.GetMsgs(id1, id2)
require.NoError(t, err)
require.Equal(t, 2, len(completed))
assert.Equal(t, cosmosdb.Errored, completed[0].State) // cancelled
@@ -187,11 +185,11 @@ func TestTxm(t *testing.T) {
tc := newReaderWriterMock(t)
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
- id1, err := txm.Enqueue(contract.String(), generateExecuteMsg(t, []byte(`0`), sender1, contract))
+ id1, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`0`), sender1, contract))
require.NoError(t, err)
- id2, err := txm.Enqueue(contract2.String(), generateExecuteMsg(t, []byte(`1`), sender2, contract2))
+ id2, err := txm.Enqueue(contract2.String(), generateExecuteMsg([]byte(`1`), sender2, contract2))
require.NoError(t, err)
ids := []int64{id1, id2}
senders := []string{sender1.String(), sender2.String()}
@@ -233,10 +231,10 @@ func TestTxm(t *testing.T) {
txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil).Twice()
tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil).Twice()
- txm.SendMsgBatch(testutils.Context(t))
+ txm.sendMsgBatch(testutils.Context(t))
// Should be in completed state
- completed, err := txm.ORM().GetMsgs(id1, id2)
+ completed, err := txm.orm.GetMsgs(id1, id2)
require.NoError(t, err)
require.Equal(t, 2, len(completed))
assert.Equal(t, cosmosdb.Confirmed, completed[0].State)
@@ -251,15 +249,15 @@ func TestTxm(t *testing.T) {
}, errors.New("not found")).Twice()
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
- i, err := txm.ORM().InsertMsg("blah", "", []byte{0x01})
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
+ i, err := txm.orm.InsertMsg("blah", "", []byte{0x01})
require.NoError(t, err)
txh := "0x123"
- require.NoError(t, txm.ORM().UpdateMsgs([]int64{i}, cosmosdb.Started, &txh))
- require.NoError(t, txm.ORM().UpdateMsgs([]int64{i}, cosmosdb.Broadcasted, &txh))
- err = txm.ConfirmTx(testutils.Context(t), tc, txh, []int64{i}, 2, 1*time.Millisecond)
+ require.NoError(t, txm.orm.UpdateMsgs([]int64{i}, cosmosdb.Started, &txh))
+ require.NoError(t, txm.orm.UpdateMsgs([]int64{i}, cosmosdb.Broadcasted, &txh))
+ err = txm.confirmTx(testutils.Context(t), tc, txh, []int64{i}, 2, 1*time.Millisecond)
require.NoError(t, err)
- m, err := txm.ORM().GetMsgs(i)
+ m, err := txm.orm.GetMsgs(i)
require.NoError(t, err)
require.Equal(t, 1, len(m))
assert.Equal(t, cosmosdb.Errored, m[0].State)
@@ -282,31 +280,31 @@ func TestTxm(t *testing.T) {
}, nil).Once()
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
// Insert and broadcast 3 msgs with different txhashes.
- id1, err := txm.ORM().InsertMsg("blah", "", []byte{0x01})
+ id1, err := txm.orm.InsertMsg("blah", "", []byte{0x01})
require.NoError(t, err)
- id2, err := txm.ORM().InsertMsg("blah", "", []byte{0x02})
+ id2, err := txm.orm.InsertMsg("blah", "", []byte{0x02})
require.NoError(t, err)
- id3, err := txm.ORM().InsertMsg("blah", "", []byte{0x03})
+ id3, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
require.NoError(t, err)
- err = txm.ORM().UpdateMsgs([]int64{id1}, cosmosdb.Started, &txHash1)
+ err = txm.orm.UpdateMsgs([]int64{id1}, cosmosdb.Started, &txHash1)
require.NoError(t, err)
- err = txm.ORM().UpdateMsgs([]int64{id2}, cosmosdb.Started, &txHash2)
+ err = txm.orm.UpdateMsgs([]int64{id2}, cosmosdb.Started, &txHash2)
require.NoError(t, err)
- err = txm.ORM().UpdateMsgs([]int64{id3}, cosmosdb.Started, &txHash3)
+ err = txm.orm.UpdateMsgs([]int64{id3}, cosmosdb.Started, &txHash3)
require.NoError(t, err)
- err = txm.ORM().UpdateMsgs([]int64{id1}, cosmosdb.Broadcasted, &txHash1)
+ err = txm.orm.UpdateMsgs([]int64{id1}, cosmosdb.Broadcasted, &txHash1)
require.NoError(t, err)
- err = txm.ORM().UpdateMsgs([]int64{id2}, cosmosdb.Broadcasted, &txHash2)
+ err = txm.orm.UpdateMsgs([]int64{id2}, cosmosdb.Broadcasted, &txHash2)
require.NoError(t, err)
- err = txm.ORM().UpdateMsgs([]int64{id3}, cosmosdb.Broadcasted, &txHash3)
+ err = txm.orm.UpdateMsgs([]int64{id3}, cosmosdb.Broadcasted, &txHash3)
require.NoError(t, err)
// Confirm them as in a restart while confirming scenario
- txm.ConfirmAnyUnconfirmed(testutils.Context(t))
- msgs, err := txm.ORM().GetMsgs(id1, id2, id3)
+ txm.confirmAnyUnconfirmed(testutils.Context(t))
+ msgs, err := txm.orm.GetMsgs(id1, id2, id3)
require.NoError(t, err)
require.Equal(t, 3, len(msgs))
assert.Equal(t, cosmosdb.Confirmed, msgs[0].State)
@@ -320,33 +318,33 @@ func TestTxm(t *testing.T) {
require.NoError(t, err)
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
two := int64(2)
- cfgShortExpiry := &cosmos.CosmosConfig{Chain: coscfg.Chain{
+ cfgShortExpiry := &coscfg.TOMLConfig{Chain: coscfg.Chain{
MaxMsgsPerBatch: &two,
TxMsgTimeout: &timeout,
}}
cfgShortExpiry.SetDefaults()
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfgShortExpiry, loopKs, lggr, pgtest.NewQConfig(true), nil)
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfgShortExpiry, loopKs, lggr, pgtest.NewQConfig(true), nil)
// Send a single one expired
- id1, err := txm.ORM().InsertMsg("blah", "", []byte{0x03})
+ id1, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
require.NoError(t, err)
time.Sleep(1 * time.Millisecond)
- txm.SendMsgBatch(testutils.Context(t))
+ txm.sendMsgBatch(testutils.Context(t))
// Should be marked errored
- m, err := txm.ORM().GetMsgs(id1)
+ m, err := txm.orm.GetMsgs(id1)
require.NoError(t, err)
assert.Equal(t, cosmosdb.Errored, m[0].State)
// Send a batch which is all expired
- id2, err := txm.ORM().InsertMsg("blah", "", []byte{0x03})
+ id2, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
require.NoError(t, err)
- id3, err := txm.ORM().InsertMsg("blah", "", []byte{0x03})
+ id3, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
require.NoError(t, err)
time.Sleep(1 * time.Millisecond)
- txm.SendMsgBatch(testutils.Context(t))
+ txm.sendMsgBatch(testutils.Context(t))
require.NoError(t, err)
- ms, err := txm.ORM().GetMsgs(id2, id3)
+ ms, err := txm.orm.GetMsgs(id2, id3)
require.NoError(t, err)
assert.Equal(t, cosmosdb.Errored, ms[0].State)
assert.Equal(t, cosmosdb.Errored, ms[1].State)
@@ -367,17 +365,17 @@ func TestTxm(t *testing.T) {
tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil)
tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
two := int64(2)
- cfgMaxMsgs := &cosmos.CosmosConfig{Chain: coscfg.Chain{
+ cfgMaxMsgs := &coscfg.TOMLConfig{Chain: coscfg.Chain{
MaxMsgsPerBatch: &two,
}}
cfgMaxMsgs.SetDefaults()
loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, cfgMaxMsgs, loopKs, lggr, pgtest.NewQConfig(true), nil)
+ txm := NewTxm(db, tcFn, *gpe, chainID, cfgMaxMsgs, loopKs, lggr, pgtest.NewQConfig(true), nil)
// Leftover started is processed
- msg1 := generateExecuteMsg(t, []byte{0x03}, sender1, contract)
+ msg1 := generateExecuteMsg([]byte{0x03}, sender1, contract)
id1 := mustInsertMsg(t, txm, contract.String(), msg1)
- require.NoError(t, txm.ORM().UpdateMsgs([]int64{id1}, cosmosdb.Started, nil))
+ require.NoError(t, txm.orm.UpdateMsgs([]int64{id1}, cosmosdb.Started, nil))
msgs := cosmosclient.SimMsgs{{ID: id1, Msg: &wasmtypes.MsgExecuteContract{
Sender: sender1.String(),
Msg: []byte{0x03},
@@ -386,16 +384,16 @@ func TestTxm(t *testing.T) {
tc.On("BatchSimulateUnsigned", msgs, mock.Anything).
Return(&cosmosclient.BatchSimResults{Failed: nil, Succeeded: msgs}, nil).Once()
time.Sleep(1 * time.Millisecond)
- txm.SendMsgBatch(testutils.Context(t))
- m, err := txm.ORM().GetMsgs(id1)
+ txm.sendMsgBatch(testutils.Context(t))
+ m, err := txm.orm.GetMsgs(id1)
require.NoError(t, err)
assert.Equal(t, cosmosdb.Confirmed, m[0].State)
// Leftover started is not cancelled
- msg2 := generateExecuteMsg(t, []byte{0x04}, sender1, contract)
- msg3 := generateExecuteMsg(t, []byte{0x05}, sender1, contract)
+ msg2 := generateExecuteMsg([]byte{0x04}, sender1, contract)
+ msg3 := generateExecuteMsg([]byte{0x05}, sender1, contract)
id2 := mustInsertMsg(t, txm, contract.String(), msg2)
- require.NoError(t, txm.ORM().UpdateMsgs([]int64{id2}, cosmosdb.Started, nil))
+ require.NoError(t, txm.orm.UpdateMsgs([]int64{id2}, cosmosdb.Started, nil))
time.Sleep(time.Millisecond) // ensure != CreatedAt
id3 := mustInsertMsg(t, txm, contract.String(), msg3)
msgs = cosmosclient.SimMsgs{{ID: id2, Msg: &wasmtypes.MsgExecuteContract{
@@ -410,19 +408,19 @@ func TestTxm(t *testing.T) {
tc.On("BatchSimulateUnsigned", msgs, mock.Anything).
Return(&cosmosclient.BatchSimResults{Failed: nil, Succeeded: msgs}, nil).Once()
time.Sleep(1 * time.Millisecond)
- txm.SendMsgBatch(testutils.Context(t))
+ txm.sendMsgBatch(testutils.Context(t))
require.NoError(t, err)
- ms, err := txm.ORM().GetMsgs(id2, id3)
+ ms, err := txm.orm.GetMsgs(id2, id3)
require.NoError(t, err)
assert.Equal(t, cosmosdb.Confirmed, ms[0].State)
assert.Equal(t, cosmosdb.Confirmed, ms[1].State)
})
}
-func mustInsertMsg(t *testing.T, txm *cosmostxm.Txm, contractID string, msg cosmostypes.Msg) int64 {
- typeURL, raw, err := txm.MarshalMsg(msg)
+func mustInsertMsg(t *testing.T, txm *Txm, contractID string, msg cosmostypes.Msg) int64 {
+ typeURL, raw, err := txm.marshalMsg(msg)
require.NoError(t, err)
- id, err := txm.ORM().InsertMsg(contractID, typeURL, raw)
+ id, err := txm.orm.InsertMsg(contractID, typeURL, raw)
require.NoError(t, err)
return id
}
diff --git a/core/chains/cosmos/cosmostxm/txm_test.go b/core/chains/cosmos/cosmostxm/txm_test.go
index a7a8d0280c..25ac9e8d9e 100644
--- a/core/chains/cosmos/cosmostxm/txm_test.go
+++ b/core/chains/cosmos/cosmostxm/txm_test.go
@@ -2,151 +2,120 @@
package cosmostxm_test
-import (
- "fmt"
- "testing"
- "time"
-
- wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
- "github.com/cometbft/cometbft/abci/types"
- sdk "github.com/cosmos/cosmos-sdk/types"
- txtypes "github.com/cosmos/cosmos-sdk/types/tx"
- banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
- "github.com/google/uuid"
- "github.com/onsi/gomega"
- "github.com/stretchr/testify/require"
-
- cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
-
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
- "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/cosmostest"
- "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/keystore"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- . "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
-)
-
-func TestTxm_Integration(t *testing.T) {
- chainID := cosmostest.RandomChainID()
- cosmosChain := coscfg.Chain{}
- cosmosChain.SetDefaults()
- fallbackGasPrice := sdk.NewDecCoinFromDec(*cosmosChain.GasToken, sdk.MustNewDecFromStr("0.01"))
- chainConfig := cosmos.CosmosConfig{ChainID: &chainID, Enabled: ptr(true), Chain: cosmosChain}
- cfg, db := heavyweight.FullTestDBNoFixturesV2(t, "cosmos_txm", func(c *chainlink.Config, s *chainlink.Secrets) {
- c.Cosmos = cosmos.CosmosConfigs{&chainConfig}
- })
- lggr := logger.TestLogger(t)
- logCfg := pgtest.NewQConfig(true)
- gpe := cosmosclient.NewMustGasPriceEstimator([]cosmosclient.GasPricesEstimator{
- cosmosclient.NewFixedGasPriceEstimator(map[string]sdk.DecCoin{
- *cosmosChain.GasToken: fallbackGasPrice,
- },
- lggr.(logger.SugaredLogger),
- ),
- }, lggr)
- orm := cosmostxm.NewORM(chainID, db, lggr, logCfg)
- eb := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, lggr, uuid.New())
- require.NoError(t, eb.Start(testutils.Context(t)))
- t.Cleanup(func() { require.NoError(t, eb.Close()) })
- ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, pgtest.NewQConfig(true))
- zeConfig := sdk.GetConfig()
- fmt.Println(zeConfig)
- accounts, testdir, tendermintURL := cosmosclient.SetupLocalCosmosNode(t, chainID, *cosmosChain.GasToken)
- tc, err := cosmosclient.NewClient(chainID, tendermintURL, cosmos.DefaultRequestTimeout, lggr)
- require.NoError(t, err)
-
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- keystoreAdapter := cosmostxm.NewKeystoreAdapter(loopKs, *cosmosChain.Bech32Prefix)
-
- // First create a transmitter key and fund it with 1k native tokens
- require.NoError(t, ks.Unlock("blah"))
- err = ks.Cosmos().EnsureKey()
- require.NoError(t, err)
- ksAccounts, err := keystoreAdapter.Accounts(testutils.Context(t))
- require.NoError(t, err)
- transmitterAddress := ksAccounts[0]
- transmitterID, err := sdk.AccAddressFromBech32(transmitterAddress)
- require.NoError(t, err)
- an, sn, err := tc.Account(accounts[0].Address)
- require.NoError(t, err)
- resp, err := tc.SignAndBroadcast([]sdk.Msg{banktypes.NewMsgSend(accounts[0].Address, transmitterID, sdk.NewCoins(sdk.NewInt64Coin(*cosmosChain.GasToken, 100000)))},
- an, sn, gpe.GasPrices()[*cosmosChain.GasToken], accounts[0].PrivateKey, txtypes.BroadcastMode_BROADCAST_MODE_SYNC)
- tx, success := cosmosclient.AwaitTxCommitted(t, tc, resp.TxResponse.TxHash)
- require.True(t, success)
- require.Equal(t, types.CodeTypeOK, tx.TxResponse.Code)
- require.NoError(t, err)
-
- // TODO: find a way to pull this test artifact from
- // the chainlink-cosmos repo instead of copying it to cores testdata
- contractID := cosmosclient.DeployTestContract(t, tendermintURL, chainID, *cosmosChain.GasToken, accounts[0], cosmosclient.Account{
- Name: "transmitter",
- PrivateKey: cosmostxm.NewKeyWrapper(keystoreAdapter, transmitterAddress),
- Address: transmitterID,
- }, tc, testdir, "../../../testdata/cosmos/my_first_contract.wasm")
-
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- // Start txm
- txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, &chainConfig, loopKs, lggr, pgtest.NewQConfig(true), eb)
- require.NoError(t, txm.Start(testutils.Context(t)))
-
- // Change the contract state
- setMsg := &wasmtypes.MsgExecuteContract{
- Sender: transmitterID.String(),
- Contract: contractID.String(),
- Msg: []byte(`{"reset":{"count":5}}`),
- Funds: sdk.Coins{},
- }
- _, err = txm.Enqueue(contractID.String(), setMsg)
- require.NoError(t, err)
-
- // Observe the counter gets set eventually
- gomega.NewWithT(t).Eventually(func() bool {
- d, err := tc.ContractState(contractID, []byte(`{"get_count":{}}`))
- require.NoError(t, err)
- t.Log("contract value", string(d))
- return string(d) == `{"count":5}`
- }, 20*time.Second, time.Second).Should(gomega.BeTrue())
- // Ensure messages are completed
- gomega.NewWithT(t).Eventually(func() bool {
- msgs, err := orm.GetMsgsState(Confirmed, 5)
- require.NoError(t, err)
- return 1 == len(msgs)
- }, 5*time.Second, time.Second).Should(gomega.BeTrue())
-
- // Ensure invalid msgs are marked as errored
- invalidMsg := &wasmtypes.MsgExecuteContract{
- Sender: transmitterID.String(),
- Contract: contractID.String(),
- Msg: []byte(`{"blah":{"blah":5}}`),
- Funds: sdk.Coins{},
- }
- _, err = txm.Enqueue(contractID.String(), invalidMsg)
- require.NoError(t, err)
- _, err = txm.Enqueue(contractID.String(), invalidMsg)
- require.NoError(t, err)
- _, err = txm.Enqueue(contractID.String(), setMsg)
- require.NoError(t, err)
-
- // Ensure messages are completed
- gomega.NewWithT(t).Eventually(func() bool {
- succeeded, err := orm.GetMsgsState(Confirmed, 5)
- require.NoError(t, err)
- errored, err := orm.GetMsgsState(Errored, 5)
- require.NoError(t, err)
- t.Log("errored", len(errored), "succeeded", len(succeeded))
- return 2 == len(succeeded) && 2 == len(errored)
- }, 20*time.Second, time.Second).Should(gomega.BeTrue())
-
- // Observe the messages have been marked as completed
- require.NoError(t, txm.Close())
-}
-
-func ptr[T any](t T) *T { return &t }
+// TestTxm_Integration is disabled in order to be moved to chainlink-cosmos before DB testing is available
+//func TestTxm_Integration(t *testing.T) {
+// chainID := cosmostest.RandomChainID()
+// cosmosChain := coscfg.Chain{}
+// cosmosChain.SetDefaults()
+// fallbackGasPrice := sdk.NewDecCoinFromDec(*cosmosChain.GasToken, sdk.MustNewDecFromStr("0.01"))
+// chainConfig := cosmos.CosmosConfig{ChainID: &chainID, Enabled: ptr(true), Chain: cosmosChain}
+// cfg, db := heavyweight.FullTestDBNoFixturesV2(t, "cosmos_txm", func(c *chainlink.Config, s *chainlink.Secrets) {
+// c.Cosmos = cosmos.CosmosConfigs{&chainConfig}
+// })
+// lggr := logger.TestLogger(t)
+// logCfg := pgtest.NewQConfig(true)
+// gpe := cosmosclient.NewMustGasPriceEstimator([]cosmosclient.GasPricesEstimator{
+// cosmosclient.NewFixedGasPriceEstimator(map[string]sdk.DecCoin{
+// *cosmosChain.GasToken: fallbackGasPrice,
+// },
+// lggr.(logger.SugaredLogger),
+// ),
+// }, lggr)
+// orm := cosmostxm.NewORM(chainID, db, lggr, logCfg)
+// eb := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, lggr, uuid.New())
+// require.NoError(t, eb.Start(testutils.Context(t)))
+// t.Cleanup(func() { require.NoError(t, eb.Close()) })
+// ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, pgtest.NewQConfig(true))
+// zeConfig := sdk.GetConfig()
+// fmt.Println(zeConfig)
+// accounts, testdir, tendermintURL := cosmosclient.SetupLocalCosmosNode(t, chainID, *cosmosChain.GasToken)
+// tc, err := cosmosclient.NewClient(chainID, tendermintURL, 0, lggr)
+// require.NoError(t, err)
+//
+// loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
+// keystoreAdapter := cosmostxm.NewKeystoreAdapter(loopKs, *cosmosChain.Bech32Prefix)
+//
+// // First create a transmitter key and fund it with 1k native tokens
+// require.NoError(t, ks.Unlock("blah"))
+// err = ks.Cosmos().EnsureKey()
+// require.NoError(t, err)
+// ksAccounts, err := keystoreAdapter.Accounts()
+// require.NoError(t, err)
+// transmitterAddress := ksAccounts[0]
+// transmitterID, err := sdk.AccAddressFromBech32(transmitterAddress)
+// require.NoError(t, err)
+// an, sn, err := tc.Account(accounts[0].Address)
+// require.NoError(t, err)
+// resp, err := tc.SignAndBroadcast([]sdk.Msg{banktypes.NewMsgSend(accounts[0].Address, transmitterID, sdk.NewCoins(sdk.NewInt64Coin(*cosmosChain.GasToken, 100000)))},
+// an, sn, gpe.GasPrices()[*cosmosChain.GasToken], accounts[0].PrivateKey, txtypes.BroadcastMode_BROADCAST_MODE_SYNC)
+// tx, success := cosmosclient.AwaitTxCommitted(t, tc, resp.TxResponse.TxHash)
+// require.True(t, success)
+// require.Equal(t, types.CodeTypeOK, tx.TxResponse.Code)
+// require.NoError(t, err)
+//
+// // TODO: find a way to pull this test artifact from
+// // the chainlink-cosmos repo instead of copying it to cores testdata
+// contractID := cosmosclient.DeployTestContract(t, tendermintURL, chainID, *cosmosChain.GasToken, accounts[0], cosmosclient.Account{
+// Name: "transmitter",
+// PrivateKey: cosmostxm.NewKeyWrapper(keystoreAdapter, transmitterAddress),
+// Address: transmitterID,
+// }, tc, testdir, "../../../testdata/cosmos/my_first_contract.wasm")
+//
+// tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
+// // Start txm
+// txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, &chainConfig, loopKs, lggr, pgtest.NewQConfig(true), eb)
+// require.NoError(t, txm.Start(testutils.Context(t)))
+//
+// // Change the contract state
+// setMsg := &wasmtypes.MsgExecuteContract{
+// Sender: transmitterID.String(),
+// Contract: contractID.String(),
+// Msg: []byte(`{"reset":{"count":5}}`),
+// Funds: sdk.Coins{},
+// }
+// _, err = txm.Enqueue(contractID.String(), setMsg)
+// require.NoError(t, err)
+//
+// // Observe the counter gets set eventually
+// gomega.NewWithT(t).Eventually(func() bool {
+// d, err := tc.ContractState(contractID, []byte(`{"get_count":{}}`))
+// require.NoError(t, err)
+// t.Log("contract value", string(d))
+// return string(d) == `{"count":5}`
+// }, 20*time.Second, time.Second).Should(gomega.BeTrue())
+// // Ensure messages are completed
+// gomega.NewWithT(t).Eventually(func() bool {
+// msgs, err := orm.GetMsgsState(Confirmed, 5)
+// require.NoError(t, err)
+// return 1 == len(msgs)
+// }, 5*time.Second, time.Second).Should(gomega.BeTrue())
+//
+// // Ensure invalid msgs are marked as errored
+// invalidMsg := &wasmtypes.MsgExecuteContract{
+// Sender: transmitterID.String(),
+// Contract: contractID.String(),
+// Msg: []byte(`{"blah":{"blah":5}}`),
+// Funds: sdk.Coins{},
+// }
+// _, err = txm.Enqueue(contractID.String(), invalidMsg)
+// require.NoError(t, err)
+// _, err = txm.Enqueue(contractID.String(), invalidMsg)
+// require.NoError(t, err)
+// _, err = txm.Enqueue(contractID.String(), setMsg)
+// require.NoError(t, err)
+//
+// // Ensure messages are completed
+// gomega.NewWithT(t).Eventually(func() bool {
+// succeeded, err := orm.GetMsgsState(Confirmed, 5)
+// require.NoError(t, err)
+// errored, err := orm.GetMsgsState(Errored, 5)
+// require.NoError(t, err)
+// t.Log("errored", len(errored), "succeeded", len(succeeded))
+// return 2 == len(succeeded) && 2 == len(errored)
+// }, 20*time.Second, time.Second).Should(gomega.BeTrue())
+//
+// // Observe the messages have been marked as completed
+// require.NoError(t, txm.Close())
+//}
+//
+//func ptr[T any](t T) *T { return &t }
diff --git a/core/cmd/cosmos_chains_commands_test.go b/core/cmd/cosmos_chains_commands_test.go
index 55e6a60d1c..a0d2052d83 100644
--- a/core/cmd/cosmos_chains_commands_test.go
+++ b/core/cmd/cosmos_chains_commands_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
@@ -17,7 +17,7 @@ func TestShell_IndexCosmosChains(t *testing.T) {
t.Parallel()
chainID := cosmostest.RandomChainID()
- chain := cosmos.CosmosConfig{
+ chain := coscfg.TOMLConfig{
ChainID: ptr(chainID),
Enabled: ptr(true),
}
diff --git a/core/cmd/cosmos_node_commands_test.go b/core/cmd/cosmos_node_commands_test.go
index c19749ecd1..9ac7dfb2ba 100644
--- a/core/cmd/cosmos_node_commands_test.go
+++ b/core/cmd/cosmos_node_commands_test.go
@@ -9,18 +9,17 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-relay/pkg/utils"
- "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
-
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest"
+ "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
)
-func cosmosStartNewApplication(t *testing.T, cfgs ...*cosmos.CosmosConfig) *cltest.TestApplication {
+func cosmosStartNewApplication(t *testing.T, cfgs ...*coscfg.TOMLConfig) *cltest.TestApplication {
for i := range cfgs {
cfgs[i].SetDefaults()
}
@@ -34,14 +33,14 @@ func TestShell_IndexCosmosNodes(t *testing.T) {
t.Parallel()
chainID := cosmostest.RandomChainID()
- node := coscfg.Node{
+ node := config.Node{
Name: ptr("second"),
TendermintURL: utils.MustParseURL("http://tender.mint.test/bombay-12"),
}
- chain := cosmos.CosmosConfig{
+ chain := config.TOMLConfig{
ChainID: ptr(chainID),
Enabled: ptr(true),
- Nodes: cosmos.CosmosNodes{&node},
+ Nodes: config.Nodes{&node},
}
app := cosmosStartNewApplication(t, &chain)
client, r := app.NewShellAndRenderer()
diff --git a/core/cmd/cosmos_transaction_commands_test.go b/core/cmd/cosmos_transaction_commands_test.go
index 04858d2956..67b014af2c 100644
--- a/core/cmd/cosmos_transaction_commands_test.go
+++ b/core/cmd/cosmos_transaction_commands_test.go
@@ -5,7 +5,6 @@ package cmd_test
import (
"flag"
"os"
- "strconv"
"testing"
"time"
@@ -20,15 +19,11 @@ import (
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/denom"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
"github.com/smartcontractkit/chainlink-relay/pkg/utils"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
"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/internal/testutils/cosmostest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
)
@@ -52,13 +47,13 @@ func TestShell_SendCosmosCoins(t *testing.T) {
cosmosChain.SetDefaults()
accounts, _, url := cosmosclient.SetupLocalCosmosNode(t, chainID, *cosmosChain.GasToken)
require.Greater(t, len(accounts), 1)
- nodes := cosmos.CosmosNodes{
+ nodes := coscfg.Nodes{
&coscfg.Node{
Name: ptr("random"),
TendermintURL: utils.MustParseURL(url),
},
}
- chainConfig := cosmos.CosmosConfig{ChainID: &chainID, Enabled: ptr(true), Chain: cosmosChain, Nodes: nodes}
+ chainConfig := coscfg.TOMLConfig{ChainID: &chainID, Enabled: ptr(true), Chain: cosmosChain, Nodes: nodes}
app := cosmosStartNewApplication(t, &chainConfig)
from := accounts[0]
@@ -78,9 +73,6 @@ func TestShell_SendCosmosCoins(t *testing.T) {
return coin.IsPositive()
}, time.Minute, 5*time.Second)
- db := app.GetSqlxDB()
- orm := cosmostxm.NewORM(chainID, db, logger.TestLogger(t), pgtest.NewQConfig(true))
-
client, r := app.NewShellAndRenderer()
cliapp := cli.NewApp()
@@ -123,49 +115,18 @@ func TestShell_SendCosmosCoins(t *testing.T) {
require.NotEmpty(t, renderedMsg.ID)
assert.Equal(t, string(cosmosdb.Unstarted), renderedMsg.State)
assert.Nil(t, renderedMsg.TxHash)
- id, err := strconv.ParseInt(renderedMsg.ID, 10, 64)
- require.NoError(t, err)
- msgs, err := orm.GetMsgs(id)
- require.NoError(t, err)
- require.Equal(t, 1, len(msgs))
- msg := msgs[0]
- assert.Equal(t, strconv.FormatInt(msg.ID, 10), renderedMsg.ID)
- assert.Equal(t, msg.ChainID, renderedMsg.ChainID)
- assert.Equal(t, msg.ContractID, renderedMsg.ContractID)
- require.NotEqual(t, cosmosdb.Errored, msg.State)
- switch msg.State {
- case cosmosdb.Unstarted:
- assert.Nil(t, msg.TxHash)
- case cosmosdb.Broadcasted, cosmosdb.Confirmed:
- assert.NotNil(t, msg.TxHash)
- }
-
- // Maybe wait for confirmation
- if msg.State != cosmosdb.Confirmed {
- require.Eventually(t, func() bool {
- msgs, err := orm.GetMsgs(id)
- if assert.NoError(t, err) && assert.NotEmpty(t, msgs) {
- if msg = msgs[0]; assert.Equal(t, msg.ID, id) {
- t.Log("State:", msg.State)
- return msg.State == cosmosdb.Confirmed
- }
- }
- return false
- }, testutils.WaitTimeout(t), time.Second)
- require.NotNil(t, msg.TxHash)
- }
// Check balance
- endBal, err := reader.Balance(from.Address, *cosmosChain.GasToken)
+ sent, err := denom.ConvertDecCoinToDenom(sdk.NewDecCoinFromDec(nativeToken, sdk.MustNewDecFromStr(tt.amount)), *cosmosChain.GasToken)
require.NoError(t, err)
- if assert.NotNil(t, startBal) && assert.NotNil(t, endBal) {
- diff := startBal.Sub(*endBal).Amount
- sent, err := denom.ConvertDecCoinToDenom(sdk.NewDecCoinFromDec(nativeToken, sdk.MustNewDecFromStr(tt.amount)), *cosmosChain.GasToken)
+ expBal := startBal.Sub(sent)
+
+ testutils.AssertEventually(t, func() bool {
+ endBal, err := reader.Balance(from.Address, *cosmosChain.GasToken)
require.NoError(t, err)
- if assert.True(t, diff.IsInt64()) && assert.True(t, sent.Amount.IsInt64()) {
- require.Greater(t, diff.Int64(), sent.Amount.Int64())
- }
- }
+ t.Logf("%s <= %s", endBal, expBal)
+ return endBal.IsLTE(expBal)
+ })
})
}
}
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index fbbce4becb..1ef99992a6 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -174,7 +174,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G
if cfg.CosmosEnabled() {
cosmosCfg := chainlink.CosmosFactoryConfig{
Keystore: keyStore.Cosmos(),
- CosmosConfigs: cfg.CosmosConfigs(),
+ TOMLConfigs: cfg.CosmosConfigs(),
EventBroadcaster: eventBroadcaster,
}
initOps = append(initOps, chainlink.InitCosmos(ctx, relayerFactory, cosmosCfg))
diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go
index 276d023994..927592e448 100644
--- a/core/config/docs/docs_test.go
+++ b/core/config/docs/docs_test.go
@@ -10,11 +10,11 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config/docs"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
@@ -92,7 +92,7 @@ func TestDoc(t *testing.T) {
})
t.Run("Cosmos", func(t *testing.T) {
- var fallbackDefaults cosmos.CosmosConfig
+ var fallbackDefaults coscfg.TOMLConfig
fallbackDefaults.SetDefaults()
assertTOML(t, fallbackDefaults.Chain, defaults.Cosmos[0].Chain)
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 3fa0090177..d47e6243b8 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -415,7 +415,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn
if cfg.CosmosEnabled() {
cosmosCfg := chainlink.CosmosFactoryConfig{
Keystore: keyStore.Cosmos(),
- CosmosConfigs: cfg.CosmosConfigs(),
+ TOMLConfigs: cfg.CosmosConfigs(),
EventBroadcaster: eventBroadcaster,
DB: db,
QConfig: cfg.Database(),
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 7c0161a066..14e29a6740 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -301,7 +301,7 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 // indirect
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index e0e5e07ecf..08356fe076 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1456,8 +1456,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go
index 26e2d539ba..3f55a2dc00 100644
--- a/core/services/chainlink/config.go
+++ b/core/services/chainlink/config.go
@@ -8,10 +8,10 @@ import (
gotoml "github.com/pelletier/go-toml/v2"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config/docs"
"github.com/smartcontractkit/chainlink/v2/core/config/env"
@@ -36,7 +36,7 @@ type Config struct {
EVM evmcfg.EVMConfigs `toml:",omitempty"`
- Cosmos cosmos.CosmosConfigs `toml:",omitempty"`
+ Cosmos coscfg.TOMLConfigs `toml:",omitempty"`
Solana solana.TOMLConfigs `toml:",omitempty"`
@@ -119,7 +119,7 @@ func (c *Config) setDefaults() {
for i := range c.Cosmos {
if c.Cosmos[i] == nil {
- c.Cosmos[i] = new(cosmos.CosmosConfig)
+ c.Cosmos[i] = new(coscfg.TOMLConfig)
}
c.Cosmos[i].Chain.SetDefaults()
}
diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go
index 6243146e91..81e3883335 100644
--- a/core/services/chainlink/config_general.go
+++ b/core/services/chainlink/config_general.go
@@ -15,10 +15,10 @@ import (
ocrnetworking "github.com/smartcontractkit/libocr/networking"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
starknet "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config"
coreconfig "github.com/smartcontractkit/chainlink/v2/core/config"
@@ -199,7 +199,7 @@ func (g *generalConfig) EVMConfigs() evmcfg.EVMConfigs {
return g.c.EVM
}
-func (g *generalConfig) CosmosConfigs() cosmos.CosmosConfigs {
+func (g *generalConfig) CosmosConfigs() coscfg.TOMLConfigs {
return g.c.Cosmos
}
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 597dab6ba1..48fb8272ac 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -23,7 +23,6 @@ import (
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
legacy "github.com/smartcontractkit/chainlink/v2/core/config"
@@ -138,7 +137,7 @@ var (
},
}},
},
- Cosmos: []*cosmos.CosmosConfig{
+ Cosmos: []*coscfg.TOMLConfig{
{
ChainID: ptr("Ibiza-808"),
Chain: coscfg.Chain{
@@ -622,7 +621,7 @@ func TestConfig_Marshal(t *testing.T) {
},
},
}
- full.Cosmos = []*cosmos.CosmosConfig{
+ full.Cosmos = []*coscfg.TOMLConfig{
{
ChainID: ptr("Malaga-420"),
Enabled: ptr(true),
@@ -1435,7 +1434,7 @@ func assertValidationError(t *testing.T, invalid interface{ Validate() error },
func TestConfig_setDefaults(t *testing.T) {
var c Config
c.EVM = evmcfg.EVMConfigs{{ChainID: utils.NewBigI(99999133712345)}}
- c.Cosmos = cosmos.CosmosConfigs{{ChainID: ptr("unknown cosmos chain")}}
+ c.Cosmos = coscfg.TOMLConfigs{{ChainID: ptr("unknown cosmos chain")}}
c.Solana = solana.TOMLConfigs{{ChainID: ptr("unknown solana chain")}}
c.Starknet = stkcfg.TOMLConfigs{{ChainID: ptr("unknown starknet chain")}}
c.setDefaults()
diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go
index 0bc51ea431..98796e9005 100644
--- a/core/services/chainlink/mocks/general_config.go
+++ b/core/services/chainlink/mocks/general_config.go
@@ -6,7 +6,7 @@ import (
chainlinkconfig "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
config "github.com/smartcontractkit/chainlink/v2/core/config"
- cosmos "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
+ cosmosconfig "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
mock "github.com/stretchr/testify/mock"
@@ -99,15 +99,15 @@ func (_m *GeneralConfig) ConfigTOML() (string, string) {
}
// CosmosConfigs provides a mock function with given fields:
-func (_m *GeneralConfig) CosmosConfigs() cosmos.CosmosConfigs {
+func (_m *GeneralConfig) CosmosConfigs() cosmosconfig.TOMLConfigs {
ret := _m.Called()
- var r0 cosmos.CosmosConfigs
- if rf, ok := ret.Get(0).(func() cosmos.CosmosConfigs); ok {
+ var r0 cosmosconfig.TOMLConfigs
+ if rf, ok := ret.Get(0).(func() cosmosconfig.TOMLConfigs); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
- r0 = ret.Get(0).(cosmos.CosmosConfigs)
+ r0 = ret.Get(0).(cosmosconfig.TOMLConfigs)
}
}
diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go
index b7291e7dc7..cfc7dbadc1 100644
--- a/core/services/chainlink/relayer_chain_interoperators_test.go
+++ b/core/services/chainlink/relayer_chain_interoperators_test.go
@@ -16,7 +16,6 @@ import (
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
@@ -132,8 +131,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
},
}
- c.Cosmos = cosmos.CosmosConfigs{
- &cosmos.CosmosConfig{
+ c.Cosmos = coscfg.TOMLConfigs{
+ &coscfg.TOMLConfig{
ChainID: &cosmosChainID1,
Enabled: ptr(true),
Chain: coscfg.Chain{
@@ -141,14 +140,14 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Bech32Prefix: ptr("wasm"),
GasToken: ptr("cosm"),
},
- Nodes: cosmos.CosmosNodes{
+ Nodes: coscfg.Nodes{
&coscfg.Node{
Name: ptr("cosmos chain 1 node 1"),
TendermintURL: (*relayutils.URL)(models.MustParseURL("http://localhost:9548").URL()),
},
},
},
- &cosmos.CosmosConfig{
+ &coscfg.TOMLConfig{
ChainID: &cosmosChainID2,
Enabled: ptr(true),
Chain: coscfg.Chain{
@@ -156,7 +155,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Bech32Prefix: ptr("wasm"),
GasToken: ptr("cosm"),
},
- Nodes: cosmos.CosmosNodes{
+ Nodes: coscfg.Nodes{
&coscfg.Node{
Name: ptr("cosmos chain 2 node 1"),
TendermintURL: (*relayutils.URL)(models.MustParseURL("http://localhost:9598").URL()),
@@ -259,7 +258,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
initFuncs: []chainlink.CoreRelayerChainInitFunc{
chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{
Keystore: keyStore.Cosmos(),
- CosmosConfigs: cfg.CosmosConfigs(),
+ TOMLConfigs: cfg.CosmosConfigs(),
EventBroadcaster: pg.NewNullEventBroadcaster(),
DB: db,
QConfig: cfg.Database()}),
@@ -292,7 +291,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
TOMLConfigs: cfg.StarknetConfigs()}),
chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{
Keystore: keyStore.Cosmos(),
- CosmosConfigs: cfg.CosmosConfigs(),
+ TOMLConfigs: cfg.CosmosConfigs(),
EventBroadcaster: pg.NewNullEventBroadcaster(),
DB: db,
QConfig: cfg.Database(),
diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go
index 31251069df..a159ee7cd0 100644
--- a/core/services/chainlink/relayer_factory.go
+++ b/core/services/chainlink/relayer_factory.go
@@ -10,6 +10,7 @@ import (
"github.com/smartcontractkit/sqlx"
pkgcosmos "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
pkgsolana "github.com/smartcontractkit/chainlink-solana/pkg/solana"
@@ -223,7 +224,7 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs config.TOML
type CosmosFactoryConfig struct {
Keystore keystore.Cosmos
- cosmos.CosmosConfigs
+ coscfg.TOMLConfigs
EventBroadcaster pg.EventBroadcaster
*sqlx.DB
pg.QConfig
@@ -234,7 +235,7 @@ func (c CosmosFactoryConfig) Validate() error {
if c.Keystore == nil {
err = errors.Join(err, fmt.Errorf("nil Keystore"))
}
- if len(c.CosmosConfigs) == 0 {
+ if len(c.TOMLConfigs) == 0 {
err = errors.Join(err, fmt.Errorf("no CosmosConfigs provided"))
}
if c.EventBroadcaster == nil {
@@ -266,7 +267,7 @@ func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConf
)
// create one relayer per chain id
- for _, chainCfg := range config.CosmosConfigs {
+ for _, chainCfg := range config.TOMLConfigs {
relayID := relay.ID{Network: relay.Cosmos, ChainID: *chainCfg.ChainID}
lggr := cosmosLggr.Named(relayID.ChainID)
diff --git a/core/services/chainlink/types.go b/core/services/chainlink/types.go
index 1233a17961..72cad69416 100644
--- a/core/services/chainlink/types.go
+++ b/core/services/chainlink/types.go
@@ -1,10 +1,10 @@
package chainlink
import (
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config"
)
@@ -14,7 +14,7 @@ import (
type GeneralConfig interface {
config.AppConfig
toml.HasEVMConfigs
- CosmosConfigs() cosmos.CosmosConfigs
+ CosmosConfigs() coscfg.TOMLConfigs
SolanaConfigs() solana.TOMLConfigs
StarknetConfigs() stkcfg.TOMLConfigs
// ConfigTOML returns both the user provided and effective configuration as TOML.
diff --git a/core/web/cosmos_chains_controller_test.go b/core/web/cosmos_chains_controller_test.go
index 475ef41352..f8dbe4614f 100644
--- a/core/web/cosmos_chains_controller_test.go
+++ b/core/web/cosmos_chains_controller_test.go
@@ -13,7 +13,6 @@ import (
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"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"
@@ -76,7 +75,7 @@ Nodes = []
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
- controller := setupCosmosChainsControllerTestV2(t, &cosmos.CosmosConfig{
+ controller := setupCosmosChainsControllerTestV2(t, &coscfg.TOMLConfig{
ChainID: ptr(validId),
Enabled: ptr(true),
Chain: coscfg.Chain{
@@ -106,7 +105,7 @@ Nodes = []
func Test_CosmosChainsController_Index(t *testing.T) {
t.Parallel()
- chainA := &cosmos.CosmosConfig{
+ chainA := &coscfg.TOMLConfig{
ChainID: ptr("a" + cosmostest.RandomChainID()),
Enabled: ptr(true),
Chain: coscfg.Chain{
@@ -114,7 +113,7 @@ func Test_CosmosChainsController_Index(t *testing.T) {
},
}
- chainB := &cosmos.CosmosConfig{
+ chainB := &coscfg.TOMLConfig{
ChainID: ptr("b" + cosmostest.RandomChainID()),
Enabled: ptr(true),
Chain: coscfg.Chain{
@@ -174,7 +173,7 @@ type TestCosmosChainsController struct {
client cltest.HTTPClientCleaner
}
-func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...*cosmos.CosmosConfig) *TestCosmosChainsController {
+func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...*coscfg.TOMLConfig) *TestCosmosChainsController {
for i := range cfgs {
cfgs[i].SetDefaults()
}
diff --git a/core/web/cosmos_transfer_controller.go b/core/web/cosmos_transfer_controller.go
index afe0fe16d1..965f694fc1 100644
--- a/core/web/cosmos_transfer_controller.go
+++ b/core/web/cosmos_transfer_controller.go
@@ -1,26 +1,26 @@
package web
import (
+ "fmt"
"net/http"
+ "slices"
sdk "github.com/cosmos/cosmos-sdk/types"
- bank "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/gin-gonic/gin"
+ "github.com/google/uuid"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
+ coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/denom"
+ "github.com/smartcontractkit/chainlink/v2/core/services/relay"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
cosmosmodels "github.com/smartcontractkit/chainlink/v2/core/store/models/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/web/presenters"
)
-// maxGasUsedTransfer is an upper bound on how much gas we expect a MsgSend for a single coin to use.
-const maxGasUsedTransfer = 100_000
-
// CosmosTransfersController can send LINK tokens to another address
type CosmosTransfersController struct {
App chainlink.Application
@@ -28,9 +28,9 @@ type CosmosTransfersController struct {
// Create sends native coins from the Chainlink's account to a specified address.
func (tc *CosmosTransfersController) Create(c *gin.Context) {
- cosmosChains := tc.App.GetRelayers().LegacyCosmosChains()
- if cosmosChains == nil {
- jsonAPIError(c, http.StatusBadRequest, ErrCosmosNotEnabled)
+ relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(relay.Cosmos))
+ if relayers == nil {
+ jsonAPIError(c, http.StatusBadRequest, ErrSolanaNotEnabled)
return
}
@@ -43,91 +43,51 @@ func (tc *CosmosTransfersController) Create(c *gin.Context) {
jsonAPIError(c, http.StatusBadRequest, errors.New("missing cosmosChainID"))
return
}
- // TODO what about ctx in Get? ctx was used here but not in ETH calls. maybe better to make the interface require ctx and
- // put in TODOs in ETH...
- chain, err := cosmosChains.Get(tr.CosmosChainID) //cosmosChains.Chain(c.Request.Context(), tr.CosmosChainID)
- if errors.Is(err, cosmos.ErrChainIDInvalid) || errors.Is(err, cosmos.ErrChainIDEmpty) {
- jsonAPIError(c, http.StatusBadRequest, err)
+ if tr.FromAddress.Empty() {
+ jsonAPIError(c, http.StatusUnprocessableEntity, errors.Errorf("withdrawal source address is missing: %v", tr.FromAddress))
return
- } else if err != nil {
+ }
+
+ relayerID := relay.ID{Network: relay.Cosmos, ChainID: tr.CosmosChainID}
+ relayer, err := relayers.Get(relayerID)
+ if err != nil {
+ if errors.Is(err, chainlink.ErrNoSuchRelayer) {
+ jsonAPIError(c, http.StatusBadRequest, err)
+ return
+ }
jsonAPIError(c, http.StatusInternalServerError, err)
return
}
-
- if tr.FromAddress.Empty() {
- jsonAPIError(c, http.StatusUnprocessableEntity, errors.Errorf("withdrawal source address is missing: %v", tr.FromAddress))
+ var gasToken string
+ cfgs := tc.App.GetConfig().CosmosConfigs()
+ if i := slices.IndexFunc(cfgs, func(config *coscfg.TOMLConfig) bool { return *config.ChainID == tr.CosmosChainID }); i != -1 {
+ gasToken = cfgs[i].GasToken()
+ } else {
+ jsonAPIError(c, http.StatusInternalServerError, fmt.Errorf("no config for chain id: %s", tr.CosmosChainID))
return
}
- coin, err := denom.ConvertDecCoinToDenom(sdk.NewDecCoinFromDec(tr.Token, tr.Amount), chain.Config().GasToken())
+
+ //TODO move this inside?
+ coin, err := denom.ConvertDecCoinToDenom(sdk.NewDecCoinFromDec(tr.Token, tr.Amount), gasToken)
if err != nil {
- jsonAPIError(c, http.StatusBadRequest, errors.Errorf("unable to convert %s to %s: %v", tr.Token, chain.Config().GasToken(), err))
+ jsonAPIError(c, http.StatusBadRequest, errors.Errorf("unable to convert %s to %s: %v", tr.Token, gasToken, err))
return
} else if !coin.Amount.IsPositive() {
jsonAPIError(c, http.StatusBadRequest, errors.Errorf("amount must be greater than zero: %s", coin.Amount))
return
}
- txm := chain.TxManager()
-
- if !tr.AllowHigherAmounts {
- var reader client.Reader
- reader, err = chain.Reader("")
- if err != nil {
- jsonAPIError(c, http.StatusInternalServerError, errors.Errorf("chain unreachable: %v", err))
- return
- }
- gasPrice, err2 := txm.GasPrice()
- if err2 != nil {
- jsonAPIError(c, http.StatusInternalServerError, errors.Errorf("gas price unavailable: %v", err2))
- return
- }
-
- err = cosmosValidateBalance(reader, gasPrice, tr.FromAddress, coin)
- if err != nil {
- jsonAPIError(c, http.StatusUnprocessableEntity, errors.Errorf("failed to validate balance: %v", err))
- return
- }
- }
-
- sendMsg := bank.NewMsgSend(tr.FromAddress, tr.DestinationAddress, sdk.Coins{coin})
- msgID, err := txm.Enqueue("", sendMsg)
+ err = relayer.Transact(c, tr.FromAddress.String(), tr.DestinationAddress.String(), coin.Amount.BigInt(), !tr.AllowHigherAmounts)
if err != nil {
- jsonAPIError(c, http.StatusInternalServerError, errors.Errorf("transaction failed: %v", err))
+ jsonAPIError(c, http.StatusInternalServerError, errors.Errorf("failed to send transaction: %v", err))
return
}
- resource := presenters.NewCosmosMsgResource(msgID, tr.CosmosChainID, "")
- msgs, err := txm.GetMsgs(msgID)
- if err != nil {
- jsonAPIError(c, http.StatusInternalServerError, errors.Errorf("failed to get message %d: %v", msgID, err))
- return
- }
- if len(msgs) != 1 {
- jsonAPIError(c, http.StatusInternalServerError, errors.Errorf("failed to get message %d: %v", msgID, err))
- return
- }
- msg := msgs[0]
- resource.TxHash = msg.TxHash
- resource.State = string(msg.State)
+ resource := presenters.NewCosmosMsgResource("cosmos_transfer_"+uuid.New().String(), tr.CosmosChainID, "")
+ resource.State = string(db.Unstarted)
tc.App.GetAuditLogger().Audit(audit.CosmosTransactionCreated, map[string]interface{}{
"cosmosTransactionResource": resource,
})
jsonAPIResponse(c, resource, "cosmos_msg")
}
-
-// cosmosValidateBalance validates that fromAddr's balance can cover coin, including fees at gasPrice.
-func cosmosValidateBalance(reader client.Reader, gasPrice sdk.DecCoin, fromAddr sdk.AccAddress, coin sdk.Coin) error {
- balance, err := reader.Balance(fromAddr, coin.GetDenom())
- if err != nil {
- return err
- }
-
- fee := gasPrice.Amount.MulInt64(maxGasUsedTransfer).RoundInt()
- need := coin.Amount.Add(fee)
-
- if balance.Amount.LT(need) {
- return errors.Errorf("balance %q is too low for this transaction to be executed: need %s total, including %s fee", balance, need, fee)
- }
- return nil
-}
diff --git a/core/web/presenters/cosmos_msg.go b/core/web/presenters/cosmos_msg.go
index d4fbc905bd..5bf0bb9b4f 100644
--- a/core/web/presenters/cosmos_msg.go
+++ b/core/web/presenters/cosmos_msg.go
@@ -15,9 +15,9 @@ func (CosmosMsgResource) GetName() string {
}
// NewCosmosMsgResource returns a new partial CosmosMsgResource.
-func NewCosmosMsgResource(id int64, chainID string, contractID string) CosmosMsgResource {
+func NewCosmosMsgResource(id string, chainID string, contractID string) CosmosMsgResource {
return CosmosMsgResource{
- JAID: NewJAIDInt64(id),
+ JAID: NewJAID(id),
ChainID: chainID,
ContractID: contractID,
}
diff --git a/go.mod b/go.mod
index 14f195d495..9c14fe8c14 100644
--- a/go.mod
+++ b/go.mod
@@ -67,7 +67,7 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
diff --git a/go.sum b/go.sum
index c9700330fa..372e705c71 100644
--- a/go.sum
+++ b/go.sum
@@ -1457,8 +1457,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 21ce192126..a0be1dbd8c 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -383,7 +383,7 @@ require (
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 // indirect
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 64305ddc24..9cc918229f 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2360,8 +2360,8 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
From ef59cf4a36e75ca747ac2f4f1ac973bb04c9c072 Mon Sep 17 00:00:00 2001
From: Domino Valdano <2644901+reductionista@users.noreply.github.com>
Date: Mon, 30 Oct 2023 12:36:25 -0700
Subject: [PATCH 034/327] Avoid risky early abort before attempting to send a
tx in tx mgr (#11016)
* Warn instead of error if anything goes wrong with tx hash conflict detection
Ignore any other errors from the DELETE, since we're only looking for an edge case--usually there
will be no txhash conflict, and if there is we'll abort anyway on the
INSERT. In some cases aborting before we even try to send the tx could be hurtful (risking tx mgr
to get stuck) and in others it won't matter either way, but in no case would it ever be helpful.
* Document error handling
* Raise Warn level to Error, so a persistent error in DELETE query doesn't go unnoticed
---
core/chains/evm/txmgr/evm_tx_store.go | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 96963e78d7..cc28c71d78 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -1486,20 +1486,23 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx,
// Note: the record of the original abandoned transaction will remain in evm.txes, only the attempt is replaced. (Any receipt
// associated with the abandoned attempt would also be lost, although this shouldn't happen since only unconfirmed transactions
// can be abandoned.)
- result, err := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t
+ res, err := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t
WHERE t.id = a.eth_tx_id AND a.hash = $1 AND t.state = $2 AND t.error = 'abandoned'`,
attempt.Hash, txmgr.TxFatalError,
)
- if err == nil {
- count, err := result.RowsAffected()
- if err != nil {
- return pkgerrors.Wrap(err, "UpdateTxUnstartedToInProgress failed to get rows affected")
- }
- if count > 0 {
- o.logger.Debugf("Replacing abandoned tx with tx hash %s with tx_id=%d with identical tx hash", attempt.Hash, attempt.TxID)
- }
- } else {
- return pkgerrors.Wrap(err, "UpdateTxUnstartedToInProgress failed to delete abandoned transactions")
+
+ if err != nil {
+ // If the DELETE fails, we don't want to abort before at least attempting the INSERT. tx hash conflicts with
+ // abandoned transactions can only happen after a nonce reset. If the node is operating normally but there is
+ // some unexpected issue with the DELETE query, blocking the txmgr from sending transactions would be risky
+ // and could potentially get the node stuck. If the INSERT is going to succeed then we definitely want to continue.
+ // And even if the INSERT fails, an error message showing the txmgr is having trouble inserting tx's in the db may be
+ // easier to understand quickly if there is a problem with the node.
+ o.logger.Errorw("Ignoring unexpected db error while checking for txhash conflict", "err", err)
+ } else if rows, err := res.RowsAffected(); err != nil {
+ o.logger.Errorw("Ignoring unexpected db error reading rows affected while checking for txhash conflict", "err", err)
+ } else if rows > 0 {
+ o.logger.Debugf("Replacing abandoned tx with tx hash %s with tx_id=%d with identical tx hash", attempt.Hash, attempt.TxID)
}
var dbAttempt DbEthTxAttempt
From 612409932c1fd92d13de7322981639cbc1263df9 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Mon, 30 Oct 2023 15:58:03 -0400
Subject: [PATCH 035/327] Updates to use default keys when available (#11128)
---
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index a0be1dbd8c..1263c406aa 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -20,7 +20,7 @@ require (
github.com/rs/zerolog v1.30.0
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.0
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.1
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.27
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 9cc918229f..08c037dd0c 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2368,8 +2368,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.0 h1:Ru7odxF0tq0FixJXM58rNZw0PvyQnRroqAInBAM83gs=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.0/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.1 h1:YznR7isiPYbywuUma5eVSyuZYwbUHIGJ2lpcJazOZgo=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.1/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
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 44bf841b393c12d4d62339e21fa3233919beb750 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Mon, 30 Oct 2023 16:03:23 -0400
Subject: [PATCH 036/327] Manually Trigger Integration Tests (#11129)
* First attempt
* Enable dispatch
---
.github/workflows/integration-tests.yml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 98e59ce8d4..5074fc35b9 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -8,6 +8,13 @@ on:
push:
tags:
- "*"
+ workflow_dispatch:
+ inputs:
+ liveNetwork:
+ description: "Run Live Testnet Tests"
+ required: false
+ type: boolean
+
# Only run 1 of this workflow at a time per PR
concurrency:
@@ -886,7 +893,7 @@ jobs:
### Start Live Testnet Section
testnet-smoke-tests-matrix:
- if: ${{ github.event_name == 'schedule' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) }} ## Only run live tests on new tags and nightly
+ if: ${{ github.event_name == 'schedule' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && inputs.liveNetwork) }} ## Only run live tests on new tags, schedule, or on manual request
environment: integration
permissions:
checks: write
From 2534e1a6055b9e409b2a9f0710cc860f0518ec24 Mon Sep 17 00:00:00 2001
From: Mateusz Sekara
Date: Tue, 31 Oct 2023 10:40:05 +0100
Subject: [PATCH 037/327] CCIP-1230 Exposing entire LogPollerBlock from
LatestBlock in LogPoller (#11105)
* Exposing entire LogPollerBlock from LatestBlock function in the LogPoller's interface
* Exposing entire LogPollerBlock from LatestBlock function in the LogPoller's interface
---
core/chains/evm/logpoller/disabled.go | 4 +-
core/chains/evm/logpoller/helper_test.go | 2 +-
core/chains/evm/logpoller/log_poller.go | 8 ++--
.../evm/logpoller/log_poller_internal_test.go | 2 +-
core/chains/evm/logpoller/log_poller_test.go | 39 ++++++++++++-------
core/chains/evm/logpoller/mocks/log_poller.go | 10 ++---
core/services/blockhashstore/coordinators.go | 6 +--
core/services/blockhashstore/delegate.go | 2 +-
core/services/blockhashstore/delegate_test.go | 3 +-
core/services/blockhashstore/feeder_test.go | 6 +--
.../plugins/ocr2keeper/evm20/log_provider.go | 24 ++++++------
.../ocr2/plugins/ocr2keeper/evm20/registry.go | 10 ++---
.../plugins/ocr2keeper/evm20/registry_test.go | 2 +-
.../ocr2keeper/evm21/block_subscriber.go | 7 ++--
.../ocr2keeper/evm21/block_subscriber_test.go | 4 +-
.../evm21/logprovider/block_time.go | 5 ++-
.../evm21/logprovider/block_time_test.go | 2 +-
.../evm21/logprovider/integration_test.go | 4 +-
.../ocr2keeper/evm21/logprovider/provider.go | 10 ++---
.../evm21/logprovider/provider_life_cycle.go | 2 +-
.../logprovider/provider_life_cycle_test.go | 5 ++-
.../evm21/logprovider/provider_test.go | 2 +-
.../ocr2keeper/evm21/logprovider/recoverer.go | 8 ++--
.../evm21/logprovider/recoverer_test.go | 11 +++---
.../ocr2/plugins/ocr2keeper/evm21/registry.go | 10 ++---
.../plugins/ocr2keeper/evm21/registry_test.go | 2 +-
.../evm21/transmit/event_provider.go | 6 +--
.../evm21/transmit/event_provider_test.go | 2 +-
.../ocr2vrf/coordinator/coordinator.go | 2 +-
.../ocr2vrf/coordinator/coordinator_test.go | 4 +-
core/services/relay/evm/config_poller.go | 2 +-
.../relay/evm/functions/config_poller.go | 2 +-
.../relay/evm/functions/logpoller_wrapper.go | 15 +++----
.../evm/functions/logpoller_wrapper_test.go | 2 +-
.../relay/evm/mercury/config_poller.go | 2 +-
35 files changed, 123 insertions(+), 104 deletions(-)
diff --git a/core/chains/evm/logpoller/disabled.go b/core/chains/evm/logpoller/disabled.go
index 4bcf1c5086..b54d4e6fc8 100644
--- a/core/chains/evm/logpoller/disabled.go
+++ b/core/chains/evm/logpoller/disabled.go
@@ -39,7 +39,9 @@ func (disabled) UnregisterFilter(name string, qopts ...pg.QOpt) error { return E
func (disabled) HasFilter(name string) bool { return false }
-func (disabled) LatestBlock(qopts ...pg.QOpt) (int64, error) { return -1, ErrDisabled }
+func (disabled) LatestBlock(qopts ...pg.QOpt) (LogPollerBlock, error) {
+ return LogPollerBlock{}, ErrDisabled
+}
func (disabled) GetBlocksRange(ctx context.Context, numbers []uint64, qopts ...pg.QOpt) ([]LogPollerBlock, error) {
return nil, ErrDisabled
diff --git a/core/chains/evm/logpoller/helper_test.go b/core/chains/evm/logpoller/helper_test.go
index 8415641c40..c61d3d5fad 100644
--- a/core/chains/evm/logpoller/helper_test.go
+++ b/core/chains/evm/logpoller/helper_test.go
@@ -92,7 +92,7 @@ func SetupTH(t testing.TB, useFinalityTag bool, finalityDepth, backfillBatchSize
func (th *TestHarness) PollAndSaveLogs(ctx context.Context, currentBlockNumber int64) int64 {
th.LogPoller.PollAndSaveLogs(ctx, currentBlockNumber)
latest, _ := th.LogPoller.LatestBlock(pg.WithParentCtx(ctx))
- return latest + 1
+ return latest.BlockNumber + 1
}
func (th *TestHarness) assertDontHave(t *testing.T, start, end int) {
diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go
index 6cda8f5b46..4cd2804d9f 100644
--- a/core/chains/evm/logpoller/log_poller.go
+++ b/core/chains/evm/logpoller/log_poller.go
@@ -38,7 +38,7 @@ type LogPoller interface {
RegisterFilter(filter Filter, qopts ...pg.QOpt) error
UnregisterFilter(name string, qopts ...pg.QOpt) error
HasFilter(name string) bool
- LatestBlock(qopts ...pg.QOpt) (int64, error)
+ LatestBlock(qopts ...pg.QOpt) (LogPollerBlock, error)
GetBlocksRange(ctx context.Context, numbers []uint64, qopts ...pg.QOpt) ([]LogPollerBlock, error)
// General querying
@@ -1019,13 +1019,13 @@ func (lp *logPoller) IndexedLogsTopicRange(eventSig common.Hash, address common.
// LatestBlock returns the latest block the log poller is on. It tracks blocks to be able
// to detect reorgs.
-func (lp *logPoller) LatestBlock(qopts ...pg.QOpt) (int64, error) {
+func (lp *logPoller) LatestBlock(qopts ...pg.QOpt) (LogPollerBlock, error) {
b, err := lp.orm.SelectLatestBlock(qopts...)
if err != nil {
- return 0, err
+ return LogPollerBlock{}, err
}
- return b.BlockNumber, nil
+ return *b, nil
}
func (lp *logPoller) BlockByNumber(n int64, qopts ...pg.QOpt) (*LogPollerBlock, error) {
diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go
index b9474158a6..c0d081582f 100644
--- a/core/chains/evm/logpoller/log_poller_internal_test.go
+++ b/core/chains/evm/logpoller/log_poller_internal_test.go
@@ -262,7 +262,7 @@ func TestLogPoller_Replay(t *testing.T) {
lp.PollAndSaveLogs(tctx, 4)
latest, err := lp.LatestBlock()
require.NoError(t, err)
- require.Equal(t, int64(4), latest)
+ require.Equal(t, int64(4), latest.BlockNumber)
t.Run("abort before replayStart received", func(t *testing.T) {
// Replay() should abort immediately if caller's context is cancelled before request signal is read
diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go
index 1ee8f4dcb7..471c728cdd 100644
--- a/core/chains/evm/logpoller/log_poller_test.go
+++ b/core/chains/evm/logpoller/log_poller_test.go
@@ -311,8 +311,8 @@ func Test_BackupLogPoller(t *testing.T) {
body.Transactions = types.Transactions{} // number of tx's must match # of logs for GetLogs() to succeed
rawdb.WriteBody(th.EthDB, h.Hash(), h.Number.Uint64(), body)
- currentBlock := th.PollAndSaveLogs(ctx, 1)
- assert.Equal(t, int64(35), currentBlock)
+ currentBlockNumber := th.PollAndSaveLogs(ctx, 1)
+ assert.Equal(t, int64(35), currentBlockNumber)
// simulate logs becoming available
rawdb.WriteReceipts(th.EthDB, h.Hash(), h.Number.Uint64(), receipts)
@@ -342,12 +342,12 @@ func Test_BackupLogPoller(t *testing.T) {
markBlockAsFinalized(t, th, 34)
// Run ordinary poller + backup poller at least once
- currentBlock, _ = th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
- th.LogPoller.PollAndSaveLogs(ctx, currentBlock+1)
+ currentBlock, _ := th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
+ th.LogPoller.PollAndSaveLogs(ctx, currentBlock.BlockNumber+1)
th.LogPoller.BackupPollAndSaveLogs(ctx, 100)
currentBlock, _ = th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
- require.Equal(t, int64(37), currentBlock+1)
+ require.Equal(t, int64(37), currentBlock.BlockNumber+1)
// logs still shouldn't show up, because we don't want to backfill the last finalized log
// to help with reorg detection
@@ -359,11 +359,11 @@ func Test_BackupLogPoller(t *testing.T) {
markBlockAsFinalized(t, th, 35)
// Run ordinary poller + backup poller at least once more
- th.LogPoller.PollAndSaveLogs(ctx, currentBlock+1)
+ th.LogPoller.PollAndSaveLogs(ctx, currentBlockNumber+1)
th.LogPoller.BackupPollAndSaveLogs(ctx, 100)
currentBlock, _ = th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
- require.Equal(t, int64(38), currentBlock+1)
+ require.Equal(t, int64(38), currentBlock.BlockNumber+1)
// all 3 logs in block 34 should show up now, thanks to backup logger
logs, err = th.LogPoller.Logs(30, 37, EmitterABI.Events["Log1"].ID, th.EmitterAddress1,
@@ -471,6 +471,13 @@ func TestLogPoller_BackupPollAndSaveLogsWithDeepBlockDelay(t *testing.T) {
// 1 -> 2 -> ...
th.PollAndSaveLogs(ctx, 1)
+ // Check that latest block has the same properties as the head
+ latestBlock, err := th.LogPoller.LatestBlock()
+ require.NoError(t, err)
+ assert.Equal(t, latestBlock.BlockNumber, header.Number.Int64())
+ assert.Equal(t, latestBlock.FinalizedBlockNumber, header.Number.Int64())
+ assert.Equal(t, latestBlock.BlockHash, header.Hash())
+
// Register filter
err = th.LogPoller.RegisterFilter(logpoller.Filter{
Name: "Test Emitter",
@@ -619,7 +626,7 @@ func TestLogPoller_BlockTimestamps(t *testing.T) {
require.Len(t, gethLogs, 2)
lb, _ := th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
- th.PollAndSaveLogs(context.Background(), lb+1)
+ th.PollAndSaveLogs(context.Background(), lb.BlockNumber+1)
lg1, err := th.LogPoller.Logs(0, 20, EmitterABI.Events["Log1"].ID, th.EmitterAddress1,
pg.WithParentCtx(testutils.Context(t)))
require.NoError(t, err)
@@ -667,9 +674,9 @@ func TestLogPoller_SynchronizedWithGeth(t *testing.T) {
for i := 0; i < finalityDepth; i++ { // Have enough blocks that we could reorg the full finalityDepth-1.
ec.Commit()
}
- currentBlock := int64(1)
- lp.PollAndSaveLogs(testutils.Context(t), currentBlock)
- currentBlock, err = lp.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
+ currentBlockNumber := int64(1)
+ lp.PollAndSaveLogs(testutils.Context(t), currentBlockNumber)
+ currentBlock, err := lp.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
require.NoError(t, err)
matchesGeth := func() bool {
// Check every block is identical
@@ -719,7 +726,7 @@ func TestLogPoller_SynchronizedWithGeth(t *testing.T) {
require.NoError(t, err1)
t.Logf("New latest (%v, %x), latest parent %x)\n", latest.NumberU64(), latest.Hash(), latest.ParentHash())
}
- lp.PollAndSaveLogs(testutils.Context(t), currentBlock)
+ lp.PollAndSaveLogs(testutils.Context(t), currentBlock.BlockNumber)
currentBlock, err = lp.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
require.NoError(t, err)
}
@@ -1245,7 +1252,7 @@ func TestGetReplayFromBlock(t *testing.T) {
require.NoError(t, err)
latest, err := th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
require.NoError(t, err)
- assert.Equal(t, latest, fromBlock)
+ assert.Equal(t, latest.BlockNumber, fromBlock)
// Should take min(latest, requested) in this case requested.
requested = int64(7)
@@ -1551,6 +1558,10 @@ func Test_PollAndSavePersistsFinalityInBlocks(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
th := SetupTH(t, tt.useFinalityTag, tt.finalityDepth, 3, 2, 1000)
+ // Should return error before the first poll and save
+ _, err := th.LogPoller.LatestBlock()
+ require.Error(t, err)
+
// Mark first block as finalized
h := th.Client.Blockchain().CurrentHeader()
th.Client.Blockchain().SetFinalized(h)
@@ -1562,7 +1573,7 @@ func Test_PollAndSavePersistsFinalityInBlocks(t *testing.T) {
th.PollAndSaveLogs(ctx, 1)
- latestBlock, err := th.ORM.SelectLatestBlock()
+ latestBlock, err := th.LogPoller.LatestBlock()
require.NoError(t, err)
require.Equal(t, int64(numberOfBlocks), latestBlock.BlockNumber)
require.Equal(t, tt.expectedFinalizedBlock, latestBlock.FinalizedBlockNumber)
diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go
index f435734164..01be5f7ba5 100644
--- a/core/chains/evm/logpoller/mocks/log_poller.go
+++ b/core/chains/evm/logpoller/mocks/log_poller.go
@@ -330,7 +330,7 @@ func (_m *LogPoller) IndexedLogsWithSigsExcluding(address common.Address, eventS
}
// LatestBlock provides a mock function with given fields: qopts
-func (_m *LogPoller) LatestBlock(qopts ...pg.QOpt) (int64, error) {
+func (_m *LogPoller) LatestBlock(qopts ...pg.QOpt) (logpoller.LogPollerBlock, error) {
_va := make([]interface{}, len(qopts))
for _i := range qopts {
_va[_i] = qopts[_i]
@@ -339,15 +339,15 @@ func (_m *LogPoller) LatestBlock(qopts ...pg.QOpt) (int64, error) {
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
- var r0 int64
+ var r0 logpoller.LogPollerBlock
var r1 error
- if rf, ok := ret.Get(0).(func(...pg.QOpt) (int64, error)); ok {
+ if rf, ok := ret.Get(0).(func(...pg.QOpt) (logpoller.LogPollerBlock, error)); ok {
return rf(qopts...)
}
- if rf, ok := ret.Get(0).(func(...pg.QOpt) int64); ok {
+ if rf, ok := ret.Get(0).(func(...pg.QOpt) logpoller.LogPollerBlock); ok {
r0 = rf(qopts...)
} else {
- r0 = ret.Get(0).(int64)
+ r0 = ret.Get(0).(logpoller.LogPollerBlock)
}
if rf, ok := ret.Get(1).(func(...pg.QOpt) error); ok {
diff --git a/core/services/blockhashstore/coordinators.go b/core/services/blockhashstore/coordinators.go
index ff5aff1f5e..4cb58bab6f 100644
--- a/core/services/blockhashstore/coordinators.go
+++ b/core/services/blockhashstore/coordinators.go
@@ -128,7 +128,7 @@ func (v *V1Coordinator) Fulfillments(ctx context.Context, fromBlock uint64) ([]E
logs, err := v.lp.LogsWithSigs(
int64(fromBlock),
- int64(toBlock),
+ toBlock.BlockNumber,
[]common.Hash{
v1.VRFCoordinatorRandomnessRequestFulfilled{}.Topic(),
},
@@ -219,7 +219,7 @@ func (v *V2Coordinator) Fulfillments(ctx context.Context, fromBlock uint64) ([]E
logs, err := v.lp.LogsWithSigs(
int64(fromBlock),
- int64(toBlock),
+ toBlock.BlockNumber,
[]common.Hash{
v2.VRFCoordinatorV2RandomWordsFulfilled{}.Topic(),
},
@@ -310,7 +310,7 @@ func (v *V2PlusCoordinator) Fulfillments(ctx context.Context, fromBlock uint64)
logs, err := v.lp.LogsWithSigs(
int64(fromBlock),
- int64(toBlock),
+ toBlock.BlockNumber,
[]common.Hash{
v2plus.IVRFCoordinatorV2PlusInternalRandomWordsFulfilled{}.Topic(),
},
diff --git a/core/services/blockhashstore/delegate.go b/core/services/blockhashstore/delegate.go
index 123052550b..c8e55e47c3 100644
--- a/core/services/blockhashstore/delegate.go
+++ b/core/services/blockhashstore/delegate.go
@@ -173,7 +173,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
if err != nil {
return 0, errors.Wrap(err, "getting chain head")
}
- return uint64(head), nil
+ return uint64(head.BlockNumber), nil
})
return []job.ServiceCtx{&service{
diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go
index 089e9544af..011ab87ad6 100644
--- a/core/services/blockhashstore/delegate_test.go
+++ b/core/services/blockhashstore/delegate_test.go
@@ -12,6 +12,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
@@ -58,7 +59,7 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) {
sendingKey, _ := cltest.MustInsertRandomKey(t, kst)
lp := &mocklp.LogPoller{}
lp.On("RegisterFilter", mock.Anything).Return(nil)
- lp.On("LatestBlock", mock.Anything, mock.Anything).Return(int64(0), nil)
+ lp.On("LatestBlock", mock.Anything, mock.Anything).Return(logpoller.LogPollerBlock{}, nil)
relayExtenders := evmtest.NewChainRelayExtenders(
t,
diff --git a/core/services/blockhashstore/feeder_test.go b/core/services/blockhashstore/feeder_test.go
index 3145a9fd76..8d9ed48c4b 100644
--- a/core/services/blockhashstore/feeder_test.go
+++ b/core/services/blockhashstore/feeder_test.go
@@ -445,7 +445,7 @@ func (test testCase) testFeederWithLogPollerVRFv1(t *testing.T) {
// Mock log poller.
lp.On("LatestBlock", mock.Anything).
- Return(latest, nil)
+ Return(logpoller.LogPollerBlock{BlockNumber: latest}, nil)
lp.On(
"LogsWithSigs",
fromBlock,
@@ -543,7 +543,7 @@ func (test testCase) testFeederWithLogPollerVRFv2(t *testing.T) {
// Mock log poller.
lp.On("LatestBlock", mock.Anything).
- Return(latest, nil)
+ Return(logpoller.LogPollerBlock{BlockNumber: latest}, nil)
lp.On(
"LogsWithSigs",
fromBlock,
@@ -641,7 +641,7 @@ func (test testCase) testFeederWithLogPollerVRFv2Plus(t *testing.T) {
// Mock log poller.
lp.On("LatestBlock", mock.Anything).
- Return(latest, nil)
+ Return(logpoller.LogPollerBlock{BlockNumber: latest}, nil)
lp.On(
"LogsWithSigs",
fromBlock,
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
index 856e508fc5..4044bb5f2a 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
@@ -151,8 +151,8 @@ func (c *LogProvider) PerformLogs(ctx context.Context) ([]ocr2keepers.PerformLog
// always check the last lookback number of blocks and rebroadcast
// this allows the plugin to make decisions based on event confirmations
logs, err := c.logPoller.LogsWithSigs(
- end-c.lookbackBlocks,
- end,
+ end.BlockNumber-c.lookbackBlocks,
+ end.BlockNumber,
[]common.Hash{
registry.KeeperRegistryUpkeepPerformed{}.Topic(),
},
@@ -175,7 +175,7 @@ func (c *LogProvider) PerformLogs(ctx context.Context) ([]ocr2keepers.PerformLog
Key: UpkeepKeyHelper[uint32]{}.MakeUpkeepKey(p.CheckBlockNumber, p.Id),
TransmitBlock: BlockKeyHelper[int64]{}.MakeBlockKey(p.BlockNumber),
TransactionHash: p.TxHash.Hex(),
- Confirmations: end - p.BlockNumber,
+ Confirmations: end.BlockNumber - p.BlockNumber,
}
vals = append(vals, l)
}
@@ -194,8 +194,8 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR
// ReorgedUpkeepReportLogs
logs, err := c.logPoller.LogsWithSigs(
- end-c.lookbackBlocks,
- end,
+ end.BlockNumber-c.lookbackBlocks,
+ end.BlockNumber,
[]common.Hash{
registry.KeeperRegistryReorgedUpkeepReport{}.Topic(),
},
@@ -212,8 +212,8 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR
// StaleUpkeepReportLogs
logs, err = c.logPoller.LogsWithSigs(
- end-c.lookbackBlocks,
- end,
+ end.BlockNumber-c.lookbackBlocks,
+ end.BlockNumber,
[]common.Hash{
registry.KeeperRegistryStaleUpkeepReport{}.Topic(),
},
@@ -230,8 +230,8 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR
// InsufficientFundsUpkeepReportLogs
logs, err = c.logPoller.LogsWithSigs(
- end-c.lookbackBlocks,
- end,
+ end.BlockNumber-c.lookbackBlocks,
+ end.BlockNumber,
[]common.Hash{
registry.KeeperRegistryInsufficientFundsUpkeepReport{}.Topic(),
},
@@ -258,7 +258,7 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR
Key: encoding.BasicEncoder{}.MakeUpkeepKey(checkBlockNumber, upkeepId),
TransmitBlock: BlockKeyHelper[int64]{}.MakeBlockKey(r.BlockNumber),
TransactionHash: r.TxHash.Hex(),
- Confirmations: end - r.BlockNumber,
+ Confirmations: end.BlockNumber - r.BlockNumber,
}
vals = append(vals, l)
}
@@ -273,7 +273,7 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR
Key: encoding.BasicEncoder{}.MakeUpkeepKey(checkBlockNumber, upkeepId),
TransmitBlock: BlockKeyHelper[int64]{}.MakeBlockKey(r.BlockNumber),
TransactionHash: r.TxHash.Hex(),
- Confirmations: end - r.BlockNumber,
+ Confirmations: end.BlockNumber - r.BlockNumber,
}
vals = append(vals, l)
}
@@ -288,7 +288,7 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR
Key: encoding.BasicEncoder{}.MakeUpkeepKey(checkBlockNumber, upkeepId),
TransmitBlock: BlockKeyHelper[int64]{}.MakeBlockKey(r.BlockNumber),
TransactionHash: r.TxHash.Hex(),
- Confirmations: end - r.BlockNumber,
+ Confirmations: end.BlockNumber - r.BlockNumber,
}
vals = append(vals, l)
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
index 49cab7b5a4..2d49a91e98 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
@@ -347,7 +347,7 @@ func (r *EvmRegistry) initialize() error {
func (r *EvmRegistry) pollLogs() error {
var latest int64
- var end int64
+ var end logpoller.LogPollerBlock
var err error
if end, err = r.poller.LatestBlock(pg.WithParentCtx(r.ctx)); err != nil {
@@ -356,11 +356,11 @@ func (r *EvmRegistry) pollLogs() error {
r.mu.Lock()
latest = r.lastPollBlock
- r.lastPollBlock = end
+ r.lastPollBlock = end.BlockNumber
r.mu.Unlock()
// if start and end are the same, no polling needs to be done
- if latest == 0 || latest == end {
+ if latest == 0 || latest == end.BlockNumber {
return nil
}
@@ -368,8 +368,8 @@ func (r *EvmRegistry) pollLogs() error {
var logs []logpoller.Log
if logs, err = r.poller.LogsWithSigs(
- end-logEventLookback,
- end,
+ end.BlockNumber-logEventLookback,
+ end.BlockNumber,
upkeepStateEvents,
r.addr,
pg.WithParentCtx(r.ctx),
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
index 348b5a47c0..8662bfd047 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
@@ -189,7 +189,7 @@ func TestPollLogs(t *testing.T) {
if test.LatestBlock != nil {
mp.On("LatestBlock", mock.Anything).
- Return(test.LatestBlock.OutputBlock, test.LatestBlock.OutputErr)
+ Return(logpoller.LogPollerBlock{BlockNumber: test.LatestBlock.OutputBlock}, test.LatestBlock.OutputErr)
}
if test.LogsWithSigs != nil {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
index 2d524e6f6c..d97156ed18 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
@@ -79,12 +79,13 @@ func (bs *BlockSubscriber) getBlockRange(ctx context.Context) ([]uint64, error)
if err != nil {
return nil, err
}
- bs.lggr.Infof("latest block from log poller is %d", h)
+ latestBlockNumber := h.BlockNumber
+ bs.lggr.Infof("latest block from log poller is %d", latestBlockNumber)
var blocks []uint64
for i := bs.blockSize - 1; i >= 0; i-- {
- if h-i > 0 {
- blocks = append(blocks, uint64(h-i))
+ if latestBlockNumber-i > 0 {
+ blocks = append(blocks, uint64(latestBlockNumber-i))
}
}
return blocks, nil
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
index 618ea83d4e..004b5fac6c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
@@ -97,7 +97,7 @@ func TestBlockSubscriber_GetBlockRange(t *testing.T) {
for _, tc := range tests {
t.Run(tc.Name, func(t *testing.T) {
lp := new(mocks.LogPoller)
- lp.On("LatestBlock", mock.Anything).Return(tc.LatestBlock, tc.LatestBlockErr)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: tc.LatestBlock}, tc.LatestBlockErr)
bs := NewBlockSubscriber(hb, lp, finality, lggr)
bs.blockHistorySize = historySize
bs.blockSize = blockSize
@@ -278,7 +278,7 @@ func TestBlockSubscriber_Start(t *testing.T) {
hb := commonmocks.NewHeadBroadcaster[*evmtypes.Head, common.Hash](t)
hb.On("Subscribe", mock.Anything).Return(&evmtypes.Head{Number: 42}, func() {})
lp := new(mocks.LogPoller)
- lp.On("LatestBlock", mock.Anything).Return(int64(100), nil)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: 100}, nil)
blocks := []uint64{97, 98, 99, 100}
pollerBlocks := []logpoller.LogPollerBlock{
{
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go
index 9fc35dd84b..814ed29d90 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go
@@ -34,10 +34,11 @@ func (r *blockTimeResolver) BlockTime(ctx context.Context, blockSampleSize int64
if err != nil {
return 0, fmt.Errorf("failed to get latest block from poller: %w", err)
}
- if latest <= blockSampleSize {
+ latestBlockNumber := latest.BlockNumber
+ if latestBlockNumber <= blockSampleSize {
return defaultBlockTime, nil
}
- start, end := latest-blockSampleSize, latest
+ start, end := latestBlockNumber-blockSampleSize, latestBlockNumber
startTime, endTime, err := r.getSampleTimestamps(ctx, uint64(start), uint64(end))
if err != nil {
return 0, err
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go
index 0ad9990e18..7009cfaa9b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go
@@ -69,7 +69,7 @@ func TestBlockTimeResolver_BlockTime(t *testing.T) {
lp := new(lpmocks.LogPoller)
resolver := newBlockTimeResolver(lp)
- lp.On("LatestBlock", mock.Anything).Return(tc.latestBlock, tc.latestBlockErr)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: tc.latestBlock}, tc.latestBlockErr)
lp.On("GetBlocksRange", mock.Anything, mock.Anything).Return(tc.blocksRange, tc.blocksRangeErr)
blockTime, err := resolver.BlockTime(ctx, tc.blockSampleSize)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index 811468746e..dad3542039 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -317,7 +317,7 @@ func TestIntegration_LogEventProvider_RateLimit(t *testing.T) {
var minimumBlockCount int64 = 500
latestBlock, _ := lp.LatestBlock()
- assert.GreaterOrEqual(t, latestBlock, minimumBlockCount, "to ensure the integrety of the test, the minimum block count before the test should be %d but got %d", minimumBlockCount, latestBlock)
+ assert.GreaterOrEqual(t, latestBlock.BlockNumber, minimumBlockCount, "to ensure the integrety of the test, the minimum block count before the test should be %d but got %d", minimumBlockCount, latestBlock)
}
require.NoError(t, logProvider.ReadLogs(ctx, ids...))
@@ -564,7 +564,7 @@ func waitLogPoller(ctx context.Context, t *testing.T, backend *backends.Simulate
for {
latestPolled, lberr := lp.LatestBlock(pg.WithParentCtx(ctx))
require.NoError(t, lberr)
- if latestPolled >= latestBlock {
+ if latestPolled.BlockNumber >= latestBlock {
break
}
lp.PollAndSaveLogs(ctx, latestBlock)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
index 729bf4ade5..349db2902b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
@@ -161,11 +161,11 @@ func (p *logEventProvider) GetLatestPayloads(ctx context.Context) ([]ocr2keepers
if err != nil {
return nil, fmt.Errorf("%w: %s", ErrHeadNotAvailable, err)
}
- start := latest - p.opts.LookbackBlocks
+ start := latest.BlockNumber - p.opts.LookbackBlocks
if start <= 0 {
start = 1
}
- logs := p.buffer.dequeueRange(start, latest, AllowedLogsPerUpkeep, MaxPayloads)
+ logs := p.buffer.dequeueRange(start, latest.BlockNumber, AllowedLogsPerUpkeep, MaxPayloads)
// p.lggr.Debugw("got latest logs from buffer", "latest", latest, "diff", diff, "logs", len(logs))
@@ -199,12 +199,12 @@ func (p *logEventProvider) ReadLogs(pctx context.Context, ids ...*big.Int) error
if err != nil {
return fmt.Errorf("%w: %s", ErrHeadNotAvailable, err)
}
- if latest == 0 {
+ if latest.BlockNumber == 0 {
return fmt.Errorf("%w: %s", ErrHeadNotAvailable, "latest block is 0")
}
- filters := p.getFilters(latest, ids...)
+ filters := p.getFilters(latest.BlockNumber, ids...)
- err = p.readLogs(ctx, latest, filters)
+ err = p.readLogs(ctx, latest.BlockNumber, filters)
p.updateFiltersLastPoll(filters)
// p.lggr.Debugw("read logs for entries", "latestBlock", latest, "entries", len(entries), "err", err)
if err != nil {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle.go
index ab816adb1b..69a4872351 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle.go
@@ -128,7 +128,7 @@ func (p *logEventProvider) register(ctx context.Context, lpFilter logpoller.Filt
// already registered in DB before, no need to backfill
return nil
}
- backfillBlock := latest - int64(LogBackfillBuffer)
+ backfillBlock := latest.BlockNumber - int64(LogBackfillBuffer)
if backfillBlock < 1 {
// New chain, backfill from start
backfillBlock = 1
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
index 4b1ff06f31..03395cb5b5 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
@@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
@@ -109,7 +110,7 @@ func TestLogEventProvider_LifeCycle(t *testing.T) {
lp := new(mocks.LogPoller)
lp.On("RegisterFilter", mock.Anything).Return(nil)
lp.On("UnregisterFilter", mock.Anything).Return(nil)
- lp.On("LatestBlock", mock.Anything).Return(int64(0), nil)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{}, nil)
hasFitlerTimes := 1
if tc.unregister {
hasFitlerTimes = 2
@@ -149,7 +150,7 @@ func TestEventLogProvider_RefreshActiveUpkeeps(t *testing.T) {
mp.On("RegisterFilter", mock.Anything).Return(nil)
mp.On("UnregisterFilter", mock.Anything).Return(nil)
mp.On("HasFilter", mock.Anything).Return(false)
- mp.On("LatestBlock", mock.Anything).Return(int64(0), nil)
+ mp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{}, nil)
mp.On("ReplayAsync", mock.Anything).Return(nil)
p := NewLogProvider(logger.TestLogger(t), mp, &mockedPacker{}, NewUpkeepFilterStore(), NewOptions(200))
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
index db22886cbb..a8e33ba23b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
@@ -248,7 +248,7 @@ func TestLogEventProvider_ReadLogs(t *testing.T) {
mp.On("ReplayAsync", mock.Anything).Return()
mp.On("HasFilter", mock.Anything).Return(false)
mp.On("UnregisterFilter", mock.Anything, mock.Anything).Return(nil)
- mp.On("LatestBlock", mock.Anything).Return(int64(1), nil)
+ mp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: int64(1)}, nil)
mp.On("LogsWithSigs", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]logpoller.Log{
{
BlockNumber: 1,
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
index b74160ae91..d6e7ad51d1 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
@@ -208,7 +208,7 @@ func (r *logRecoverer) getLogTriggerCheckData(ctx context.Context, proposal ocr2
return nil, err
}
- start, offsetBlock := r.getRecoveryWindow(latest)
+ start, offsetBlock := r.getRecoveryWindow(latest.BlockNumber)
if proposal.Trigger.LogTriggerExtension == nil {
return nil, errors.New("missing log trigger extension")
}
@@ -297,7 +297,7 @@ func (r *logRecoverer) GetRecoveryProposals(ctx context.Context) ([]ocr2keepers.
allLogsCounter := 0
logsCount := map[string]int{}
- r.sortPending(uint64(latestBlock))
+ r.sortPending(uint64(latestBlock.BlockNumber))
var results, pending []ocr2keepers.UpkeepPayload
for _, payload := range r.pending {
@@ -330,7 +330,7 @@ func (r *logRecoverer) recover(ctx context.Context) error {
return fmt.Errorf("%w: %s", ErrHeadNotAvailable, err)
}
- start, offsetBlock := r.getRecoveryWindow(latest)
+ start, offsetBlock := r.getRecoveryWindow(latest.BlockNumber)
if offsetBlock < 0 {
// too soon to recover, we don't have enough blocks
return nil
@@ -611,7 +611,7 @@ func (r *logRecoverer) tryExpire(ctx context.Context, ids ...string) error {
return fmt.Errorf("failed to get states: %w", err)
}
lggr := r.lggr.With("where", "clean")
- start, _ := r.getRecoveryWindow(latestBlock)
+ start, _ := r.getRecoveryWindow(latestBlock.BlockNumber)
r.lock.Lock()
defer r.lock.Unlock()
var removed int
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
index 2fdf04f76c..c882a22bc1 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
@@ -32,7 +32,7 @@ func TestLogRecoverer_GetRecoverables(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
lp := &lpmocks.LogPoller{}
- lp.On("LatestBlock", mock.Anything).Return(int64(100), nil)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: 100}, nil)
r := NewLogRecoverer(logger.TestLogger(t), lp, nil, nil, nil, nil, NewOptions(200))
tests := []struct {
@@ -182,7 +182,7 @@ func TestLogRecoverer_Clean(t *testing.T) {
start, _ := r.getRecoveryWindow(0)
block24h := int64(math.Abs(float64(start)))
- lp.On("LatestBlock", mock.Anything).Return(block24h+oldLogsOffset, nil)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: block24h + oldLogsOffset}, nil)
statesReader.On("SelectByWorkIDs", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.states, nil)
r.lock.Lock()
@@ -423,7 +423,7 @@ func TestLogRecoverer_Recover(t *testing.T) {
recoverer, filterStore, lp, statesReader := setupTestRecoverer(t, time.Millisecond*50, lookbackBlocks)
filterStore.AddActiveUpkeeps(tc.active...)
- lp.On("LatestBlock", mock.Anything).Return(tc.latestBlock, tc.latestBlockErr)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: tc.latestBlock}, tc.latestBlockErr)
lp.On("LogsWithSigs", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.logs, tc.logsErr)
statesReader.On("SelectByWorkIDs", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.states, tc.statesErr)
@@ -1206,8 +1206,9 @@ type mockLogPoller struct {
func (p *mockLogPoller) LogsWithSigs(start, end int64, eventSigs []common.Hash, address common.Address, qopts ...pg.QOpt) ([]logpoller.Log, error) {
return p.LogsWithSigsFn(start, end, eventSigs, address, qopts...)
}
-func (p *mockLogPoller) LatestBlock(qopts ...pg.QOpt) (int64, error) {
- return p.LatestBlockFn(qopts...)
+func (p *mockLogPoller) LatestBlock(qopts ...pg.QOpt) (logpoller.LogPollerBlock, error) {
+ block, err := p.LatestBlockFn(qopts...)
+ return logpoller.LogPollerBlock{BlockNumber: block}, err
}
type mockClient struct {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
index 5d180c05b8..0ca20477f2 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
@@ -362,7 +362,7 @@ func (r *EvmRegistry) refreshLogTriggerUpkeepsBatch(logTriggerIDs []*big.Int) er
func (r *EvmRegistry) pollUpkeepStateLogs() error {
var latest int64
- var end int64
+ var end logpoller.LogPollerBlock
var err error
if end, err = r.poller.LatestBlock(pg.WithParentCtx(r.ctx)); err != nil {
@@ -371,18 +371,18 @@ func (r *EvmRegistry) pollUpkeepStateLogs() error {
r.mu.Lock()
latest = r.lastPollBlock
- r.lastPollBlock = end
+ r.lastPollBlock = end.BlockNumber
r.mu.Unlock()
// if start and end are the same, no polling needs to be done
- if latest == 0 || latest == end {
+ if latest == 0 || latest == end.BlockNumber {
return nil
}
var logs []logpoller.Log
if logs, err = r.poller.LogsWithSigs(
- end-logEventLookback,
- end,
+ end.BlockNumber-logEventLookback,
+ end.BlockNumber,
upkeepStateEvents,
r.addr,
pg.WithParentCtx(r.ctx),
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go
index 0cd5ecd259..4be0ccce4e 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go
@@ -145,7 +145,7 @@ func TestPollLogs(t *testing.T) {
if test.LatestBlock != nil {
mp.On("LatestBlock", mock.Anything).
- Return(test.LatestBlock.OutputBlock, test.LatestBlock.OutputErr)
+ Return(logpoller.LogPollerBlock{BlockNumber: test.LatestBlock.OutputBlock}, test.LatestBlock.OutputErr)
}
if test.LogsWithSigs != nil {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
index 5fd320df8e..8f84ca1495 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
@@ -141,8 +141,8 @@ func (c *EventProvider) GetLatestEvents(ctx context.Context) ([]ocr2keepers.Tran
// always check the last lookback number of blocks and rebroadcast
// this allows the plugin to make decisions based on event confirmations
logs, err := c.logPoller.LogsWithSigs(
- end-c.lookbackBlocks,
- end,
+ end.BlockNumber-c.lookbackBlocks,
+ end.BlockNumber,
[]common.Hash{
iregistry21.IKeeperRegistryMasterUpkeepPerformed{}.Topic(),
iregistry21.IKeeperRegistryMasterStaleUpkeepReport{}.Topic(),
@@ -156,7 +156,7 @@ func (c *EventProvider) GetLatestEvents(ctx context.Context) ([]ocr2keepers.Tran
return nil, fmt.Errorf("%w: failed to collect logs from log poller", err)
}
- return c.processLogs(end, logs...)
+ return c.processLogs(end.BlockNumber, logs...)
}
// processLogs will parse the unseen logs and return the corresponding transmit events.
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
index 72f3b63088..58e95bc423 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
@@ -89,7 +89,7 @@ func TestTransmitEventProvider_Sanity(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
- lp.On("LatestBlock", mock.Anything).Return(tc.latestBlock, nil)
+ lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: tc.latestBlock}, nil)
lp.On("LogsWithSigs", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.logs, nil)
res, err := provider.GetLatestEvents(ctx)
diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go
index e51b68f415..1b58a01732 100644
--- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go
+++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go
@@ -227,7 +227,7 @@ func (c *coordinator) CurrentChainHeight(ctx context.Context) (uint64, error) {
if err != nil {
return 0, err
}
- return uint64(head), nil
+ return uint64(head.BlockNumber), nil
}
// ReportIsOnchain returns true iff a report for the given OCR epoch/round is
diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
index 26d0f2996a..dc489b4958 100644
--- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
@@ -1032,7 +1032,7 @@ func TestCoordinator_ReportBlocks(t *testing.T) {
requestedBlocks := []uint64{195, 196}
lp := lp_mocks.NewLogPoller(t)
lp.On("LatestBlock", mock.Anything).
- Return(int64(latestHeadNumber), nil)
+ Return(logpoller.LogPollerBlock{BlockNumber: int64(latestHeadNumber)}, nil)
lp.On("GetBlocksRange", mock.Anything, append(requestedBlocks, uint64(latestHeadNumber-lookbackBlocks+1), uint64(latestHeadNumber)), mock.Anything).
Return(nil, errors.New("GetBlocks error"))
@@ -1720,7 +1720,7 @@ func getLogPoller(
lp := lp_mocks.NewLogPoller(t)
if needsLatestBlock {
lp.On("LatestBlock", mock.Anything).
- Return(int64(latestHeadNumber), nil)
+ Return(logpoller.LogPollerBlock{BlockNumber: int64(latestHeadNumber)}, nil)
}
var logPollerBlocks []logpoller.LogPollerBlock
diff --git a/core/services/relay/evm/config_poller.go b/core/services/relay/evm/config_poller.go
index 1cf2318b29..daccf400ea 100644
--- a/core/services/relay/evm/config_poller.go
+++ b/core/services/relay/evm/config_poller.go
@@ -212,7 +212,7 @@ func (cp *configPoller) LatestBlockHeight(ctx context.Context) (blockHeight uint
}
return 0, err
}
- return uint64(latest), nil
+ return uint64(latest.BlockNumber), nil
}
func (cp *configPoller) isConfigStoreAvailable() bool {
diff --git a/core/services/relay/evm/functions/config_poller.go b/core/services/relay/evm/functions/config_poller.go
index f068f13cc7..7a59d49989 100644
--- a/core/services/relay/evm/functions/config_poller.go
+++ b/core/services/relay/evm/functions/config_poller.go
@@ -181,7 +181,7 @@ func (cp *configPoller) LatestBlockHeight(ctx context.Context) (blockHeight uint
}
return 0, err
}
- return uint64(latest), nil
+ return uint64(latest.BlockNumber), nil
}
// called from LogPollerWrapper in a separate goroutine
diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go
index 777717d01c..d355bd6569 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper.go
@@ -77,7 +77,7 @@ func (l *logPollerWrapper) Start(context.Context) error {
l.lggr.Errorw("LogPollerWrapper: LatestBlock() failed, starting from 0", "error", err)
} else {
l.lggr.Debugw("LogPollerWrapper: LatestBlock() got starting block", "block", nextBlock)
- l.nextBlock = nextBlock - l.blockOffset
+ l.nextBlock = nextBlock.BlockNumber - l.blockOffset
}
l.closeWait.Add(1)
go l.checkForRouteUpdates()
@@ -123,9 +123,10 @@ func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmR
l.mu.Unlock()
return nil, nil, err
}
- latest -= l.blockOffset
- if latest >= nextBlock {
- l.nextBlock = latest + 1
+ latestBlockNumber := latest.BlockNumber
+ latestBlockNumber -= l.blockOffset
+ if latestBlockNumber >= nextBlock {
+ l.nextBlock = latestBlockNumber + 1
}
l.mu.Unlock()
@@ -136,18 +137,18 @@ func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmR
l.lggr.Debug("LatestEvents: no non-zero coordinators to check")
return resultsReq, resultsResp, errors.New("no non-zero coordinators to check")
}
- if latest < nextBlock {
+ if latestBlockNumber < nextBlock {
l.lggr.Debugw("LatestEvents: no new blocks to check", "latest", latest, "nextBlock", nextBlock)
return resultsReq, resultsResp, nil
}
for _, coordinator := range coordinators {
- requestLogs, err := l.logPoller.Logs(nextBlock, latest, functions_coordinator.FunctionsCoordinatorOracleRequest{}.Topic(), coordinator)
+ requestLogs, err := l.logPoller.Logs(nextBlock, latestBlockNumber, functions_coordinator.FunctionsCoordinatorOracleRequest{}.Topic(), coordinator)
if err != nil {
l.lggr.Errorw("LatestEvents: fetching request logs from LogPoller failed", "latest", latest, "nextBlock", nextBlock)
return nil, nil, err
}
- responseLogs, err := l.logPoller.Logs(nextBlock, latest, functions_coordinator.FunctionsCoordinatorOracleResponse{}.Topic(), coordinator)
+ responseLogs, err := l.logPoller.Logs(nextBlock, latestBlockNumber, functions_coordinator.FunctionsCoordinatorOracleResponse{}.Topic(), coordinator)
if err != nil {
l.lggr.Errorw("LatestEvents: fetching response logs from LogPoller failed", "latest", latest, "nextBlock", nextBlock)
return nil, nil, err
diff --git a/core/services/relay/evm/functions/logpoller_wrapper_test.go b/core/services/relay/evm/functions/logpoller_wrapper_test.go
index 224aa51a5d..c91c3c49aa 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper_test.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper_test.go
@@ -60,7 +60,7 @@ func setUp(t *testing.T, updateFrequencySec uint32) (*lpmocks.LogPoller, types.L
lpWrapper, err := functions.NewLogPollerWrapper(gethcommon.Address{}, config, client, lp, lggr)
require.NoError(t, err)
- lp.On("LatestBlock").Return(int64(100), nil)
+ lp.On("LatestBlock").Return(logpoller.LogPollerBlock{BlockNumber: int64(100)}, nil)
return lp, lpWrapper, client
}
diff --git a/core/services/relay/evm/mercury/config_poller.go b/core/services/relay/evm/mercury/config_poller.go
index 2f16157bfa..8964a28304 100644
--- a/core/services/relay/evm/mercury/config_poller.go
+++ b/core/services/relay/evm/mercury/config_poller.go
@@ -188,7 +188,7 @@ func (cp *ConfigPoller) LatestBlockHeight(ctx context.Context) (blockHeight uint
}
return 0, err
}
- return uint64(latest), nil
+ return uint64(latest.BlockNumber), nil
}
func (cp *ConfigPoller) startLogSubscription() {
From 943a1ade98bcc6cc134aa332074228257c72b141 Mon Sep 17 00:00:00 2001
From: Patrick
Date: Tue, 31 Oct 2023 07:07:10 -0400
Subject: [PATCH 038/327] fix/lint (#11131)
---
core/chains/evm/txmgr/evm_tx_store.go | 8 ++++----
core/utils/utils.go | 3 ---
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index cc28c71d78..86a06b6025 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -1486,19 +1486,19 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx,
// Note: the record of the original abandoned transaction will remain in evm.txes, only the attempt is replaced. (Any receipt
// associated with the abandoned attempt would also be lost, although this shouldn't happen since only unconfirmed transactions
// can be abandoned.)
- res, err := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t
+ res, err2 := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t
WHERE t.id = a.eth_tx_id AND a.hash = $1 AND t.state = $2 AND t.error = 'abandoned'`,
attempt.Hash, txmgr.TxFatalError,
)
- if err != nil {
+ if err2 != nil {
// If the DELETE fails, we don't want to abort before at least attempting the INSERT. tx hash conflicts with
// abandoned transactions can only happen after a nonce reset. If the node is operating normally but there is
// some unexpected issue with the DELETE query, blocking the txmgr from sending transactions would be risky
// and could potentially get the node stuck. If the INSERT is going to succeed then we definitely want to continue.
// And even if the INSERT fails, an error message showing the txmgr is having trouble inserting tx's in the db may be
// easier to understand quickly if there is a problem with the node.
- o.logger.Errorw("Ignoring unexpected db error while checking for txhash conflict", "err", err)
+ o.logger.Errorw("Ignoring unexpected db error while checking for txhash conflict", "err", err2)
} else if rows, err := res.RowsAffected(); err != nil {
o.logger.Errorw("Ignoring unexpected db error reading rows affected while checking for txhash conflict", "err", err)
} else if rows > 0 {
@@ -1511,7 +1511,7 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx,
if e != nil {
return pkgerrors.Wrap(e, "failed to BindNamed")
}
- err = tx.Get(&dbAttempt, query, args...)
+ err := tx.Get(&dbAttempt, query, args...)
if err != nil {
var pqErr *pgconn.PgError
if isPqErr := errors.As(err, &pqErr); isPqErr &&
diff --git a/core/utils/utils.go b/core/utils/utils.go
index b8515f3362..e5541ecf55 100644
--- a/core/utils/utils.go
+++ b/core/utils/utils.go
@@ -40,9 +40,6 @@ const (
DefaultSecretSize = 48
// EVMWordByteLen the length of an EVM Word Byte
EVMWordByteLen = 32
-
- // defaultErrorBufferCap is the default cap on the errors an error buffer can store at any time
- defaultErrorBufferCap = 50
)
// ZeroAddress is an address of all zeroes, otherwise in Ethereum as
From 14804a959975cf53aa52ab95f5f0438046a9cc42 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Tue, 31 Oct 2023 12:45:34 +0100
Subject: [PATCH 039/327] bump version without changes (#11118)
---
contracts/scripts/native_solc_compile_all_shared | 2 +-
.../src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol | 4 ++--
.../automation/upkeeps/LinkAvailableBalanceMonitor.sol | 6 +++---
.../src/v0.8/functions/dev/v1_X/FunctionsBilling.sol | 2 +-
contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol | 4 ++--
.../v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol | 4 ++--
.../dev/v1_X/accessControl/TermsOfServiceAllowList.sol | 4 ++--
.../functions/tests/v1_X/FunctionsSubscriptions.t.sol | 2 +-
contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol | 2 +-
contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol | 4 ++--
.../src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol | 4 ++--
.../v1_0_0/accessControl/TermsOfServiceAllowList.sol | 4 ++--
contracts/src/v0.8/llo-feeds/FeeManager.sol | 8 ++++----
contracts/src/v0.8/llo-feeds/RewardManager.sol | 4 ++--
contracts/src/v0.8/llo-feeds/Verifier.sol | 2 +-
contracts/src/v0.8/llo-feeds/VerifierProxy.sol | 2 +-
contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol | 2 +-
.../src/v0.8/llo-feeds/interfaces/IRewardManager.sol | 2 +-
contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol | 2 +-
.../src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol | 2 +-
.../v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol | 2 +-
.../llo-feeds/test/reward-manager/BaseRewardManager.t.sol | 2 +-
.../test/reward-manager/RewardManager.general.t.sol | 2 +-
.../v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol | 4 ++--
.../test/verifier/VerifierProxySetVerifierTest.t.sol | 2 +-
contracts/src/v0.8/operatorforwarder/dev/Operator.sol | 2 +-
contracts/src/v0.8/shared/mocks/WERC20Mock.sol | 2 +-
.../v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol | 4 ++--
.../shared/test/token/ERC677/OpStackBurnMintERC677.t.sol | 2 +-
contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol | 2 +-
.../v0.8/shared/token/ERC20/IOptimismMintableERC20.sol | 2 +-
contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol | 8 ++++----
contracts/src/v0.8/shared/token/ERC677/ERC677.sol | 4 ++--
.../v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol | 2 +-
contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol | 2 +-
.../{v4.8.0 => v4.8.3}/contracts/interfaces/IERC165.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/interfaces/IERC20.sol | 0
.../contracts/interfaces/draft-IERC20Permit.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/mocks/ERC20Mock.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/security/Pausable.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/token/ERC20/ERC20.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/token/ERC20/IERC20.sol | 0
.../contracts/token/ERC20/extensions/ERC20Burnable.sol | 0
.../contracts/token/ERC20/extensions/IERC20Metadata.sol | 0
.../token/ERC20/extensions/draft-ERC20Permit.sol | 0
.../token/ERC20/extensions/draft-IERC20Permit.sol | 0
.../contracts/token/ERC20/utils/SafeERC20.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/Address.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/Context.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/Counters.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/StorageSlot.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/Strings.sol | 0
.../contracts/utils/cryptography/ECDSA.sol | 0
.../contracts/utils/cryptography/EIP712.sol | 0
.../contracts/utils/introspection/IERC165.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/math/Math.sol | 0
.../{v4.8.0 => v4.8.3}/contracts/utils/math/SafeCast.sol | 0
.../contracts/utils/math/SignedMath.sol | 0
.../contracts/utils/structs/EnumerableMap.sol | 0
.../contracts/utils/structs/EnumerableSet.sol | 0
60 files changed, 54 insertions(+), 54 deletions(-)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/interfaces/IERC165.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/interfaces/IERC20.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/interfaces/draft-IERC20Permit.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/mocks/ERC20Mock.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/security/Pausable.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/ERC20.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/IERC20.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/extensions/ERC20Burnable.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/extensions/IERC20Metadata.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/extensions/draft-ERC20Permit.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/extensions/draft-IERC20Permit.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/token/ERC20/utils/SafeERC20.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/Address.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/Context.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/Counters.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/StorageSlot.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/Strings.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/cryptography/ECDSA.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/cryptography/EIP712.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/introspection/IERC165.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/math/Math.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/math/SafeCast.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/math/SignedMath.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/structs/EnumerableMap.sol (100%)
rename contracts/src/v0.8/vendor/openzeppelin-solidity/{v4.8.0 => v4.8.3}/contracts/utils/structs/EnumerableSet.sol (100%)
diff --git a/contracts/scripts/native_solc_compile_all_shared b/contracts/scripts/native_solc_compile_all_shared
index 705cedce7a..db421f45e0 100755
--- a/contracts/scripts/native_solc_compile_all_shared
+++ b/contracts/scripts/native_solc_compile_all_shared
@@ -28,4 +28,4 @@ compileContract () {
compileContract shared/token/ERC677/BurnMintERC677.sol
compileContract shared/token/ERC677/LinkToken.sol
compileContract shared/mocks/WERC20Mock.sol
-compileContract vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/ERC20.sol
+compileContract vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol
diff --git a/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol b/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol
index 61a6e882d8..d2a7adc67a 100644
--- a/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol
+++ b/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol
@@ -4,8 +4,8 @@ pragma solidity ^0.8.4;
import "../../shared/access/ConfirmedOwner.sol";
import "../interfaces/KeeperCompatibleInterface.sol";
-import "../../vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol";
-import "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol";
+import "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol";
+import "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title The ERC20BalanceMonitor contract.
diff --git a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
index 028579397a..e2d42bc066 100644
--- a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
+++ b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
@@ -4,9 +4,9 @@ pragma solidity 0.8.6;
import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
-import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol";
-import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
-import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol";
+import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol";
+import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
+import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol";
interface IAggregatorProxy {
function aggregator() external view returns (address);
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
index e7958a7bca..ed67d48543 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
@@ -8,7 +8,7 @@ import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol";
import {Routable} from "./Routable.sol";
import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
-import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol";
+import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
/// @title Functions Billing contract
/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON).
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol
index 8daa821bb5..2e12a75679 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol
@@ -10,8 +10,8 @@ import {FunctionsSubscriptions} from "./FunctionsSubscriptions.sol";
import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol";
-import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol";
-import {Pausable} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol";
+import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
+import {Pausable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol";
contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable, ITypeAndVersion, ConfirmedOwner {
using FunctionsResponse for FunctionsResponse.RequestMeta;
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol
index 86e762e39c..bcd01c1f0c 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol
@@ -7,8 +7,8 @@ import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol";
import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
-import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
-import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol";
+import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
+import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title Functions Subscriptions contract
/// @notice Contract that coordinates payment from users to the nodes of the Decentralized Oracle Network (DON).
diff --git a/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol b/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol
index fbeef3c298..b36d063ad7 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol
@@ -7,8 +7,8 @@ import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol
import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol";
-import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol";
-import {EnumerableSet} from "../../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol";
+import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol";
+import {EnumerableSet} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol";
/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service
contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner {
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
index df905fb8be..8f08a6c1e8 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
@@ -6,7 +6,7 @@ import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol";
import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol";
import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol";
-import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
+import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {FunctionsRouterSetup, FunctionsOwnerAcceptTermsOfServiceSetup, FunctionsClientSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsFulfillmentSetup} from "./Setup.t.sol";
diff --git a/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol b/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol
index 1f99903c5a..5168bdc01e 100644
--- a/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol
@@ -8,7 +8,7 @@ import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol";
import {Routable} from "./Routable.sol";
import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
-import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol";
+import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
/// @title Functions Billing contract
/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON).
diff --git a/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol b/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol
index dad50b042b..9f35c4dfe5 100644
--- a/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol
+++ b/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol
@@ -10,8 +10,8 @@ import {FunctionsSubscriptions} from "./FunctionsSubscriptions.sol";
import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
-import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol";
-import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol";
+import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
+import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol";
contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable, ITypeAndVersion, ConfirmedOwner {
using FunctionsResponse for FunctionsResponse.RequestMeta;
diff --git a/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol b/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol
index 7fa2368c46..b93d217473 100644
--- a/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol
+++ b/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol
@@ -7,8 +7,8 @@ import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol";
import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
-import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
-import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol";
+import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
+import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title Functions Subscriptions contract
/// @notice Contract that coordinates payment from users to the nodes of the Decentralized Oracle Network (DON).
diff --git a/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol b/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol
index a7b1357784..8a42e34cb8 100644
--- a/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol
+++ b/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol
@@ -7,8 +7,8 @@ import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol";
import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol";
-import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol";
-import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol";
+import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol";
+import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol";
/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service
contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner {
diff --git a/contracts/src/v0.8/llo-feeds/FeeManager.sol b/contracts/src/v0.8/llo-feeds/FeeManager.sol
index 0cc8273442..397605d9b2 100644
--- a/contracts/src/v0.8/llo-feeds/FeeManager.sol
+++ b/contracts/src/v0.8/llo-feeds/FeeManager.sol
@@ -4,13 +4,13 @@ pragma solidity 0.8.16;
import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {IFeeManager} from "./interfaces/IFeeManager.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
-import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../libraries/Common.sol";
import {IRewardManager} from "./interfaces/IRewardManager.sol";
import {IWERC20} from "../shared/interfaces/IWERC20.sol";
-import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC20.sol";
-import {Math} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/Math.sol";
-import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol";
+import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
+import {Math} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol";
+import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol";
/**
diff --git a/contracts/src/v0.8/llo-feeds/RewardManager.sol b/contracts/src/v0.8/llo-feeds/RewardManager.sol
index e064bff8b6..3777b432fc 100644
--- a/contracts/src/v0.8/llo-feeds/RewardManager.sol
+++ b/contracts/src/v0.8/llo-feeds/RewardManager.sol
@@ -3,10 +3,10 @@ pragma solidity 0.8.16;
import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {IRewardManager} from "./interfaces/IRewardManager.sol";
-import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC20.sol";
+import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
import {Common} from "../libraries/Common.sol";
-import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol";
+import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title RewardManager
diff --git a/contracts/src/v0.8/llo-feeds/Verifier.sol b/contracts/src/v0.8/llo-feeds/Verifier.sol
index cd7e3d2bad..f7ce156a60 100644
--- a/contracts/src/v0.8/llo-feeds/Verifier.sol
+++ b/contracts/src/v0.8/llo-feeds/Verifier.sol
@@ -5,7 +5,7 @@ import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {IVerifier} from "./interfaces/IVerifier.sol";
import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
-import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../libraries/Common.sol";
// OCR2 standard
diff --git a/contracts/src/v0.8/llo-feeds/VerifierProxy.sol b/contracts/src/v0.8/llo-feeds/VerifierProxy.sol
index 989c5c6b81..6abb2b78e9 100644
--- a/contracts/src/v0.8/llo-feeds/VerifierProxy.sol
+++ b/contracts/src/v0.8/llo-feeds/VerifierProxy.sol
@@ -6,7 +6,7 @@ import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol";
import {IVerifier} from "./interfaces/IVerifier.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
import {AccessControllerInterface} from "../shared/interfaces/AccessControllerInterface.sol";
-import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol";
import {Common} from "../libraries/Common.sol";
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol b/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol
index ed7213870e..08373a6a5b 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
-import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../../libraries/Common.sol";
import {IVerifierFeeManager} from "./IVerifierFeeManager.sol";
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol b/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol
index 68cecc4f97..a76366a3eb 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
-import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../../libraries/Common.sol";
interface IRewardManager is IERC165 {
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol b/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol
index 7617d9a5c3..9b9ba2e657 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
-import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../../libraries/Common.sol";
interface IVerifier is IERC165 {
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol b/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol
index 8e490d39d1..e5a73e612c 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
-import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../../libraries/Common.sol";
interface IVerifierFeeManager is IERC165 {
diff --git a/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol b/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol
index c446150406..ec2611f9e4 100644
--- a/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol
@@ -5,7 +5,7 @@ import {Test} from "forge-std/Test.sol";
import {FeeManager} from "../../FeeManager.sol";
import {RewardManager} from "../../RewardManager.sol";
import {Common} from "../../../libraries/Common.sol";
-import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/mocks/ERC20Mock.sol";
+import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {WERC20Mock} from "../../../shared/mocks/WERC20Mock.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
import {FeeManagerProxy} from "../mocks/FeeManagerProxy.sol";
diff --git a/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol b/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol
index 4a70109316..3e50adef95 100644
--- a/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {Test} from "forge-std/Test.sol";
-import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/mocks/ERC20Mock.sol";
+import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {RewardManager} from "../../RewardManager.sol";
import {Common} from "../../../libraries/Common.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
diff --git a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.general.t.sol b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.general.t.sol
index 9cee5b05c5..e7bc43dc81 100644
--- a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.general.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.general.t.sol
@@ -3,7 +3,7 @@ pragma solidity 0.8.16;
import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol";
import {RewardManager} from "../../RewardManager.sol";
-import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/mocks/ERC20Mock.sol";
+import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
/**
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol
index 3faa65fb52..91e0f9da90 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol
@@ -3,7 +3,7 @@ pragma solidity 0.8.16;
import {Test} from "forge-std/Test.sol";
import {VerifierProxy} from "../../VerifierProxy.sol";
-import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {IVerifier} from "../../interfaces/IVerifier.sol";
import {ErroredVerifier} from "../mocks/ErroredVerifier.sol";
import {Verifier} from "../../Verifier.sol";
@@ -11,7 +11,7 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol";
import {FeeManager} from "../../FeeManager.sol";
import {Common} from "../../../libraries/Common.sol";
-import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/mocks/ERC20Mock.sol";
+import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {WERC20Mock} from "../../../shared/mocks/WERC20Mock.sol";
import {FeeManager} from "../../FeeManager.sol";
import {RewardManager} from "../../RewardManager.sol";
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol
index 3699aaf420..a6b23d7e8b 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol
@@ -4,7 +4,7 @@ pragma solidity 0.8.16;
import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol";
import {IVerifier} from "../../interfaces/IVerifier.sol";
import {VerifierProxy} from "../../VerifierProxy.sol";
-import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol";
+import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {Common} from "../../../libraries/Common.sol";
contract VerifierProxyInitializeVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager {
diff --git a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol b/contracts/src/v0.8/operatorforwarder/dev/Operator.sol
index b68e283730..b83996a9ed 100644
--- a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol
+++ b/contracts/src/v0.8/operatorforwarder/dev/Operator.sol
@@ -11,7 +11,7 @@ import {IOwnable} from "../../shared/interfaces/IOwnable.sol";
import {WithdrawalInterface} from "./interfaces/WithdrawalInterface.sol";
import {OracleInterface} from "../../interfaces/OracleInterface.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
-import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol";
+import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
// @title The Chainlink Operator contract
// @notice Node operators can deploy this contract to fulfill requests sent to them
diff --git a/contracts/src/v0.8/shared/mocks/WERC20Mock.sol b/contracts/src/v0.8/shared/mocks/WERC20Mock.sol
index 02c13be993..cee7fa7ff8 100644
--- a/contracts/src/v0.8/shared/mocks/WERC20Mock.sol
+++ b/contracts/src/v0.8/shared/mocks/WERC20Mock.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/ERC20.sol";
+import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol";
contract WERC20Mock is ERC20 {
constructor() ERC20("WERC20Mock", "WERC") {}
diff --git a/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol b/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol
index 6b13f39000..de9067a569 100644
--- a/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol
+++ b/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol
@@ -7,8 +7,8 @@ import {IERC677} from "../../../token/ERC677/IERC677.sol";
import {BaseTest} from "../../BaseTest.t.sol";
import {BurnMintERC677} from "../../../token/ERC677/BurnMintERC677.sol";
-import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
-import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol";
+import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
+import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";
contract BurnMintERC677Setup is BaseTest {
event Transfer(address indexed from, address indexed to, uint256 value);
diff --git a/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol b/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol
index f22a92a425..7987fefec4 100644
--- a/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol
+++ b/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol
@@ -9,7 +9,7 @@ import {BurnMintERC677} from "../../../token/ERC677/BurnMintERC677.sol";
import {BaseTest} from "../../BaseTest.t.sol";
import {OpStackBurnMintERC677} from "../../../token/ERC677/OpStackBurnMintERC677.sol";
-import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol";
+import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";
contract OpStackBurnMintERC677Setup is BaseTest {
address internal s_l1Token = address(897352983527);
diff --git a/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol b/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol
index 2b2f3fd378..b9b3b54bf7 100644
--- a/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol
+++ b/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
+import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
interface IBurnMintERC20 is IERC20 {
/// @notice Mints new tokens for a given address.
diff --git a/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol b/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol
index 6362d9e78a..4e9d3a2494 100644
--- a/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol
+++ b/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol
@@ -2,7 +2,7 @@
// solhint-disable one-contract-per-file
pragma solidity ^0.8.0;
-import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol";
+import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";
/// @title IOptimismMintableERC20Minimal
/// @dev This interface is a subset of the Optimism ERC20 interface that is defined
diff --git a/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol b/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol
index 775d5fb3d9..556914da12 100644
--- a/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol
+++ b/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol
@@ -7,10 +7,10 @@ import {IERC677} from "./IERC677.sol";
import {ERC677} from "./ERC677.sol";
import {OwnerIsCreator} from "../../access/OwnerIsCreator.sol";
-import {ERC20Burnable} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/ERC20Burnable.sol";
-import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol";
-import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol";
-import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
+import {ERC20Burnable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol";
+import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol";
+import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";
+import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
/// @notice A basic ERC677 compatible token contract with burn and minting roles.
/// @dev The total supply can be limited during deployment.
diff --git a/contracts/src/v0.8/shared/token/ERC677/ERC677.sol b/contracts/src/v0.8/shared/token/ERC677/ERC677.sol
index c9a2996e8e..9a68bac3a1 100644
--- a/contracts/src/v0.8/shared/token/ERC677/ERC677.sol
+++ b/contracts/src/v0.8/shared/token/ERC677/ERC677.sol
@@ -4,8 +4,8 @@ pragma solidity ^0.8.0;
import {IERC677} from "./IERC677.sol";
import {IERC677Receiver} from "./IERC677Receiver.sol";
-import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol";
-import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/ERC20.sol";
+import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol";
+import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol";
contract ERC677 is IERC677, ERC20 {
using Address for address;
diff --git a/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol b/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol
index 714a4a11ba..95c64c9cd2 100644
--- a/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol
+++ b/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol
@@ -5,7 +5,7 @@ import {IOptimismMintableERC20Minimal, IOptimismMintableERC20} from "../ERC20/IO
import {BurnMintERC677} from "./BurnMintERC677.sol";
-import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol";
+import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";
/// @notice A basic ERC677 compatible token contract with burn and minting roles that supports
/// the native L2 bridging requirements of the Optimism Stack.
diff --git a/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol b/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol
index 1947379929..ae8b6af1cc 100644
--- a/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol
+++ b/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol
@@ -2,7 +2,7 @@
pragma solidity >=0.7.6 <0.9.0;
-import "./openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol";
+import "./openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol";
/**
* @title iOVM_CrossDomainMessenger
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC165.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC20.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/IERC20.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/draft-IERC20Permit.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/interfaces/draft-IERC20Permit.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/mocks/ERC20Mock.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/mocks/ERC20Mock.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/security/Pausable.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/ERC20.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/ERC20.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/ERC20Burnable.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/ERC20Burnable.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/IERC20Metadata.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/IERC20Metadata.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/draft-ERC20Permit.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/draft-ERC20Permit.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/draft-IERC20Permit.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Context.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Context.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Counters.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Counters.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/StorageSlot.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/StorageSlot.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Strings.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Strings.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/cryptography/ECDSA.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/cryptography/ECDSA.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/cryptography/EIP712.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/cryptography/EIP712.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/Math.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/Math.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SafeCast.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SignedMath.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/math/SignedMath.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol
diff --git a/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol b/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol
similarity index 100%
rename from contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol
rename to contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol
From 7cadec057ebc180b131deeed49bbb4a8b78aadcc Mon Sep 17 00:00:00 2001
From: Andrei Smirnov
Date: Tue, 31 Oct 2023 15:00:50 +0300
Subject: [PATCH 040/327] Contracts: running hardhat tests in parallel (#11090)
Co-authored-by: Rens Rooimans
---
contracts/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contracts/package.json b/contracts/package.json
index 935c7901b6..05a5293e48 100644
--- a/contracts/package.json
+++ b/contracts/package.json
@@ -6,7 +6,7 @@
"license": "MIT",
"private": false,
"scripts": {
- "test": "hardhat test",
+ "test": "hardhat test --parallel",
"lint": "eslint --ext js,ts .",
"prettier:check": "prettier '**/*' --check --ignore-unknown",
"prettier:write": "prettier '**/*' --write --ignore-unknown",
From 8fba9c8a4217356cf51a8ddda1daa62fbdb9e150 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Tue, 31 Oct 2023 12:29:17 +0000
Subject: [PATCH 041/327] [BCF-2727] Add telemetry adapter service (#11125)
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
.../ocr2/plugins/generic/telemetry_adapter.go | 56 +++++++++
.../plugins/generic/telemetry_adapter_test.go | 108 ++++++++++++++++++
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
8 files changed, 173 insertions(+), 9 deletions(-)
create mode 100644 core/services/ocr2/plugins/generic/telemetry_adapter.go
create mode 100644 core/services/ocr2/plugins/generic/telemetry_adapter_test.go
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 14e29a6740..690a8d189c 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -302,7 +302,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 08356fe076..5cbdb37427 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1458,8 +1458,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter.go b/core/services/ocr2/plugins/generic/telemetry_adapter.go
new file mode 100644
index 0000000000..a81befa985
--- /dev/null
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter.go
@@ -0,0 +1,56 @@
+package generic
+
+import (
+ "context"
+ "errors"
+
+ "github.com/smartcontractkit/libocr/commontypes"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+)
+
+var _ types.TelemetryService = (*TelemetryAdapter)(nil)
+
+type TelemetryAdapter struct {
+ endpointGenerator types.MonitoringEndpointGenerator
+ endpoints map[[4]string]commontypes.MonitoringEndpoint
+}
+
+func NewTelemetryAdapter(endpointGen types.MonitoringEndpointGenerator) *TelemetryAdapter {
+ return &TelemetryAdapter{
+ endpoints: make(map[[4]string]commontypes.MonitoringEndpoint),
+ endpointGenerator: endpointGen,
+ }
+}
+
+func (t *TelemetryAdapter) Send(ctx context.Context, network string, chainID string, contractID string, telemetryType string, payload []byte) error {
+ e, err := t.getOrCreateEndpoint(contractID, telemetryType, network, chainID)
+ if err != nil {
+ return err
+ }
+ e.SendLog(payload)
+ return nil
+}
+
+func (t *TelemetryAdapter) getOrCreateEndpoint(contractID string, telemetryType string, network string, chainID string) (commontypes.MonitoringEndpoint, error) {
+ if contractID == "" {
+ return nil, errors.New("contractID cannot be empty")
+ }
+ if telemetryType == "" {
+ return nil, errors.New("telemetryType cannot be empty")
+ }
+ if network == "" {
+ return nil, errors.New("network cannot be empty")
+ }
+ if chainID == "" {
+ return nil, errors.New("chainID cannot be empty")
+ }
+
+ key := [4]string{network, chainID, contractID, telemetryType}
+ e, ok := t.endpoints[key]
+ if !ok {
+ e = t.endpointGenerator.GenMonitoringEndpoint(network, chainID, contractID, telemetryType)
+ t.endpoints[key] = e
+ }
+ return e, nil
+}
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
new file mode 100644
index 0000000000..d430b889a4
--- /dev/null
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
@@ -0,0 +1,108 @@
+package generic
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/smartcontractkit/libocr/commontypes"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+type mockEndpoint struct {
+ network string
+ chainID string
+ contractID string
+ telemetryType string
+ payload []byte
+}
+
+func (m *mockEndpoint) SendLog(payload []byte) { m.payload = payload }
+
+type mockGenerator struct{}
+
+func (m *mockGenerator) GenMonitoringEndpoint(network, chainID, contractID, telemetryType string) commontypes.MonitoringEndpoint {
+ return &mockEndpoint{
+ network: network,
+ chainID: chainID,
+ contractID: contractID,
+ telemetryType: telemetryType,
+ }
+}
+
+func TestTelemetryAdapter(t *testing.T) {
+ ta := NewTelemetryAdapter(&mockGenerator{})
+
+ tests := []struct {
+ name string
+ contractID string
+ telemetryType string
+ networkID string
+ chainID string
+ payload []byte
+ errorMsg string
+ }{
+ {
+ name: "valid request",
+ contractID: "contract",
+ telemetryType: "mercury",
+ networkID: "solana",
+ chainID: "1337",
+ payload: []byte("uh oh"),
+ },
+ {
+ name: "no valid contractID",
+ telemetryType: "mercury",
+ networkID: "solana",
+ chainID: "1337",
+ payload: []byte("uh oh"),
+ errorMsg: "contractID cannot be empty",
+ },
+ {
+ name: "no valid chainID",
+ contractID: "contract",
+ telemetryType: "mercury",
+ networkID: "solana",
+ payload: []byte("uh oh"),
+ errorMsg: "chainID cannot be empty",
+ },
+ {
+ name: "no valid telemetryType",
+ contractID: "contract",
+ networkID: "solana",
+ chainID: "1337",
+ payload: []byte("uh oh"),
+ errorMsg: "telemetryType cannot be empty",
+ },
+ {
+ name: "no valid network",
+ contractID: "contract",
+ telemetryType: "mercury",
+ chainID: "1337",
+ payload: []byte("uh oh"),
+ errorMsg: "network cannot be empty",
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ err := ta.Send(context.Background(), test.networkID, test.chainID, test.contractID, test.telemetryType, test.payload)
+ if test.errorMsg != "" {
+ assert.ErrorContains(t, err, test.errorMsg)
+ } else {
+ require.NoError(t, err)
+ key := [4]string{test.networkID, test.chainID, test.contractID, test.telemetryType}
+ fmt.Printf("%+v", ta.endpoints)
+ endpoint, ok := ta.endpoints[key]
+ require.True(t, ok)
+
+ me := endpoint.(*mockEndpoint)
+ assert.Equal(t, test.networkID, me.network)
+ assert.Equal(t, test.chainID, me.chainID)
+ assert.Equal(t, test.contractID, me.contractID)
+ assert.Equal(t, test.telemetryType, me.telemetryType)
+ assert.Equal(t, test.payload, me.payload)
+ }
+ })
+ }
+}
diff --git a/go.mod b/go.mod
index 9c14fe8c14..ad3cb5f78e 100644
--- a/go.mod
+++ b/go.mod
@@ -68,7 +68,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index 372e705c71..f879f16272 100644
--- a/go.sum
+++ b/go.sum
@@ -1459,8 +1459,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 1263c406aa..3affd79919 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -384,7 +384,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 08c037dd0c..98685fdf88 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2362,8 +2362,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436 h1:XJuWThPInOZ9Bz0zM8xmACO+Ly/cY9+0JOILkHlN/2o=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231030111206-48c9bf5d5436/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From 9fd1d5d0e28dd631ac879035f56bee7e03e78713 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Tue, 31 Oct 2023 09:45:26 -0500
Subject: [PATCH 042/327] golangci-lint fix issue & disable only-new-issues
(#11133)
* core/services/ocr/plugins/generic: rm unused error return
* .github/actions/golangci-lint: disable only-new-issues
---
.github/actions/golangci-lint/action.yml | 2 +-
.../ocr2/plugins/generic/pipeline_runner_adapter.go | 9 ++-------
.../ocr2/plugins/generic/pipeline_runner_adapter_test.go | 3 +--
3 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml
index c9ea735d1f..97755fa46e 100644
--- a/.github/actions/golangci-lint/action.yml
+++ b/.github/actions/golangci-lint/action.yml
@@ -58,7 +58,7 @@ runs:
skip-pkg-cache: true
skip-build-cache: true
# only-new-issues is only applicable to PRs, otherwise it is always set to false
- only-new-issues: true
+ only-new-issues: false # disabled for PRs due to unreliability
args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml
working-directory: ${{ inputs.go-directory }}
- name: Store lint report artifact
diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
index 5c58522f40..6afb35ca75 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
@@ -41,10 +41,7 @@ func (p *PipelineRunnerAdapter) ExecuteRun(ctx context.Context, spec string, var
},
}
- err := merge(defaultVars, vars.Vars)
- if err != nil {
- return nil, err
- }
+ merge(defaultVars, vars.Vars)
finalVars := pipeline.NewVarsFrom(defaultVars)
_, trrs, err := p.runner.ExecuteRun(ctx, s, finalVars, p.logger)
@@ -74,7 +71,7 @@ func NewPipelineRunnerAdapter(logger logger.Logger, job job.Job, runner pipeline
}
// merge merges mapTwo into mapOne, modifying mapOne in the process.
-func merge(mapOne, mapTwo map[string]interface{}) error {
+func merge(mapOne, mapTwo map[string]interface{}) {
for k, v := range mapTwo {
// if `mapOne` doesn't have `k`, then nothing to do, just assign v to `mapOne`.
if _, ok := mapOne[k]; !ok {
@@ -89,6 +86,4 @@ func merge(mapOne, mapTwo map[string]interface{}) error {
}
}
}
-
- return nil
}
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 d1f06d8766..ee0038232d 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
@@ -131,8 +131,7 @@ func TestMerge(t *testing.T) {
"val": 0,
}
- err := merge(vars, addedVars)
- require.NoError(t, err)
+ merge(vars, addedVars)
assert.True(t, reflect.DeepEqual(vars, map[string]interface{}{
"jb": map[string]interface{}{
From 921a89ca6243d274062b2090458e6b40421242e9 Mon Sep 17 00:00:00 2001
From: ilija42 <57732589+ilija42@users.noreply.github.com>
Date: Tue, 31 Oct 2023 20:14:02 +0100
Subject: [PATCH 043/327] BCF-2672 cleanup legacy job orm env var loading
(#11119)
* Remove unused DRSpecConfig param in LoadEnvConfigVarsVRF
* Remove unused DirectRequestSpec MinIncomingConfirmationsEnv field
* Remove unnecessary DRSpecConfig wrapper interface from job orm
* Remove DirectRequestSpec MinIncomingConfirmations override from job orm
MinIncomingConfirmations for DirectRequestSpec already gets overridden in delegate before its only usage
* Remove DirectRequestSpec MinIncomingConfirmationsENV from graphql spec
* Revert removal of DirectRequestSpec MinIncomingConfirmationsENV
* Remove legacy chains from job orm
- Remove LoadEnvConfigVarsOCR for ocr spec, because it gets called in delegate anyway
- Remove legacy chains as it is no longer used in orm
* Remove unused legacyChains from job_orm_test.go
* Revert "Remove unused legacyChains from job_orm_test.go"
This reverts commit dce7e3f5dc67fb924a204ecb5f1491a970786286.
* Revert "Remove legacy chains from job orm"
This reverts commit a41a48f74b11235a4e9519e691eab31e6bb6088d.
* Rename legacy env var loading funcs in job orm and cleanup unused stuff
* Remove unused legacy tramsnimtter address env
* minor func rename
* Update func signature in calls to LoadDefaultVRFPollPeriod
* Remove EncryptedOCRKeyBundleIDEnv and ConfirmationsEnv
---
core/services/directrequest/delegate.go | 2 +-
core/services/job/models.go | 74 +++++++--------
core/services/job/orm.go | 62 ++++---------
core/services/job/orm_test.go | 32 +++----
core/services/ocr/config.go | 2 +-
core/services/ocr/delegate.go | 2 +-
core/services/vrf/v1/listener_v1.go | 2 +-
core/services/vrf/v2/listener_v2.go | 2 +-
core/web/presenters/job.go | 114 ++++++++++--------------
core/web/resolver/spec.go | 58 ------------
core/web/resolver/spec_test.go | 72 +++++----------
core/web/schema/type/spec.graphql | 10 ---
12 files changed, 140 insertions(+), 292 deletions(-)
diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go
index 174dca062a..920f94b4d6 100644
--- a/core/services/directrequest/delegate.go
+++ b/core/services/directrequest/delegate.go
@@ -77,7 +77,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
if err != nil {
return nil, err
}
- concreteSpec := job.LoadEnvConfigVarsDR(chain.Config().EVM(), *jb.DirectRequestSpec)
+ concreteSpec := job.SetDRMinIncomingConfirmations(chain.Config().EVM().MinIncomingConfirmations(), *jb.DirectRequestSpec)
oracle, err := operator_wrapper.NewOperator(concreteSpec.ContractAddress.Address(), chain.Client())
if err != nil {
diff --git a/core/services/job/models.go b/core/services/job/models.go
index a3dfce5999..a474040dd4 100644
--- a/core/services/job/models.go
+++ b/core/services/job/models.go
@@ -15,6 +15,7 @@ import (
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
@@ -233,35 +234,25 @@ func (pr *PipelineRun) SetID(value string) error {
// OCROracleSpec defines the job spec for OCR jobs.
type OCROracleSpec struct {
- ID int32 `toml:"-"`
- ContractAddress ethkey.EIP55Address `toml:"contractAddress"`
- P2PBootstrapPeers pq.StringArray `toml:"p2pBootstrapPeers" db:"p2p_bootstrap_peers"`
- P2PV2Bootstrappers pq.StringArray `toml:"p2pv2Bootstrappers" db:"p2pv2_bootstrappers"`
- IsBootstrapPeer bool `toml:"isBootstrapPeer"`
- EncryptedOCRKeyBundleID *models.Sha256Hash `toml:"keyBundleID"`
- EncryptedOCRKeyBundleIDEnv bool
- TransmitterAddress *ethkey.EIP55Address `toml:"transmitterAddress"`
- TransmitterAddressEnv bool
- ObservationTimeout models.Interval `toml:"observationTimeout"`
- ObservationTimeoutEnv bool
- BlockchainTimeout models.Interval `toml:"blockchainTimeout"`
- BlockchainTimeoutEnv bool
- ContractConfigTrackerSubscribeInterval models.Interval `toml:"contractConfigTrackerSubscribeInterval"`
- ContractConfigTrackerSubscribeIntervalEnv bool
- ContractConfigTrackerPollInterval models.Interval `toml:"contractConfigTrackerPollInterval"`
- ContractConfigTrackerPollIntervalEnv bool
- ContractConfigConfirmations uint16 `toml:"contractConfigConfirmations"`
- ContractConfigConfirmationsEnv bool
- EVMChainID *utils.Big `toml:"evmChainID" db:"evm_chain_id"`
- DatabaseTimeout *models.Interval `toml:"databaseTimeout"`
- DatabaseTimeoutEnv bool
- ObservationGracePeriod *models.Interval `toml:"observationGracePeriod"`
- ObservationGracePeriodEnv bool
- ContractTransmitterTransmitTimeout *models.Interval `toml:"contractTransmitterTransmitTimeout"`
- ContractTransmitterTransmitTimeoutEnv bool
- CaptureEATelemetry bool `toml:"captureEATelemetry"`
- CreatedAt time.Time `toml:"-"`
- UpdatedAt time.Time `toml:"-"`
+ ID int32 `toml:"-"`
+ ContractAddress ethkey.EIP55Address `toml:"contractAddress"`
+ P2PBootstrapPeers pq.StringArray `toml:"p2pBootstrapPeers" db:"p2p_bootstrap_peers"`
+ P2PV2Bootstrappers pq.StringArray `toml:"p2pv2Bootstrappers" db:"p2pv2_bootstrappers"`
+ IsBootstrapPeer bool `toml:"isBootstrapPeer"`
+ EncryptedOCRKeyBundleID *models.Sha256Hash `toml:"keyBundleID"`
+ TransmitterAddress *ethkey.EIP55Address `toml:"transmitterAddress"`
+ ObservationTimeout models.Interval `toml:"observationTimeout"`
+ BlockchainTimeout models.Interval `toml:"blockchainTimeout"`
+ ContractConfigTrackerSubscribeInterval models.Interval `toml:"contractConfigTrackerSubscribeInterval"`
+ ContractConfigTrackerPollInterval models.Interval `toml:"contractConfigTrackerPollInterval"`
+ ContractConfigConfirmations uint16 `toml:"contractConfigConfirmations"`
+ EVMChainID *utils.Big `toml:"evmChainID" db:"evm_chain_id"`
+ DatabaseTimeout *models.Interval `toml:"databaseTimeout"`
+ ObservationGracePeriod *models.Interval `toml:"observationGracePeriod"`
+ ContractTransmitterTransmitTimeout *models.Interval `toml:"contractTransmitterTransmitTimeout"`
+ CaptureEATelemetry bool `toml:"captureEATelemetry"`
+ CreatedAt time.Time `toml:"-"`
+ UpdatedAt time.Time `toml:"-"`
}
// GetID is a getter function that returns the ID of the spec.
@@ -438,15 +429,14 @@ func (w *WebhookSpec) SetID(value string) error {
}
type DirectRequestSpec struct {
- ID int32 `toml:"-"`
- ContractAddress ethkey.EIP55Address `toml:"contractAddress"`
- MinIncomingConfirmations clnull.Uint32 `toml:"minIncomingConfirmations"`
- MinIncomingConfirmationsEnv bool `toml:"minIncomingConfirmationsEnv"`
- Requesters models.AddressCollection `toml:"requesters"`
- MinContractPayment *assets.Link `toml:"minContractPaymentLinkJuels"`
- EVMChainID *utils.Big `toml:"evmChainID"`
- CreatedAt time.Time `toml:"-"`
- UpdatedAt time.Time `toml:"-"`
+ ID int32 `toml:"-"`
+ ContractAddress ethkey.EIP55Address `toml:"contractAddress"`
+ MinIncomingConfirmations clnull.Uint32 `toml:"minIncomingConfirmations"`
+ Requesters models.AddressCollection `toml:"requesters"`
+ MinContractPayment *assets.Link `toml:"minContractPaymentLinkJuels"`
+ EVMChainID *utils.Big `toml:"evmChainID"`
+ CreatedAt time.Time `toml:"-"`
+ UpdatedAt time.Time `toml:"-"`
}
type CronSpec struct {
@@ -522,13 +512,11 @@ type VRFSpec struct {
CoordinatorAddress ethkey.EIP55Address `toml:"coordinatorAddress"`
PublicKey secp256k1.PublicKey `toml:"publicKey"`
MinIncomingConfirmations uint32 `toml:"minIncomingConfirmations"`
- ConfirmationsEnv bool `toml:"-"`
EVMChainID *utils.Big `toml:"evmChainID"`
FromAddresses []ethkey.EIP55Address `toml:"fromAddresses"`
- PollPeriod time.Duration `toml:"pollPeriod"` // For v2 jobs
- PollPeriodEnv bool
- RequestedConfsDelay int64 `toml:"requestedConfsDelay"` // For v2 jobs. Optional, defaults to 0 if not provided.
- RequestTimeout time.Duration `toml:"requestTimeout"` // Optional, defaults to 24hr if not provided.
+ PollPeriod time.Duration `toml:"pollPeriod"` // For v2 jobs
+ RequestedConfsDelay int64 `toml:"requestedConfsDelay"` // For v2 jobs. Optional, defaults to 0 if not provided.
+ RequestTimeout time.Duration `toml:"requestTimeout"` // Optional, defaults to 24hr if not provided.
// GasLanePrice specifies the gas lane price for this VRF job.
// If the specified keys in FromAddresses do not have the provided gas price the job
diff --git a/core/services/job/orm.go b/core/services/job/orm.go
index cbdd7ebfae..372b2fe74a 100644
--- a/core/services/job/orm.go
+++ b/core/services/job/orm.go
@@ -705,61 +705,41 @@ func (o *orm) FindJobs(offset, limit int) (jobs []Job, count int, err error) {
return err
}
for i := range jobs {
- err = multierr.Combine(err, o.LoadEnvConfigVars(&jobs[i]))
+ err = multierr.Combine(err, o.LoadConfigVars(&jobs[i]))
}
return nil
})
return jobs, int(count), err
}
-func (o *orm) LoadEnvConfigVars(jb *Job) error {
+func (o *orm) LoadConfigVars(jb *Job) error {
if jb.OCROracleSpec != nil {
ch, err := o.legacyChains.Get(jb.OCROracleSpec.EVMChainID.String())
if err != nil {
return err
}
- newSpec, err := LoadEnvConfigVarsOCR(ch.Config().EVM().OCR(), ch.Config().OCR(), *jb.OCROracleSpec)
+ newSpec, err := LoadConfigVarsOCR(ch.Config().EVM().OCR(), ch.Config().OCR(), *jb.OCROracleSpec)
if err != nil {
return err
}
jb.OCROracleSpec = newSpec
- } else if jb.VRFSpec != nil {
- ch, err := o.legacyChains.Get(jb.VRFSpec.EVMChainID.String())
- if err != nil {
- return err
- }
- jb.VRFSpec = LoadEnvConfigVarsVRF(ch.Config().EVM(), *jb.VRFSpec)
- } else if jb.DirectRequestSpec != nil {
- ch, err := o.legacyChains.Get(jb.DirectRequestSpec.EVMChainID.String())
- if err != nil {
- return err
- }
- jb.DirectRequestSpec = LoadEnvConfigVarsDR(ch.Config().EVM(), *jb.DirectRequestSpec)
}
return nil
}
-type DRSpecConfig interface {
- MinIncomingConfirmations() uint32
-}
-
-func LoadEnvConfigVarsVRF(cfg DRSpecConfig, vrfs VRFSpec) *VRFSpec {
+func LoadDefaultVRFPollPeriod(vrfs VRFSpec) *VRFSpec {
if vrfs.PollPeriod == 0 {
- vrfs.PollPeriodEnv = true
vrfs.PollPeriod = 5 * time.Second
}
return &vrfs
}
-func LoadEnvConfigVarsDR(cfg DRSpecConfig, drs DirectRequestSpec) *DirectRequestSpec {
- // Take the largest of the global vs specific.
- minIncomingConfirmations := cfg.MinIncomingConfirmations()
- if !drs.MinIncomingConfirmations.Valid || drs.MinIncomingConfirmations.Uint32 < minIncomingConfirmations {
- drs.MinIncomingConfirmationsEnv = true
- drs.MinIncomingConfirmations = null.Uint32From(minIncomingConfirmations)
+// SetDRMinIncomingConfirmations takes the largest of the global vs specific.
+func SetDRMinIncomingConfirmations(defaultMinIncomingConfirmations uint32, drs DirectRequestSpec) *DirectRequestSpec {
+ if !drs.MinIncomingConfirmations.Valid || drs.MinIncomingConfirmations.Uint32 < defaultMinIncomingConfirmations {
+ drs.MinIncomingConfirmations = null.Uint32From(defaultMinIncomingConfirmations)
}
-
return &drs
}
@@ -773,38 +753,30 @@ type OCRConfig interface {
TransmitterAddress() (ethkey.EIP55Address, error)
}
-// LoadEnvConfigVarsLocalOCR loads local OCR env vars into the OCROracleSpec.
-func LoadEnvConfigVarsLocalOCR(evmOcrCfg evmconfig.OCR, os OCROracleSpec, ocrCfg OCRConfig) *OCROracleSpec {
+// LoadConfigVarsLocalOCR loads local OCR vars into the OCROracleSpec.
+func LoadConfigVarsLocalOCR(evmOcrCfg evmconfig.OCR, os OCROracleSpec, ocrCfg OCRConfig) *OCROracleSpec {
if os.ObservationTimeout == 0 {
- os.ObservationTimeoutEnv = true
os.ObservationTimeout = models.Interval(ocrCfg.ObservationTimeout())
}
if os.BlockchainTimeout == 0 {
- os.BlockchainTimeoutEnv = true
os.BlockchainTimeout = models.Interval(ocrCfg.BlockchainTimeout())
}
if os.ContractConfigTrackerSubscribeInterval == 0 {
- os.ContractConfigTrackerSubscribeIntervalEnv = true
os.ContractConfigTrackerSubscribeInterval = models.Interval(ocrCfg.ContractSubscribeInterval())
}
if os.ContractConfigTrackerPollInterval == 0 {
- os.ContractConfigTrackerPollIntervalEnv = true
os.ContractConfigTrackerPollInterval = models.Interval(ocrCfg.ContractPollInterval())
}
if os.ContractConfigConfirmations == 0 {
- os.ContractConfigConfirmationsEnv = true
os.ContractConfigConfirmations = evmOcrCfg.ContractConfirmations()
}
if os.DatabaseTimeout == nil {
- os.DatabaseTimeoutEnv = true
os.DatabaseTimeout = models.NewInterval(evmOcrCfg.DatabaseTimeout())
}
if os.ObservationGracePeriod == nil {
- os.ObservationGracePeriodEnv = true
os.ObservationGracePeriod = models.NewInterval(evmOcrCfg.ObservationGracePeriod())
}
if os.ContractTransmitterTransmitTimeout == nil {
- os.ContractTransmitterTransmitTimeoutEnv = true
os.ContractTransmitterTransmitTimeout = models.NewInterval(evmOcrCfg.ContractTransmitterTransmitTimeout())
}
os.CaptureEATelemetry = ocrCfg.CaptureEATelemetry()
@@ -812,15 +784,14 @@ func LoadEnvConfigVarsLocalOCR(evmOcrCfg evmconfig.OCR, os OCROracleSpec, ocrCfg
return &os
}
-// LoadEnvConfigVarsOCR loads OCR env vars into the OCROracleSpec.
-func LoadEnvConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracleSpec) (*OCROracleSpec, error) {
+// LoadConfigVarsOCR loads OCR config vars into the OCROracleSpec.
+func LoadConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracleSpec) (*OCROracleSpec, error) {
if os.TransmitterAddress == nil {
ta, err := ocrCfg.TransmitterAddress()
if !errors.Is(errors.Cause(err), config.ErrEnvUnset) {
if err != nil {
return nil, err
}
- os.TransmitterAddressEnv = true
os.TransmitterAddress = &ta
}
}
@@ -834,11 +805,10 @@ func LoadEnvConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracl
if err != nil {
return nil, err
}
- os.EncryptedOCRKeyBundleIDEnv = true
os.EncryptedOCRKeyBundleID = &encryptedOCRKeyBundleID
}
- return LoadEnvConfigVarsLocalOCR(evmOcrCfg, os, ocrCfg), nil
+ return LoadConfigVarsLocalOCR(evmOcrCfg, os, ocrCfg), nil
}
func (o *orm) FindJobTx(id int32) (Job, error) {
@@ -872,7 +842,7 @@ func (o *orm) FindJobWithoutSpecErrors(id int32) (jb Job, err error) {
return jb, errors.Wrap(err, "FindJobWithoutSpecErrors failed")
}
- return jb, o.LoadEnvConfigVars(&jb)
+ return jb, o.LoadConfigVars(&jb)
}
// FindSpecErrorsByJobIDs returns all jobs spec errors by jobs IDs
@@ -961,7 +931,7 @@ func (o *orm) findJob(jb *Job, col string, arg interface{}, qopts ...pg.QOpt) er
if err != nil {
return errors.Wrap(err, "findJob failed")
}
- return o.LoadEnvConfigVars(jb)
+ return o.LoadConfigVars(jb)
}
func (o *orm) FindJobIDsWithBridge(name string) (jids []int32, err error) {
@@ -1205,7 +1175,7 @@ func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) {
return err
}
for i := range jbs {
- err = o.LoadEnvConfigVars(&jbs[i])
+ err = o.LoadConfigVars(&jbs[i])
//We must return the jobs even if the chainID is disabled
if err != nil && !errors.Is(err, chains.ErrNoSuchChainID) {
return err
diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go
index a6986d7fb3..cd437147b4 100644
--- a/core/services/job/orm_test.go
+++ b/core/services/job/orm_test.go
@@ -19,6 +19,7 @@ import (
"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, legacyChains evm.LegacyChainContainer, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, cfg pg.QConfig) job.ORM {
@@ -27,26 +28,28 @@ func NewTestORM(t *testing.T, db *sqlx.DB, legacyChains evm.LegacyChainContainer
return o
}
-func TestLoadEnvConfigVarsLocalOCR(t *testing.T) {
+func TestLoadConfigVarsLocalOCR(t *testing.T) {
t.Parallel()
config := configtest.NewTestGeneralConfig(t)
chainConfig := evmtest.NewChainScopedConfig(t, config)
jobSpec := &job.OCROracleSpec{}
- jobSpec = job.LoadEnvConfigVarsLocalOCR(chainConfig.EVM().OCR(), *jobSpec, chainConfig.OCR())
+ jobSpec = job.LoadConfigVarsLocalOCR(chainConfig.EVM().OCR(), *jobSpec, chainConfig.OCR())
- require.True(t, jobSpec.ObservationTimeoutEnv)
- require.True(t, jobSpec.BlockchainTimeoutEnv)
- require.True(t, jobSpec.ContractConfigTrackerSubscribeIntervalEnv)
- require.True(t, jobSpec.ContractConfigTrackerPollIntervalEnv)
- require.True(t, jobSpec.ContractConfigConfirmationsEnv)
- require.True(t, jobSpec.DatabaseTimeoutEnv)
- require.True(t, jobSpec.ObservationGracePeriodEnv)
- require.True(t, jobSpec.ContractTransmitterTransmitTimeoutEnv)
+ require.Equal(t, models.Interval(chainConfig.OCR().ObservationTimeout()), jobSpec.ObservationTimeout)
+ require.Equal(t, models.Interval(chainConfig.OCR().BlockchainTimeout()), jobSpec.BlockchainTimeout)
+ require.Equal(t, models.Interval(chainConfig.OCR().ContractSubscribeInterval()), jobSpec.ContractConfigTrackerSubscribeInterval)
+ require.Equal(t, models.Interval(chainConfig.OCR().ContractPollInterval()), jobSpec.ContractConfigTrackerPollInterval)
+ require.Equal(t, chainConfig.OCR().CaptureEATelemetry(), jobSpec.CaptureEATelemetry)
+
+ require.Equal(t, chainConfig.EVM().OCR().ContractConfirmations(), jobSpec.ContractConfigConfirmations)
+ require.Equal(t, models.Interval(chainConfig.EVM().OCR().DatabaseTimeout()), *jobSpec.DatabaseTimeout)
+ require.Equal(t, models.Interval(chainConfig.EVM().OCR().ObservationGracePeriod()), *jobSpec.ObservationGracePeriod)
+ require.Equal(t, models.Interval(chainConfig.EVM().OCR().ContractTransmitterTransmitTimeout()), *jobSpec.ContractTransmitterTransmitTimeout)
}
-func TestLoadEnvConfigVarsDR(t *testing.T) {
+func TestSetDRMinIncomingConfirmations(t *testing.T) {
t.Parallel()
config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
@@ -59,15 +62,14 @@ func TestLoadEnvConfigVarsDR(t *testing.T) {
MinIncomingConfirmations: clnull.Uint32From(10),
}
- drs10 := job.LoadEnvConfigVarsDR(chainConfig.EVM(), jobSpec10)
- assert.True(t, drs10.MinIncomingConfirmationsEnv)
+ drs10 := job.SetDRMinIncomingConfirmations(chainConfig.EVM().MinIncomingConfirmations(), jobSpec10)
+ assert.Equal(t, uint32(100), drs10.MinIncomingConfirmations.Uint32)
jobSpec200 := job.DirectRequestSpec{
MinIncomingConfirmations: clnull.Uint32From(200),
}
- drs200 := job.LoadEnvConfigVarsDR(chainConfig.EVM(), jobSpec200)
- assert.False(t, drs200.MinIncomingConfirmationsEnv)
+ drs200 := job.SetDRMinIncomingConfirmations(chainConfig.EVM().MinIncomingConfirmations(), jobSpec200)
assert.True(t, drs200.MinIncomingConfirmations.Valid)
assert.Equal(t, uint32(200), drs200.MinIncomingConfirmations.Uint32)
}
diff --git a/core/services/ocr/config.go b/core/services/ocr/config.go
index e1bc997f26..53ec9f9cea 100644
--- a/core/services/ocr/config.go
+++ b/core/services/ocr/config.go
@@ -14,7 +14,7 @@ type Config interface {
}
func toLocalConfig(cfg ValidationConfig, evmOcrConfig evmconfig.OCR, insecureCfg insecureConfig, spec job.OCROracleSpec, ocrConfig job.OCRConfig) ocrtypes.LocalConfig {
- concreteSpec := job.LoadEnvConfigVarsLocalOCR(evmOcrConfig, spec, ocrConfig)
+ concreteSpec := job.LoadConfigVarsLocalOCR(evmOcrConfig, spec, ocrConfig)
lc := ocrtypes.LocalConfig{
BlockchainTimeout: concreteSpec.BlockchainTimeout.Duration(),
ContractConfigConfirmations: concreteSpec.ContractConfigConfirmations,
diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go
index dee349a9a0..b761690485 100644
--- a/core/services/ocr/delegate.go
+++ b/core/services/ocr/delegate.go
@@ -95,7 +95,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) (services []job.ServiceCtx, err e
if err != nil {
return nil, err
}
- concreteSpec, err := job.LoadEnvConfigVarsOCR(chain.Config().EVM().OCR(), chain.Config().OCR(), *jb.OCROracleSpec)
+ concreteSpec, err := job.LoadConfigVarsOCR(chain.Config().EVM().OCR(), chain.Config().OCR(), *jb.OCROracleSpec)
if err != nil {
return nil, err
}
diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go
index 613c0d124d..92e697f229 100644
--- a/core/services/vrf/v1/listener_v1.go
+++ b/core/services/vrf/v1/listener_v1.go
@@ -112,7 +112,7 @@ func (lsn *Listener) getLatestHead() uint64 {
// Start complies with job.Service
func (lsn *Listener) Start(context.Context) error {
return lsn.StartOnce("VRFListener", func() error {
- spec := job.LoadEnvConfigVarsVRF(lsn.Cfg, *lsn.Job.VRFSpec)
+ spec := job.LoadDefaultVRFPollPeriod(*lsn.Job.VRFSpec)
unsubscribeLogs := lsn.LogBroadcaster.Register(lsn, log.ListenerOpts{
Contract: lsn.Coordinator.Address(),
diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go
index 7560baad3a..8bac485d65 100644
--- a/core/services/vrf/v2/listener_v2.go
+++ b/core/services/vrf/v2/listener_v2.go
@@ -271,7 +271,7 @@ func (lsn *listenerV2) Start(ctx context.Context) error {
"proofVerificationGas", GasProofVerification)
}
- spec := job.LoadEnvConfigVarsVRF(lsn.cfg, *lsn.job.VRFSpec)
+ spec := job.LoadDefaultVRFPollPeriod(*lsn.job.VRFSpec)
unsubscribeLogs := lsn.logBroadcaster.Register(lsn, log.ListenerOpts{
Contract: lsn.coordinator.Address(),
diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go
index 2aa9773088..06b9950755 100644
--- a/core/web/presenters/job.go
+++ b/core/web/presenters/job.go
@@ -41,26 +41,24 @@ const (
// DirectRequestSpec defines the spec details of a DirectRequest Job
type DirectRequestSpec struct {
- ContractAddress ethkey.EIP55Address `json:"contractAddress"`
- MinIncomingConfirmations clnull.Uint32 `json:"minIncomingConfirmations"`
- MinIncomingConfirmationsEnv bool `json:"minIncomingConfirmationsEnv,omitempty"`
- MinContractPayment *assets.Link `json:"minContractPaymentLinkJuels"`
- Requesters models.AddressCollection `json:"requesters"`
- Initiator string `json:"initiator"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- EVMChainID *utils.Big `json:"evmChainID"`
+ ContractAddress ethkey.EIP55Address `json:"contractAddress"`
+ MinIncomingConfirmations clnull.Uint32 `json:"minIncomingConfirmations"`
+ MinContractPayment *assets.Link `json:"minContractPaymentLinkJuels"`
+ Requesters models.AddressCollection `json:"requesters"`
+ Initiator string `json:"initiator"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ EVMChainID *utils.Big `json:"evmChainID"`
}
// NewDirectRequestSpec initializes a new DirectRequestSpec from a
// job.DirectRequestSpec
func NewDirectRequestSpec(spec *job.DirectRequestSpec) *DirectRequestSpec {
return &DirectRequestSpec{
- ContractAddress: spec.ContractAddress,
- MinIncomingConfirmations: spec.MinIncomingConfirmations,
- MinIncomingConfirmationsEnv: spec.MinIncomingConfirmationsEnv,
- MinContractPayment: spec.MinContractPayment,
- Requesters: spec.Requesters,
+ ContractAddress: spec.ContractAddress,
+ MinIncomingConfirmations: spec.MinIncomingConfirmations,
+ MinContractPayment: spec.MinContractPayment,
+ Requesters: spec.Requesters,
// This is hardcoded to runlog. When we support other initiators, we need
// to change this
Initiator: "runlog",
@@ -120,64 +118,48 @@ func NewFluxMonitorSpec(spec *job.FluxMonitorSpec) *FluxMonitorSpec {
// OffChainReportingSpec defines the spec details of a OffChainReporting Job
type OffChainReportingSpec struct {
- ContractAddress ethkey.EIP55Address `json:"contractAddress"`
- P2PBootstrapPeers pq.StringArray `json:"p2pBootstrapPeers"`
- P2PV2Bootstrappers pq.StringArray `json:"p2pv2Bootstrappers"`
- IsBootstrapPeer bool `json:"isBootstrapPeer"`
- EncryptedOCRKeyBundleID *models.Sha256Hash `json:"keyBundleID"`
- TransmitterAddress *ethkey.EIP55Address `json:"transmitterAddress"`
- ObservationTimeout models.Interval `json:"observationTimeout"`
- ObservationTimeoutEnv bool `json:"observationTimeoutEnv,omitempty"`
- BlockchainTimeout models.Interval `json:"blockchainTimeout"`
- BlockchainTimeoutEnv bool `json:"blockchainTimeoutEnv,omitempty"`
- ContractConfigTrackerSubscribeInterval models.Interval `json:"contractConfigTrackerSubscribeInterval"`
- ContractConfigTrackerSubscribeIntervalEnv bool `json:"contractConfigTrackerSubscribeIntervalEnv,omitempty"`
- ContractConfigTrackerPollInterval models.Interval `json:"contractConfigTrackerPollInterval"`
- ContractConfigTrackerPollIntervalEnv bool `json:"contractConfigTrackerPollIntervalEnv,omitempty"`
- ContractConfigConfirmations uint16 `json:"contractConfigConfirmations"`
- ContractConfigConfirmationsEnv bool `json:"contractConfigConfirmationsEnv,omitempty"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- EVMChainID *utils.Big `json:"evmChainID"`
- DatabaseTimeout *models.Interval `json:"databaseTimeout"`
- DatabaseTimeoutEnv bool `json:"databaseTimeoutEnv,omitempty"`
- ObservationGracePeriod *models.Interval `json:"observationGracePeriod"`
- ObservationGracePeriodEnv bool `json:"observationGracePeriodEnv,omitempty"`
- ContractTransmitterTransmitTimeout *models.Interval `json:"contractTransmitterTransmitTimeout"`
- ContractTransmitterTransmitTimeoutEnv bool `json:"contractTransmitterTransmitTimeoutEnv,omitempty"`
- CollectTelemetry bool `json:"collectTelemetry,omitempty"`
+ ContractAddress ethkey.EIP55Address `json:"contractAddress"`
+ P2PBootstrapPeers pq.StringArray `json:"p2pBootstrapPeers"`
+ P2PV2Bootstrappers pq.StringArray `json:"p2pv2Bootstrappers"`
+ IsBootstrapPeer bool `json:"isBootstrapPeer"`
+ EncryptedOCRKeyBundleID *models.Sha256Hash `json:"keyBundleID"`
+ TransmitterAddress *ethkey.EIP55Address `json:"transmitterAddress"`
+ ObservationTimeout models.Interval `json:"observationTimeout"`
+ BlockchainTimeout models.Interval `json:"blockchainTimeout"`
+ ContractConfigTrackerSubscribeInterval models.Interval `json:"contractConfigTrackerSubscribeInterval"`
+ ContractConfigTrackerPollInterval models.Interval `json:"contractConfigTrackerPollInterval"`
+ ContractConfigConfirmations uint16 `json:"contractConfigConfirmations"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ EVMChainID *utils.Big `json:"evmChainID"`
+ DatabaseTimeout *models.Interval `json:"databaseTimeout"`
+ ObservationGracePeriod *models.Interval `json:"observationGracePeriod"`
+ ContractTransmitterTransmitTimeout *models.Interval `json:"contractTransmitterTransmitTimeout"`
+ CollectTelemetry bool `json:"collectTelemetry,omitempty"`
}
// NewOffChainReportingSpec initializes a new OffChainReportingSpec from a
// job.OCROracleSpec
func NewOffChainReportingSpec(spec *job.OCROracleSpec) *OffChainReportingSpec {
return &OffChainReportingSpec{
- ContractAddress: spec.ContractAddress,
- P2PBootstrapPeers: spec.P2PBootstrapPeers,
- P2PV2Bootstrappers: spec.P2PV2Bootstrappers,
- IsBootstrapPeer: spec.IsBootstrapPeer,
- EncryptedOCRKeyBundleID: spec.EncryptedOCRKeyBundleID,
- TransmitterAddress: spec.TransmitterAddress,
- ObservationTimeout: spec.ObservationTimeout,
- ObservationTimeoutEnv: spec.ObservationTimeoutEnv,
- BlockchainTimeout: spec.BlockchainTimeout,
- BlockchainTimeoutEnv: spec.BlockchainTimeoutEnv,
- ContractConfigTrackerSubscribeInterval: spec.ContractConfigTrackerSubscribeInterval,
- ContractConfigTrackerSubscribeIntervalEnv: spec.ContractConfigTrackerSubscribeIntervalEnv,
- ContractConfigTrackerPollInterval: spec.ContractConfigTrackerPollInterval,
- ContractConfigTrackerPollIntervalEnv: spec.ContractConfigTrackerPollIntervalEnv,
- ContractConfigConfirmations: spec.ContractConfigConfirmations,
- ContractConfigConfirmationsEnv: spec.ContractConfigConfirmationsEnv,
- CreatedAt: spec.CreatedAt,
- UpdatedAt: spec.UpdatedAt,
- EVMChainID: spec.EVMChainID,
- DatabaseTimeout: spec.DatabaseTimeout,
- DatabaseTimeoutEnv: spec.DatabaseTimeoutEnv,
- ObservationGracePeriod: spec.ObservationGracePeriod,
- ObservationGracePeriodEnv: spec.ObservationGracePeriodEnv,
- ContractTransmitterTransmitTimeout: spec.ContractTransmitterTransmitTimeout,
- ContractTransmitterTransmitTimeoutEnv: spec.ContractTransmitterTransmitTimeoutEnv,
- CollectTelemetry: spec.CaptureEATelemetry,
+ ContractAddress: spec.ContractAddress,
+ P2PBootstrapPeers: spec.P2PBootstrapPeers,
+ P2PV2Bootstrappers: spec.P2PV2Bootstrappers,
+ IsBootstrapPeer: spec.IsBootstrapPeer,
+ EncryptedOCRKeyBundleID: spec.EncryptedOCRKeyBundleID,
+ TransmitterAddress: spec.TransmitterAddress,
+ ObservationTimeout: spec.ObservationTimeout,
+ BlockchainTimeout: spec.BlockchainTimeout,
+ ContractConfigTrackerSubscribeInterval: spec.ContractConfigTrackerSubscribeInterval,
+ ContractConfigTrackerPollInterval: spec.ContractConfigTrackerPollInterval,
+ ContractConfigConfirmations: spec.ContractConfigConfirmations,
+ CreatedAt: spec.CreatedAt,
+ UpdatedAt: spec.UpdatedAt,
+ EVMChainID: spec.EVMChainID,
+ DatabaseTimeout: spec.DatabaseTimeout,
+ ObservationGracePeriod: spec.ObservationGracePeriod,
+ ContractTransmitterTransmitTimeout: spec.ContractTransmitterTransmitTimeout,
+ CollectTelemetry: spec.CaptureEATelemetry,
}
}
diff --git a/core/web/resolver/spec.go b/core/web/resolver/spec.go
index 48040d118a..c9ee519922 100644
--- a/core/web/resolver/spec.go
+++ b/core/web/resolver/spec.go
@@ -164,11 +164,6 @@ func (r *DirectRequestSpecResolver) MinIncomingConfirmations() int32 {
return 0
}
-// EVMChainID resolves the spec's evm chain id.
-func (r *DirectRequestSpecResolver) MinIncomingConfirmationsEnv() bool {
- return r.spec.MinIncomingConfirmationsEnv
-}
-
// MinContractPaymentLinkJuels resolves the spec's min contract payment link.
func (r *DirectRequestSpecResolver) MinContractPaymentLinkJuels() string {
return r.spec.MinContractPayment.String()
@@ -328,12 +323,6 @@ func (r *OCRSpecResolver) BlockchainTimeout() *string {
return &timeout
}
-// BlockchainTimeoutEnv resolves whether the spec's blockchain timeout comes
-// from an env var.
-func (r *OCRSpecResolver) BlockchainTimeoutEnv() bool {
- return r.spec.BlockchainTimeoutEnv
-}
-
// ContractAddress resolves the spec's contract address.
func (r *OCRSpecResolver) ContractAddress() string {
return r.spec.ContractAddress.String()
@@ -350,12 +339,6 @@ func (r *OCRSpecResolver) ContractConfigConfirmations() *int32 {
return &confirmations
}
-// ContractConfigConfirmationsEnv resolves whether spec's confirmations
-// config comes from an env var.
-func (r *OCRSpecResolver) ContractConfigConfirmationsEnv() bool {
- return r.spec.ContractConfigConfirmationsEnv
-}
-
// ContractConfigTrackerPollInterval resolves the spec's contract tracker poll
// interval config.
func (r *OCRSpecResolver) ContractConfigTrackerPollInterval() *string {
@@ -368,12 +351,6 @@ func (r *OCRSpecResolver) ContractConfigTrackerPollInterval() *string {
return &interval
}
-// ContractConfigTrackerPollIntervalEnv resolves the whether spec's tracker poll
-// config comes from an env var.
-func (r *OCRSpecResolver) ContractConfigTrackerPollIntervalEnv() bool {
- return r.spec.ContractConfigTrackerPollIntervalEnv
-}
-
// ContractConfigTrackerSubscribeInterval resolves the spec's tracker subscribe
// interval config.
func (r *OCRSpecResolver) ContractConfigTrackerSubscribeInterval() *string {
@@ -386,12 +363,6 @@ func (r *OCRSpecResolver) ContractConfigTrackerSubscribeInterval() *string {
return &interval
}
-// ContractConfigTrackerSubscribeIntervalEnv resolves whether spec's tracker
-// subscribe interval config comes from an env var.
-func (r *OCRSpecResolver) ContractConfigTrackerSubscribeIntervalEnv() bool {
- return r.spec.ContractConfigTrackerSubscribeIntervalEnv
-}
-
// CreatedAt resolves the spec's created at timestamp.
func (r *OCRSpecResolver) CreatedAt() graphql.Time {
return graphql.Time{Time: r.spec.CreatedAt}
@@ -413,34 +384,16 @@ func (r *OCRSpecResolver) DatabaseTimeout() string {
return r.spec.DatabaseTimeout.Duration().String()
}
-// DatabaseTimeoutEnv resolves the whether spec's database timeout
-// config comes from an env var.
-func (r *OCRSpecResolver) DatabaseTimeoutEnv() bool {
- return r.spec.DatabaseTimeoutEnv
-}
-
// ObservationGracePeriod resolves the spec's observation grace period.
func (r *OCRSpecResolver) ObservationGracePeriod() string {
return r.spec.ObservationGracePeriod.Duration().String()
}
-// ObservationGracePeriodEnv resolves the whether spec's observation grace period
-// config comes from an env var.
-func (r *OCRSpecResolver) ObservationGracePeriodEnv() bool {
- return r.spec.ObservationGracePeriodEnv
-}
-
// ContractTransmitterTransmitTimeout resolves the spec's contract transmitter transmit timeout.
func (r *OCRSpecResolver) ContractTransmitterTransmitTimeout() string {
return r.spec.ContractTransmitterTransmitTimeout.Duration().String()
}
-// ContractTransmitterTransmitTimeoutEnv resolves the whether spec's
-// contract transmitter transmit timeout config comes from an env var.
-func (r *OCRSpecResolver) ContractTransmitterTransmitTimeoutEnv() bool {
- return r.spec.ContractTransmitterTransmitTimeoutEnv
-}
-
// IsBootstrapPeer resolves whether spec is a bootstrap peer.
func (r *OCRSpecResolver) IsBootstrapPeer() bool {
return r.spec.IsBootstrapPeer
@@ -468,12 +421,6 @@ func (r *OCRSpecResolver) ObservationTimeout() *string {
return &timeout
}
-// ObservationTimeoutEnv resolves whether spec's observation timeout comes
-// from an env var.
-func (r *OCRSpecResolver) ObservationTimeoutEnv() bool {
- return r.spec.ObservationTimeoutEnv
-}
-
// P2PBootstrapPeers resolves the spec's p2p bootstrap peers
func (r *OCRSpecResolver) P2PBootstrapPeers() *[]string {
if len(r.spec.P2PBootstrapPeers) == 0 {
@@ -631,11 +578,6 @@ func (r *VRFSpecResolver) MinIncomingConfirmations() int32 {
return int32(r.spec.MinIncomingConfirmations)
}
-// MinIncomingConfirmations resolves the spec's min incoming confirmations.
-func (r *VRFSpecResolver) MinIncomingConfirmationsEnv() bool {
- return r.spec.ConfirmationsEnv
-}
-
// CoordinatorAddress resolves the spec's coordinator address.
func (r *VRFSpecResolver) CoordinatorAddress() string {
return r.spec.CoordinatorAddress.String()
diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go
index 04bfffbe05..8e4095e171 100644
--- a/core/web/resolver/spec_test.go
+++ b/core/web/resolver/spec_test.go
@@ -10,6 +10,7 @@ import (
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -91,13 +92,12 @@ func TestResolver_DirectRequestSpec(t *testing.T) {
f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{
Type: job.DirectRequest,
DirectRequestSpec: &job.DirectRequestSpec{
- ContractAddress: contractAddress,
- CreatedAt: f.Timestamp(),
- EVMChainID: utils.NewBigI(42),
- MinIncomingConfirmations: clnull.NewUint32(1, true),
- MinIncomingConfirmationsEnv: true,
- MinContractPayment: assets.NewLinkFromJuels(1000),
- Requesters: models.AddressCollection{requesterAddress},
+ ContractAddress: contractAddress,
+ CreatedAt: f.Timestamp(),
+ EVMChainID: utils.NewBigI(42),
+ MinIncomingConfirmations: clnull.NewUint32(1, true),
+ MinContractPayment: assets.NewLinkFromJuels(1000),
+ Requesters: models.AddressCollection{requesterAddress},
},
}, nil)
},
@@ -112,7 +112,6 @@ func TestResolver_DirectRequestSpec(t *testing.T) {
createdAt
evmChainID
minIncomingConfirmations
- minIncomingConfirmationsEnv
minContractPaymentLinkJuels
requesters
}
@@ -130,7 +129,6 @@ func TestResolver_DirectRequestSpec(t *testing.T) {
"createdAt": "2021-01-01T00:00:00Z",
"evmChainID": "42",
"minIncomingConfirmations": 1,
- "minIncomingConfirmationsEnv": true,
"minContractPaymentLinkJuels": "1000",
"requesters": ["0x3cCad4715152693fE3BC4460591e3D3Fbd071b42"]
}
@@ -373,30 +371,22 @@ func TestResolver_OCRSpec(t *testing.T) {
f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{
Type: job.OffchainReporting,
OCROracleSpec: &job.OCROracleSpec{
- BlockchainTimeout: models.Interval(1 * time.Minute),
- BlockchainTimeoutEnv: false,
- ContractAddress: contractAddress,
- ContractConfigConfirmations: 1,
- ContractConfigConfirmationsEnv: true,
- ContractConfigTrackerPollInterval: models.Interval(1 * time.Minute),
- ContractConfigTrackerPollIntervalEnv: false,
- ContractConfigTrackerSubscribeInterval: models.Interval(2 * time.Minute),
- ContractConfigTrackerSubscribeIntervalEnv: true,
- DatabaseTimeout: models.NewInterval(3 * time.Second),
- DatabaseTimeoutEnv: true,
- ObservationGracePeriod: models.NewInterval(4 * time.Second),
- ObservationGracePeriodEnv: true,
- ContractTransmitterTransmitTimeout: models.NewInterval(555 * time.Millisecond),
- ContractTransmitterTransmitTimeoutEnv: true,
- CreatedAt: f.Timestamp(),
- EVMChainID: utils.NewBigI(42),
- IsBootstrapPeer: false,
- EncryptedOCRKeyBundleID: &keyBundleID,
- ObservationTimeout: models.Interval(2 * time.Minute),
- ObservationTimeoutEnv: false,
- P2PBootstrapPeers: pq.StringArray{"/dns4/test.com/tcp/2001/p2pkey"},
- P2PV2Bootstrappers: pq.StringArray{"12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw@localhost:5001"},
- TransmitterAddress: &transmitterAddress,
+ BlockchainTimeout: models.Interval(1 * time.Minute),
+ ContractAddress: contractAddress,
+ ContractConfigConfirmations: 1,
+ ContractConfigTrackerPollInterval: models.Interval(1 * time.Minute),
+ ContractConfigTrackerSubscribeInterval: models.Interval(2 * time.Minute),
+ DatabaseTimeout: models.NewInterval(3 * time.Second),
+ ObservationGracePeriod: models.NewInterval(4 * time.Second),
+ ContractTransmitterTransmitTimeout: models.NewInterval(555 * time.Millisecond),
+ CreatedAt: f.Timestamp(),
+ EVMChainID: utils.NewBigI(42),
+ IsBootstrapPeer: false,
+ EncryptedOCRKeyBundleID: &keyBundleID,
+ ObservationTimeout: models.Interval(2 * time.Minute),
+ P2PBootstrapPeers: pq.StringArray{"/dns4/test.com/tcp/2001/p2pkey"},
+ P2PV2Bootstrappers: pq.StringArray{"12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw@localhost:5001"},
+ TransmitterAddress: &transmitterAddress,
},
}, nil)
},
@@ -408,26 +398,18 @@ func TestResolver_OCRSpec(t *testing.T) {
__typename
... on OCRSpec {
blockchainTimeout
- blockchainTimeoutEnv
contractAddress
contractConfigConfirmations
- contractConfigConfirmationsEnv
contractConfigTrackerPollInterval
- contractConfigTrackerPollIntervalEnv
contractConfigTrackerSubscribeInterval
- contractConfigTrackerSubscribeIntervalEnv
databaseTimeout
- databaseTimeoutEnv
observationGracePeriod
- observationGracePeriodEnv
contractTransmitterTransmitTimeout
- contractTransmitterTransmitTimeoutEnv
createdAt
evmChainID
isBootstrapPeer
keyBundleID
observationTimeout
- observationTimeoutEnv
p2pBootstrapPeers
p2pv2Bootstrappers
transmitterAddress
@@ -443,26 +425,18 @@ func TestResolver_OCRSpec(t *testing.T) {
"spec": {
"__typename": "OCRSpec",
"blockchainTimeout": "1m0s",
- "blockchainTimeoutEnv": false,
"contractAddress": "0x613a38AC1659769640aaE063C651F48E0250454C",
"contractConfigConfirmations": 1,
- "contractConfigConfirmationsEnv": true,
"contractConfigTrackerPollInterval": "1m0s",
- "contractConfigTrackerPollIntervalEnv": false,
"contractConfigTrackerSubscribeInterval": "2m0s",
- "contractConfigTrackerSubscribeIntervalEnv": true,
"databaseTimeout": "3s",
- "databaseTimeoutEnv": true,
"observationGracePeriod": "4s",
- "observationGracePeriodEnv": true,
"contractTransmitterTransmitTimeout": "555ms",
- "contractTransmitterTransmitTimeoutEnv": true,
"createdAt": "2021-01-01T00:00:00Z",
"evmChainID": "42",
"isBootstrapPeer": false,
"keyBundleID": "f5bf259689b26f1374efb3c9a9868796953a0f814bb2d39b968d0e61b58620a5",
"observationTimeout": "2m0s",
- "observationTimeoutEnv": false,
"p2pBootstrapPeers": ["/dns4/test.com/tcp/2001/p2pkey"],
"p2pv2Bootstrappers": ["12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw@localhost:5001"],
"transmitterAddress": "0x3cCad4715152693fE3BC4460591e3D3Fbd071b42"
diff --git a/core/web/schema/type/spec.graphql b/core/web/schema/type/spec.graphql
index cdcbabf9ef..98203a1870 100644
--- a/core/web/schema/type/spec.graphql
+++ b/core/web/schema/type/spec.graphql
@@ -22,7 +22,6 @@ type DirectRequestSpec {
createdAt: Time!
evmChainID: String
minIncomingConfirmations: Int!
- minIncomingConfirmationsEnv: Boolean!
minContractPaymentLinkJuels: String!
requesters: [String!]
}
@@ -52,29 +51,21 @@ type KeeperSpec {
type OCRSpec {
blockchainTimeout: String
- blockchainTimeoutEnv: Boolean!
contractAddress: String!
contractConfigConfirmations: Int
- contractConfigConfirmationsEnv: Boolean!
contractConfigTrackerPollInterval: String
- contractConfigTrackerPollIntervalEnv: Boolean!
contractConfigTrackerSubscribeInterval: String
- contractConfigTrackerSubscribeIntervalEnv: Boolean!
createdAt: Time!
evmChainID: String
isBootstrapPeer: Boolean!
keyBundleID: String
observationTimeout: String
- observationTimeoutEnv: Boolean!
p2pBootstrapPeers: [String!]
p2pv2Bootstrappers: [String!]
transmitterAddress: String
databaseTimeout: String!
- databaseTimeoutEnv: Boolean!
observationGracePeriod: String!
- observationGracePeriodEnv: Boolean!
contractTransmitterTransmitTimeout: String!
- contractTransmitterTransmitTimeoutEnv: Boolean!
}
type OCR2Spec {
@@ -100,7 +91,6 @@ type VRFSpec {
evmChainID: String
fromAddresses: [String!]
minIncomingConfirmations: Int!
- minIncomingConfirmationsEnv: Boolean!
pollPeriod: String!
publicKey: String!
requestedConfsDelay: Int!
From 8c96682617ad90b57b759a95f1555c51b842ee00 Mon Sep 17 00:00:00 2001
From: Jim W
Date: Tue, 31 Oct 2023 16:53:02 -0400
Subject: [PATCH 044/327] remove dependency of postgres trigger for broadcaster
(#11109)
* remove dependency of postgres trigger for broadcaster
* remove extra argument in NewBroadcaster call
* fixes for extra args
* fix some failing tests and remove some error wraps
* remove pkgerrors from txm
* remove parseAddr which is now dead code
* fix error handling
* remove trigger from postgres via migration; use error wrapping in txmgr
* fix naming of new migration
---
common/txmgr/broadcaster.go | 40 -------------
common/txmgr/txmgr.go | 50 ++++++++++------
core/chains/evm/evm_txm.go | 1 -
core/chains/evm/txmgr/broadcaster_test.go | 60 ++-----------------
core/chains/evm/txmgr/builder.go | 7 +--
core/chains/evm/txmgr/common.go | 7 ---
core/chains/evm/txmgr/txmgr_test.go | 28 +++------
core/services/pg/channels.go | 1 -
.../0206_remove_tx_insert_trigger.sql | 18 ++++++
9 files changed, 67 insertions(+), 145 deletions(-)
create mode 100644 core/store/migrate/migrations/0206_remove_tx_insert_trigger.sql
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index 011866bf39..4f6ffae2ad 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -21,7 +21,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -123,8 +122,6 @@ type Broadcaster[
// when Start is called
autoSyncSequence bool
- txInsertListener pg.Subscription
- eventBroadcaster pg.EventBroadcaster
processUnstartedTxsImpl ProcessUnstartedTxs[ADDR]
ks txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ]
@@ -143,8 +140,6 @@ type Broadcaster[
initSync sync.Mutex
isStarted bool
- parseAddr func(string) (ADDR, error)
-
sequenceLock sync.RWMutex
nextSequenceMap map[ADDR]SEQ
generateNextSequence types.GenerateNextSequenceFunc[SEQ]
@@ -166,13 +161,11 @@ func NewBroadcaster[
txConfig txmgrtypes.BroadcasterTransactionsConfig,
listenerConfig txmgrtypes.BroadcasterListenerConfig,
keystore txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ],
- eventBroadcaster pg.EventBroadcaster,
txAttemptBuilder txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE],
sequenceSyncer SequenceSyncer[ADDR, TX_HASH, BLOCK_HASH, SEQ],
logger logger.Logger,
checkerFactory TransmitCheckerFactory[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE],
autoSyncSequence bool,
- parseAddress func(string) (ADDR, error),
generateNextSequence types.GenerateNextSequenceFunc[SEQ],
) *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] {
logger = logger.Named("Broadcaster")
@@ -187,11 +180,9 @@ func NewBroadcaster[
feeConfig: feeConfig,
txConfig: txConfig,
listenerConfig: listenerConfig,
- eventBroadcaster: eventBroadcaster,
ks: keystore,
checkerFactory: checkerFactory,
autoSyncSequence: autoSyncSequence,
- parseAddr: parseAddress,
}
b.processUnstartedTxsImpl = b.processUnstartedTxs
@@ -215,10 +206,6 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) star
return errors.New("Broadcaster is already started")
}
var err error
- eb.txInsertListener, err = eb.eventBroadcaster.Subscribe(pg.ChannelInsertOnTx, "")
- if err != nil {
- return errors.Wrap(err, "Broadcaster could not start")
- }
eb.enabledAddresses, err = eb.ks.EnabledAddressesForChain(eb.chainID)
if err != nil {
return errors.Wrap(err, "Broadcaster: failed to load EnabledAddressesForChain")
@@ -239,9 +226,6 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) star
go eb.monitorTxs(addr, triggerCh)
}
- eb.wg.Add(1)
- go eb.txInsertTriggerer()
-
eb.sequenceLock.Lock()
defer eb.sequenceLock.Unlock()
eb.nextSequenceMap, err = eb.loadNextSequenceMap(eb.enabledAddresses)
@@ -266,9 +250,6 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) clos
if !eb.isStarted {
return errors.Wrap(utils.ErrAlreadyStopped, "Broadcaster is not started")
}
- if eb.txInsertListener != nil {
- eb.txInsertListener.Close()
- }
close(eb.chStop)
eb.wg.Wait()
eb.isStarted = false
@@ -305,27 +286,6 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Trig
}
}
-func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) txInsertTriggerer() {
- defer eb.wg.Done()
- for {
- select {
- case ev, ok := <-eb.txInsertListener.Events():
- if !ok {
- eb.logger.Debug("txInsertListener channel closed, exiting trigger loop")
- return
- }
- addr, err := eb.parseAddr(ev.Payload)
- if err != nil {
- eb.logger.Errorw("failed to parse address in trigger", "err", err)
- continue
- }
- eb.Trigger(addr)
- case <-eb.chStop:
- return
- }
- }
-}
-
// Load the next sequence map using the tx table or on-chain (if not found in tx table)
func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) loadNextSequenceMap(addresses []ADDR) (map[ADDR]SEQ, error) {
ctx, cancel := eb.chStop.NewCtx()
diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go
index 0c7117afab..d80f534ad2 100644
--- a/common/txmgr/txmgr.go
+++ b/common/txmgr/txmgr.go
@@ -10,7 +10,6 @@ import (
"time"
"github.com/google/uuid"
- pkgerrors "github.com/pkg/errors"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
@@ -166,14 +165,14 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Start(ctx
return b.StartOnce("Txm", func() error {
var ms services.MultiStart
if err := ms.Start(ctx, b.broadcaster); err != nil {
- return pkgerrors.Wrap(err, "Txm: Broadcaster failed to start")
+ return fmt.Errorf("Txm: Broadcaster failed to start: %w", err)
}
if err := ms.Start(ctx, b.confirmer); err != nil {
- return pkgerrors.Wrap(err, "Txm: Confirmer failed to start")
+ return fmt.Errorf("Txm: Confirmer failed to start: %w", err)
}
if err := ms.Start(ctx, b.txAttemptBuilder); err != nil {
- return pkgerrors.Wrap(err, "Txm: Estimator failed to start")
+ return fmt.Errorf("Txm: Estimator failed to start: %w", err)
}
b.wg.Add(1)
@@ -190,7 +189,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Start(ctx
if b.fwdMgr != nil {
if err := ms.Start(ctx, b.fwdMgr); err != nil {
- return pkgerrors.Wrap(err, "Txm: ForwarderManager failed to start")
+ return fmt.Errorf("Txm: ForwarderManager failed to start: %w", err)
}
}
@@ -223,8 +222,10 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Reset(addr
func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) abandon(addr ADDR) (err error) {
ctx, cancel := utils.StopChan(b.chStop).NewCtx()
defer cancel()
- err = b.txStore.Abandon(ctx, b.chainID, addr)
- return pkgerrors.Wrapf(err, "abandon failed to update txes for key %s", addr.String())
+ if err = b.txStore.Abandon(ctx, b.chainID, addr); err != nil {
+ return fmt.Errorf("abandon failed to update txes for key %s: %w", addr.String(), err)
+ }
+ return nil
}
func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Close() (merr error) {
@@ -241,14 +242,14 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Close() (m
}
if b.fwdMgr != nil {
if err := b.fwdMgr.Close(); err != nil {
- merr = errors.Join(merr, pkgerrors.Wrap(err, "Txm: failed to stop ForwarderManager"))
+ merr = errors.Join(merr, fmt.Errorf("Txm: failed to stop ForwarderManager: %w", err))
}
}
b.wg.Wait()
if err := b.txAttemptBuilder.Close(); err != nil {
- merr = errors.Join(merr, pkgerrors.Wrap(err, "Txm: failed to close TxAttemptBuilder"))
+ merr = errors.Join(merr, fmt.Errorf("Txm: failed to close TxAttemptBuilder: %w", err))
}
return nil
@@ -444,7 +445,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTran
var existingTx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
existingTx, err = b.txStore.FindTxWithIdempotencyKey(ctx, *txRequest.IdempotencyKey, b.chainID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
- return tx, pkgerrors.Wrap(err, "Failed to search for transaction with IdempotencyKey")
+ return tx, fmt.Errorf("Failed to search for transaction with IdempotencyKey: %w", err)
}
if existingTx != nil {
b.logger.Infow("Found a Tx with IdempotencyKey. Returning existing Tx without creating a new one.", "IdempotencyKey", *txRequest.IdempotencyKey)
@@ -470,31 +471,40 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTran
txRequest.ToAddress = txRequest.ForwarderAddress
txRequest.EncodedPayload = fwdPayload
} else {
- b.logger.Errorf("Failed to use forwarder set upstream: %s", fwdErr.Error())
+ b.logger.Errorf("Failed to use forwarder set upstream: %w", fwdErr.Error())
}
}
err = b.txStore.CheckTxQueueCapacity(ctx, txRequest.FromAddress, b.txConfig.MaxQueued(), b.chainID)
if err != nil {
- return tx, pkgerrors.Wrap(err, "Txm#CreateTransaction")
+ return tx, fmt.Errorf("Txm#CreateTransaction: %w", err)
}
tx, err = b.txStore.CreateTransaction(ctx, txRequest, b.chainID)
- return
+ if err != nil {
+ return tx, err
+ }
+
+ // Trigger the Broadcaster to check for new transaction
+ b.broadcaster.Trigger(txRequest.FromAddress)
+
+ return tx, nil
}
// Calls forwarderMgr to get a proper forwarder for a given EOA.
func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetForwarderForEOA(eoa ADDR) (forwarder ADDR, err error) {
if !b.txConfig.ForwardersEnabled() {
- return forwarder, pkgerrors.Errorf("Forwarding is not enabled, to enable set Transactions.ForwardersEnabled =true")
+ return forwarder, fmt.Errorf("forwarding is not enabled, to enable set Transactions.ForwardersEnabled =true")
}
forwarder, err = b.fwdMgr.ForwarderFor(eoa)
return
}
func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) checkEnabled(addr ADDR) error {
- err := b.keyStore.CheckEnabled(addr, b.chainID)
- return pkgerrors.Wrapf(err, "cannot send transaction from %s on chain ID %s", addr, b.chainID.String())
+ if err := b.keyStore.CheckEnabled(addr, b.chainID); err != nil {
+ return fmt.Errorf("cannot send transaction from %s on chain ID %s: %w", addr, b.chainID.String(), err)
+ }
+ return nil
}
// SendNativeToken creates a transaction that transfers the given value of native tokens
@@ -511,7 +521,13 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SendNative
Strategy: NewSendEveryStrategy(),
}
etx, err = b.txStore.CreateTransaction(ctx, txRequest, chainID)
- return etx, pkgerrors.Wrap(err, "SendNativeToken failed to insert tx")
+ if err != nil {
+ return etx, fmt.Errorf("SendNativeToken failed to insert tx: %w", err)
+ }
+
+ // Trigger the Broadcaster to check for new transaction
+ b.broadcaster.Trigger(from)
+ return etx, nil
}
type NullTxManager[
diff --git a/core/chains/evm/evm_txm.go b/core/chains/evm/evm_txm.go
index d2f4178c7d..a8673e954a 100644
--- a/core/chains/evm/evm_txm.go
+++ b/core/chains/evm/evm_txm.go
@@ -61,7 +61,6 @@ func newEvmTxm(
lggr,
logPoller,
opts.KeyStore,
- opts.EventBroadcaster,
estimator)
} else {
txm = opts.GenTxManager(chainID)
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 3901da59ee..61a230c21b 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -15,7 +15,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/google/uuid"
- "github.com/onsi/gomega"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -44,9 +43,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
- pgmocks "github.com/smartcontractkit/chainlink/v2/core/services/pg/mocks"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -61,17 +58,14 @@ func NewTestEthBroadcaster(
nonceAutoSync bool,
) *txmgr.Broadcaster {
t.Helper()
- eb := cltest.NewEventBroadcaster(t, config.Database().URL())
ctx := testutils.Context(t)
- require.NoError(t, eb.Start(ctx))
- t.Cleanup(func() { assert.NoError(t, eb.Close()) })
lggr := logger.TestLogger(t)
ge := config.EVM().GasEstimator()
estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), ge.BlockHistory(), lggr), ge.EIP1559DynamicFees(), nil)
txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, keyStore, estimator)
txNonceSyncer := txmgr.NewNonceSyncer(txStore, lggr, ethClient)
- ethBroadcaster := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), config.Database().Listener(), keyStore, eb, txBuilder, txNonceSyncer, lggr, checkerFactory, nonceAutoSync)
+ ethBroadcaster := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), config.Database().Listener(), keyStore, txBuilder, txNonceSyncer, lggr, checkerFactory, nonceAutoSync)
// Mark instance as test
ethBroadcaster.XXXTestDisableUnstartedTxAutoProcessing()
@@ -82,10 +76,6 @@ func NewTestEthBroadcaster(
func TestEthBroadcaster_Lifecycle(t *testing.T) {
cfg, db := heavyweight.FullTestDBV2(t, "eth_broadcaster_optimistic_locking", nil)
- eventBroadcaster := cltest.NewEventBroadcaster(t, cfg.Database().URL())
- err := eventBroadcaster.Start(testutils.Context(t))
- require.NoError(t, err)
- t.Cleanup(func() { assert.NoError(t, eventBroadcaster.Close()) })
txStore := cltest.NewTestTxStore(t, db, cfg.Database())
evmcfg := evmtest.NewChainScopedConfig(t, cfg)
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
@@ -102,7 +92,6 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) {
evmcfg.EVM().Transactions(),
evmcfg.Database().Listener(),
ethKeyStore,
- eventBroadcaster,
txBuilder,
nil,
logger.TestLogger(t),
@@ -111,7 +100,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) {
)
// Can't close an unstarted instance
- err = eb.Close()
+ err := eb.Close()
require.Error(t, err)
ctx := testutils.Context(t)
@@ -577,9 +566,6 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) {
func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testing.T) {
// non-transactional DB needed because we deliberately test for FK violation
cfg, db := heavyweight.FullTestDBV2(t, "eth_broadcaster_optimistic_locking", nil)
- eventBroadcaster := cltest.NewEventBroadcaster(t, cfg.Database().URL())
- require.NoError(t, eventBroadcaster.Start(testutils.Context(t)))
- t.Cleanup(func() { assert.NoError(t, eventBroadcaster.Close()) })
txStore := cltest.NewTestTxStore(t, db, cfg.Database())
ccfg := evmtest.NewChainScopedConfig(t, cfg)
evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM())
@@ -605,7 +591,6 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi
ccfg.EVM().Transactions(),
cfg.Database().Listener(),
ethKeyStore,
- eventBroadcaster,
txBuilder,
nil,
logger.TestLogger(t),
@@ -1113,17 +1098,12 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// same as the parent test, but callback is set by ctor
t.Run("callback set by ctor", func(t *testing.T) {
- eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New())
- err := eventBroadcaster.Start(testutils.Context(t))
- require.NoError(t, err)
- t.Cleanup(func() { assert.NoError(t, eventBroadcaster.Close()) })
lggr := logger.TestLogger(t)
estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr), evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil)
txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator)
localNextNonce = getLocalNextNonce(t, eb, fromAddress)
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce), nil).Once()
- eb2 := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), evmcfg.Database().Listener(), ethKeyStore, eventBroadcaster, txBuilder, nil, lggr, &testCheckerFactory{}, false)
- require.NoError(t, err)
+ eb2 := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), evmcfg.Database().Listener(), ethKeyStore, txBuilder, nil, lggr, &testCheckerFactory{}, false)
retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1724,29 +1704,6 @@ func TestEthBroadcaster_Trigger(t *testing.T) {
eb.Trigger(testutils.NewAddress())
}
-func TestEthBroadcaster_EthTxInsertEventCausesTriggerToFire(t *testing.T) {
- // NOTE: Testing triggers requires committing transactions and does not work with transactional tests
- cfg, db := heavyweight.FullTestDBV2(t, "eth_tx_triggers", nil)
- txStore := cltest.NewTestTxStore(t, db, cfg.Database())
-
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
-
- ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth()
- _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
- eventBroadcaster := cltest.NewEventBroadcaster(t, evmcfg.Database().URL())
- require.NoError(t, eventBroadcaster.Start(testutils.Context(t)))
- t.Cleanup(func() { require.NoError(t, eventBroadcaster.Close()) })
-
- ethTxInsertListener, err := eventBroadcaster.Subscribe(pg.ChannelInsertOnTx, "")
- require.NoError(t, err)
-
- // Give it some time to start listening
- time.Sleep(100 * time.Millisecond)
-
- cltest.MustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID)
- gomega.NewWithT(t).Eventually(ethTxInsertListener.Events()).Should(gomega.Receive())
-}
-
func TestEthBroadcaster_SyncNonce(t *testing.T) {
db := pgtest.NewSqlxDB(t)
ctx := testutils.Context(t)
@@ -1765,11 +1722,6 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
ethNodeNonce := uint64(22)
- eventBroadcaster := pgmocks.NewEventBroadcaster(t)
- sub := pgmocks.NewSubscription(t)
- sub.On("Events").Return(make(<-chan pg.Event))
- sub.On("Close")
- eventBroadcaster.On("Subscribe", "evm.insert_on_txes", "").Return(sub, nil)
estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr), evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil)
checkerFactory := &testCheckerFactory{}
@@ -1783,7 +1735,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
addresses := []gethCommon.Address{fromAddress}
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Once()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
- eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, eventBroadcaster, txBuilder, nil, lggr, checkerFactory, false)
+ eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, nil, lggr, checkerFactory, false)
err := eb.Start(testutils.Context(t))
assert.NoError(t, err)
@@ -1801,7 +1753,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
addresses := []gethCommon.Address{fromAddress}
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Once()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
- eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, eventBroadcaster, txBuilder, txNonceSyncer, lggr, checkerFactory, true)
+ eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, txNonceSyncer, lggr, checkerFactory, true)
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(ethNodeNonce), nil).Once()
require.NoError(t, eb.Start(ctx))
@@ -1832,7 +1784,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Once()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
- eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, eventBroadcaster, txBuilder, txNonceSyncer, lggr, checkerFactory, true)
+ eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, txNonceSyncer, lggr, checkerFactory, true)
eb.XXXTestDisableUnstartedTxAutoProcessing()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), errors.New("something exploded")).Once()
diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go
index 39781e83f4..9123d1dfc0 100644
--- a/core/chains/evm/txmgr/builder.go
+++ b/core/chains/evm/txmgr/builder.go
@@ -16,7 +16,6 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
)
// NewTxm constructs the necessary dependencies for the EvmTxm (broadcaster, confirmer, etc) and returns a new EvmTxManager
@@ -31,7 +30,6 @@ func NewTxm(
lggr logger.Logger,
logPoller logpoller.LogPoller,
keyStore keystore.Eth,
- eventBroadcaster pg.EventBroadcaster,
estimator gas.EvmFeeEstimator,
) (txm TxManager,
err error,
@@ -52,7 +50,7 @@ func NewTxm(
txmCfg := NewEvmTxmConfig(chainConfig) // wrap Evm specific config
feeCfg := NewEvmTxmFeeConfig(fCfg) // wrap Evm specific config
txmClient := NewEvmTxmClient(client) // wrap Evm specific client
- ethBroadcaster := NewEvmBroadcaster(txStore, txmClient, txmCfg, feeCfg, txConfig, listenerConfig, keyStore, eventBroadcaster, txAttemptBuilder, txNonceSyncer, lggr, checker, chainConfig.NonceAutoSync())
+ ethBroadcaster := NewEvmBroadcaster(txStore, txmClient, txmCfg, feeCfg, txConfig, listenerConfig, keyStore, txAttemptBuilder, txNonceSyncer, lggr, checker, chainConfig.NonceAutoSync())
ethConfirmer := NewEvmConfirmer(txStore, txmClient, txmCfg, feeCfg, txConfig, dbConfig, keyStore, txAttemptBuilder, lggr)
var ethResender *Resender
if txConfig.ResendAfterThreshold() > 0 {
@@ -123,12 +121,11 @@ func NewEvmBroadcaster(
txConfig txmgrtypes.BroadcasterTransactionsConfig,
listenerConfig txmgrtypes.BroadcasterListenerConfig,
keystore KeyStore,
- eventBroadcaster pg.EventBroadcaster,
txAttemptBuilder TxAttemptBuilder,
nonceSyncer NonceSyncer,
logger logger.Logger,
checkerFactory TransmitCheckerFactory,
autoSyncNonce bool,
) *Broadcaster {
- return txmgr.NewBroadcaster(txStore, client, chainConfig, feeConfig, txConfig, listenerConfig, keystore, eventBroadcaster, txAttemptBuilder, nonceSyncer, logger, checkerFactory, autoSyncNonce, stringToGethAddress, evmtypes.GenerateNextNonce)
+ return txmgr.NewBroadcaster(txStore, client, chainConfig, feeConfig, txConfig, listenerConfig, keystore, txAttemptBuilder, nonceSyncer, logger, checkerFactory, autoSyncNonce, evmtypes.GenerateNextNonce)
}
diff --git a/core/chains/evm/txmgr/common.go b/core/chains/evm/txmgr/common.go
index 5dbb2ef961..37cc89dd7a 100644
--- a/core/chains/evm/txmgr/common.go
+++ b/core/chains/evm/txmgr/common.go
@@ -69,10 +69,3 @@ func batchSendTransactions(
}
return reqs, now, successfulBroadcast, nil
}
-
-func stringToGethAddress(s string) (common.Address, error) {
- if !common.IsHexAddress(s) {
- return common.Address{}, fmt.Errorf("invalid hex address: %s", s)
- }
- return common.HexToAddress(s), nil
-}
diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go
index 6cb43b2771..e9823ee021 100644
--- a/core/chains/evm/txmgr/txmgr_test.go
+++ b/core/chains/evm/txmgr/txmgr_test.go
@@ -37,12 +37,11 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- pgmocks "github.com/smartcontractkit/chainlink/v2/core/services/pg/mocks"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
func makeTestEvmTxm(
- t *testing.T, db *sqlx.DB, ethClient evmclient.Client, estimator gas.EvmFeeEstimator, ccfg txmgr.ChainConfig, fcfg txmgr.FeeConfig, txConfig evmconfig.Transactions, dbConfig txmgr.DatabaseConfig, listenerConfig txmgr.ListenerConfig, keyStore keystore.Eth, eventBroadcaster pg.EventBroadcaster) (txmgr.TxManager, error) {
+ t *testing.T, db *sqlx.DB, ethClient evmclient.Client, estimator gas.EvmFeeEstimator, ccfg txmgr.ChainConfig, fcfg txmgr.FeeConfig, txConfig evmconfig.Transactions, dbConfig txmgr.DatabaseConfig, listenerConfig txmgr.ListenerConfig, keyStore keystore.Eth) (txmgr.TxManager, error) {
lggr := logger.TestLogger(t)
lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr, pgtest.NewQConfig(true)), ethClient, lggr, 100*time.Millisecond, false, 2, 3, 2, 1000)
@@ -66,7 +65,6 @@ func makeTestEvmTxm(
lggr,
lp,
keyStore,
- eventBroadcaster,
estimator)
}
@@ -83,7 +81,7 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) {
keyStore := cltest.NewKeyStore(t, db, dbConfig).Eth()
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator())
- txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore, nil)
+ txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore)
require.NoError(t, err)
_, err = txm.SendNativeToken(testutils.Context(t), big.NewInt(0), from, to, *value, 21000)
@@ -109,7 +107,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator())
- txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth(), nil)
+ txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth())
require.NoError(t, err)
t.Run("with queue under capacity inserts eth_tx", func(t *testing.T) {
@@ -523,7 +521,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator())
- txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), etKeyStore, nil)
+ txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), etKeyStore)
require.NoError(t, err)
t.Run("if another key has any transactions with insufficient eth errors, transmits as normal", func(t *testing.T) {
@@ -567,7 +565,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
Meta: nil,
Strategy: strategy,
})
- assert.NoError(t, err)
+ require.NoError(t, err)
require.Equal(t, payload, etx.EncodedPayload)
})
@@ -589,7 +587,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
Meta: nil,
Strategy: strategy,
})
- assert.NoError(t, err)
+ require.NoError(t, err)
require.Equal(t, payload, etx.EncodedPayload)
})
}
@@ -599,7 +597,6 @@ func TestTxm_Lifecycle(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
kst := ksmocks.NewEth(t)
- eventBroadcaster := pgmocks.NewEventBroadcaster(t)
config, dbConfig, evmConfig := makeConfigs(t)
config.finalityDepth = uint32(42)
@@ -615,16 +612,13 @@ func TestTxm_Lifecycle(t *testing.T) {
unsub := cltest.NewAwaiter()
kst.On("SubscribeToKeyChanges").Return(keyChangeCh, unsub.ItHappened)
estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator())
- txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst, eventBroadcaster)
+ txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst)
require.NoError(t, err)
head := cltest.Head(42)
// It should not hang or panic
txm.OnNewLongestChain(testutils.Context(t), head)
- sub := pgmocks.NewSubscription(t)
- sub.On("Events").Return(make(<-chan pg.Event))
- eventBroadcaster.On("Subscribe", "evm.insert_on_txes", "").Return(sub, nil)
evmConfig.bumpThreshold = uint64(1)
require.NoError(t, txm.Start(testutils.Context(t)))
@@ -638,7 +632,6 @@ func TestTxm_Lifecycle(t *testing.T) {
addr := []gethcommon.Address{keyState.Address.Address()}
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addr, nil)
- sub.On("Close").Return()
ethClient.On("PendingNonceAt", mock.AnythingOfType("*context.cancelCtx"), gethcommon.Address{}).Return(uint64(0), nil).Maybe()
keyChangeCh <- struct{}{}
@@ -670,14 +663,9 @@ func TestTxm_Reset(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil)
ethClient.On("BatchCallContextAll", mock.Anything, mock.Anything).Return(nil).Maybe()
- eventBroadcaster := pgmocks.NewEventBroadcaster(t)
- sub := pgmocks.NewSubscription(t)
- sub.On("Events").Return(make(<-chan pg.Event))
- sub.On("Close")
- eventBroadcaster.On("Subscribe", "evm.insert_on_txes", "").Return(sub, nil)
estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, cfg.EVM(), cfg.EVM().GasEstimator())
- txm, err := makeTestEvmTxm(t, db, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), cfg.Database(), cfg.Database().Listener(), kst.Eth(), eventBroadcaster)
+ txm, err := makeTestEvmTxm(t, db, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), cfg.Database(), cfg.Database().Listener(), kst.Eth())
require.NoError(t, err)
cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, addr2)
diff --git a/core/services/pg/channels.go b/core/services/pg/channels.go
index 736cd40796..1d67dabe52 100644
--- a/core/services/pg/channels.go
+++ b/core/services/pg/channels.go
@@ -2,7 +2,6 @@ package pg
// Postgres channel to listen for new evm.txes
const (
- ChannelInsertOnTx = "evm.insert_on_txes"
ChannelInsertOnCosmosMsg = "insert_on_cosmos_msg"
ChannelInsertOnEVMLogs = "evm.insert_on_logs"
)
diff --git a/core/store/migrate/migrations/0206_remove_tx_insert_trigger.sql b/core/store/migrate/migrations/0206_remove_tx_insert_trigger.sql
new file mode 100644
index 0000000000..94b2e4aa8a
--- /dev/null
+++ b/core/store/migrate/migrations/0206_remove_tx_insert_trigger.sql
@@ -0,0 +1,18 @@
+-- +goose Up
+DROP TRIGGER IF EXISTS notify_tx_insertion on evm.txes;
+DROP FUNCTION IF EXISTS evm.notifyethtxinsertion();
+
+
+-- +goose Down
+-- +goose StatementBegin
+CREATE OR REPLACE FUNCTION evm.notifytxinsertion() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ BEGIN
+ PERFORM pg_notify('evm.insert_on_txes'::text, encode(NEW.from_address, 'hex'));
+ RETURN NULL;
+ END
+ $$;
+
+CREATE TRIGGER notify_tx_insertion AFTER INSERT ON evm.txes FOR EACH ROW EXECUTE PROCEDURE evm.notifytxinsertion();
+-- +goose StatementEnd
\ No newline at end of file
From 24de8afe09954c45c16d2143186e042bcb300788 Mon Sep 17 00:00:00 2001
From: Morgan Kuphal <87319522+KuphJr@users.noreply.github.com>
Date: Tue, 31 Oct 2023 18:55:58 -0500
Subject: [PATCH 045/327] Get request logs from past n blocks (#11052)
* Get request logs from past n blocks
* Separate confirmations setting for reqs & resps
* Filter already detected reqs & resps
* validate pastBlocksToPoll
* Fixed bugs which appeared during tests
* Addressed feedback
* Added test
* Added comment to config
* Fixed log & removed const
* Used const values for defaults
* Address feedback
* Fixed types for logPoller
* Added tests for FilterPreviouslyDetectedEvents
* Added additional test assertions
* Fixed lint errors
---
core/scripts/functions/templates/oracle.toml | 1 +
.../ocr2/plugins/functions/config/config.go | 4 +
.../relay/evm/functions/logpoller_wrapper.go | 174 +++++++++++++-----
.../evm/functions/logpoller_wrapper_test.go | 127 ++++++++++++-
4 files changed, 250 insertions(+), 56 deletions(-)
diff --git a/core/scripts/functions/templates/oracle.toml b/core/scripts/functions/templates/oracle.toml
index 4739252d68..d21fe4a5e8 100644
--- a/core/scripts/functions/templates/oracle.toml
+++ b/core/scripts/functions/templates/oracle.toml
@@ -36,6 +36,7 @@ requestTimeoutSec = 300
maxRequestSizesList = [30_720, 51_200, 102_400, 204_800, 512_000, 1_048_576, 2_097_152, 3_145_728, 5_242_880, 10_485_760]
maxSecretsSizesList = [10_240, 20_480, 51_200, 102_400, 307_200, 512_000, 1_048_576, 2_097_152]
minimumSubscriptionBalance = "2 link"
+pastBlocksToPoll = 25
[pluginConfig.OnchainAllowlist]
diff --git a/core/services/ocr2/plugins/functions/config/config.go b/core/services/ocr2/plugins/functions/config/config.go
index 3f35d1dba9..0978500deb 100644
--- a/core/services/ocr2/plugins/functions/config/config.go
+++ b/core/services/ocr2/plugins/functions/config/config.go
@@ -23,7 +23,11 @@ type PluginConfig struct {
EnableRequestSignatureCheck bool `json:"enableRequestSignatureCheck"`
DONID string `json:"donID"`
ContractVersion uint32 `json:"contractVersion"`
+ MinRequestConfirmations uint32 `json:"minRequestConfirmations"`
+ MinResponseConfirmations uint32 `json:"minResponseConfirmations"`
MinIncomingConfirmations uint32 `json:"minIncomingConfirmations"`
+ PastBlocksToPoll uint32 `json:"pastBlocksToPoll"`
+ LogPollerCacheDurationSec uint32 `json:"logPollerCacheDurationSec"` // Duration to cache previously detected request or response logs such that they can be filtered when calling logpoller_wrapper.LatestEvents()
RequestTimeoutSec uint32 `json:"requestTimeoutSec"`
RequestTimeoutCheckFrequencySec uint32 `json:"requestTimeoutCheckFrequencySec"`
RequestTimeoutBatchLookupSize uint32 `json:"requestTimeoutBatchLookupSize"`
diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go
index d355bd6569..6193f4ba86 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper.go
@@ -24,21 +24,39 @@ import (
type logPollerWrapper struct {
services.StateMachine
- routerContract *functions_router.FunctionsRouter
- pluginConfig config.PluginConfig
- client client.Client
- logPoller logpoller.LogPoller
- subscribers map[string]evmRelayTypes.RouteUpdateSubscriber
- activeCoordinator common.Address
- proposedCoordinator common.Address
- blockOffset int64
- nextBlock int64
- mu sync.Mutex
- closeWait sync.WaitGroup
- stopCh utils.StopChan
- lggr logger.Logger
+ routerContract *functions_router.FunctionsRouter
+ pluginConfig config.PluginConfig
+ client client.Client
+ logPoller logpoller.LogPoller
+ subscribers map[string]evmRelayTypes.RouteUpdateSubscriber
+ activeCoordinator common.Address
+ proposedCoordinator common.Address
+ requestBlockOffset int64
+ responseBlockOffset int64
+ pastBlocksToPoll int64
+ logPollerCacheDurationSec int64
+ detectedRequests detectedEvents
+ detectedResponses detectedEvents
+ mu sync.Mutex
+ closeWait sync.WaitGroup
+ stopCh utils.StopChan
+ lggr logger.Logger
}
+type detectedEvent struct {
+ requestId [32]byte
+ timeDetected time.Time
+}
+
+type detectedEvents struct {
+ isPreviouslyDetected map[[32]byte]struct{}
+ detectedEventsOrdered []detectedEvent
+}
+
+const logPollerCacheDurationSecDefault = 300
+const pastBlocksToPollDefault = 50
+const maxLogsToProcess = 1000
+
var _ evmRelayTypes.LogPollerWrapper = &logPollerWrapper{}
func NewLogPollerWrapper(routerContractAddress common.Address, pluginConfig config.PluginConfig, client client.Client, logPoller logpoller.LogPoller, lggr logger.Logger) (evmRelayTypes.LogPollerWrapper, error) {
@@ -48,18 +66,48 @@ func NewLogPollerWrapper(routerContractAddress common.Address, pluginConfig conf
}
blockOffset := int64(pluginConfig.MinIncomingConfirmations) - 1
if blockOffset < 0 {
+ lggr.Warnw("invalid minIncomingConfirmations, using 1 instead", "minIncomingConfirmations", pluginConfig.MinIncomingConfirmations)
blockOffset = 0
}
+ requestBlockOffset := int64(pluginConfig.MinRequestConfirmations) - 1
+ if requestBlockOffset < 0 {
+ lggr.Warnw("invalid minRequestConfirmations, using minIncomingConfirmations instead", "minRequestConfirmations", pluginConfig.MinRequestConfirmations)
+ requestBlockOffset = blockOffset
+ }
+ responseBlockOffset := int64(pluginConfig.MinResponseConfirmations) - 1
+ if responseBlockOffset < 0 {
+ lggr.Warnw("invalid minResponseConfirmations, using minIncomingConfirmations instead", "minResponseConfirmations", pluginConfig.MinResponseConfirmations)
+ responseBlockOffset = blockOffset
+ }
+ logPollerCacheDurationSec := int64(pluginConfig.LogPollerCacheDurationSec)
+ if logPollerCacheDurationSec <= 0 {
+ lggr.Warnw("invalid logPollerCacheDuration, using 300 instead", "logPollerCacheDurationSec", logPollerCacheDurationSec)
+ logPollerCacheDurationSec = logPollerCacheDurationSecDefault
+ }
+ pastBlocksToPoll := int64(pluginConfig.PastBlocksToPoll)
+ if pastBlocksToPoll <= 0 {
+ lggr.Warnw("invalid pastBlocksToPoll, using 50 instead", "pastBlocksToPoll", pastBlocksToPoll)
+ pastBlocksToPoll = pastBlocksToPollDefault
+ }
+ if blockOffset >= pastBlocksToPoll || requestBlockOffset >= pastBlocksToPoll || responseBlockOffset >= pastBlocksToPoll {
+ lggr.Errorw("invalid config: number of required confirmation blocks >= pastBlocksToPoll", "pastBlocksToPoll", pastBlocksToPoll, "minIncomingConfirmations", pluginConfig.MinIncomingConfirmations, "minRequestConfirmations", pluginConfig.MinRequestConfirmations, "minResponseConfirmations", pluginConfig.MinResponseConfirmations)
+ return nil, errors.Errorf("invalid config: number of required confirmation blocks >= pastBlocksToPoll")
+ }
return &logPollerWrapper{
- routerContract: routerContract,
- pluginConfig: pluginConfig,
- blockOffset: blockOffset,
- logPoller: logPoller,
- client: client,
- subscribers: make(map[string]evmRelayTypes.RouteUpdateSubscriber),
- stopCh: make(utils.StopChan),
- lggr: lggr,
+ routerContract: routerContract,
+ pluginConfig: pluginConfig,
+ requestBlockOffset: requestBlockOffset,
+ responseBlockOffset: responseBlockOffset,
+ pastBlocksToPoll: pastBlocksToPoll,
+ logPollerCacheDurationSec: logPollerCacheDurationSec,
+ detectedRequests: detectedEvents{isPreviouslyDetected: make(map[[32]byte]struct{})},
+ detectedResponses: detectedEvents{isPreviouslyDetected: make(map[[32]byte]struct{})},
+ logPoller: logPoller,
+ client: client,
+ subscribers: make(map[string]evmRelayTypes.RouteUpdateSubscriber),
+ stopCh: make(utils.StopChan),
+ lggr: lggr,
}, nil
}
@@ -68,20 +116,11 @@ func (l *logPollerWrapper) Start(context.Context) error {
l.lggr.Infow("starting LogPollerWrapper", "routerContract", l.routerContract.Address().Hex(), "contractVersion", l.pluginConfig.ContractVersion)
l.mu.Lock()
defer l.mu.Unlock()
- if l.pluginConfig.ContractVersion == 0 {
- l.activeCoordinator = l.routerContract.Address()
- l.proposedCoordinator = l.routerContract.Address()
- } else if l.pluginConfig.ContractVersion == 1 {
- nextBlock, err := l.logPoller.LatestBlock()
- if err != nil {
- l.lggr.Errorw("LogPollerWrapper: LatestBlock() failed, starting from 0", "error", err)
- } else {
- l.lggr.Debugw("LogPollerWrapper: LatestBlock() got starting block", "block", nextBlock)
- l.nextBlock = nextBlock.BlockNumber - l.blockOffset
- }
- l.closeWait.Add(1)
- go l.checkForRouteUpdates()
+ if l.pluginConfig.ContractVersion != 1 {
+ return errors.New("only contract version 1 is supported")
}
+ l.closeWait.Add(1)
+ go l.checkForRouteUpdates()
return nil
})
}
@@ -117,16 +156,15 @@ func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmR
if l.proposedCoordinator != (common.Address{}) && l.activeCoordinator != l.proposedCoordinator {
coordinators = append(coordinators, l.proposedCoordinator)
}
- nextBlock := l.nextBlock
latest, err := l.logPoller.LatestBlock()
if err != nil {
l.mu.Unlock()
return nil, nil, err
}
- latestBlockNumber := latest.BlockNumber
- latestBlockNumber -= l.blockOffset
- if latestBlockNumber >= nextBlock {
- l.nextBlock = latestBlockNumber + 1
+ latestBlockNum := latest.BlockNumber
+ startBlockNum := latestBlockNum - l.pastBlocksToPoll
+ if startBlockNum < 0 {
+ startBlockNum = 0
}
l.mu.Unlock()
@@ -137,22 +175,24 @@ func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmR
l.lggr.Debug("LatestEvents: no non-zero coordinators to check")
return resultsReq, resultsResp, errors.New("no non-zero coordinators to check")
}
- if latestBlockNumber < nextBlock {
- l.lggr.Debugw("LatestEvents: no new blocks to check", "latest", latest, "nextBlock", nextBlock)
- return resultsReq, resultsResp, nil
- }
for _, coordinator := range coordinators {
- requestLogs, err := l.logPoller.Logs(nextBlock, latestBlockNumber, functions_coordinator.FunctionsCoordinatorOracleRequest{}.Topic(), coordinator)
+ requestEndBlock := latestBlockNum - l.requestBlockOffset
+ requestLogs, err := l.logPoller.Logs(startBlockNum, requestEndBlock, functions_coordinator.FunctionsCoordinatorOracleRequest{}.Topic(), coordinator)
if err != nil {
- l.lggr.Errorw("LatestEvents: fetching request logs from LogPoller failed", "latest", latest, "nextBlock", nextBlock)
+ l.lggr.Errorw("LatestEvents: fetching request logs from LogPoller failed", "startBlock", startBlockNum, "endBlock", requestEndBlock)
return nil, nil, err
}
- responseLogs, err := l.logPoller.Logs(nextBlock, latestBlockNumber, functions_coordinator.FunctionsCoordinatorOracleResponse{}.Topic(), coordinator)
+ l.lggr.Debugw("LatestEvents: fetched request logs", "nRequestLogs", len(requestLogs), "latestBlock", latest, "startBlock", startBlockNum, "endBlock", requestEndBlock)
+ requestLogs = l.filterPreviouslyDetectedEvents(requestLogs, &l.detectedRequests, "requests")
+ responseEndBlock := latestBlockNum - l.responseBlockOffset
+ responseLogs, err := l.logPoller.Logs(startBlockNum, responseEndBlock, functions_coordinator.FunctionsCoordinatorOracleResponse{}.Topic(), coordinator)
if err != nil {
- l.lggr.Errorw("LatestEvents: fetching response logs from LogPoller failed", "latest", latest, "nextBlock", nextBlock)
+ l.lggr.Errorw("LatestEvents: fetching response logs from LogPoller failed", "startBlock", startBlockNum, "endBlock", responseEndBlock)
return nil, nil, err
}
+ l.lggr.Debugw("LatestEvents: fetched request logs", "nResponseLogs", len(responseLogs), "latestBlock", latest, "startBlock", startBlockNum, "endBlock", responseEndBlock)
+ responseLogs = l.filterPreviouslyDetectedEvents(responseLogs, &l.detectedResponses, "responses")
parsingContract, err := functions_coordinator.NewFunctionsCoordinator(coordinator, l.client)
if err != nil {
@@ -165,7 +205,7 @@ func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmR
gethLog := log.ToGethLog()
oracleRequest, err := parsingContract.ParseOracleRequest(gethLog)
if err != nil {
- l.lggr.Errorw("LatestEvents: failed to parse a request log, skipping")
+ l.lggr.Errorw("LatestEvents: failed to parse a request log, skipping", "err", err)
continue
}
@@ -241,10 +281,46 @@ func (l *logPollerWrapper) LatestEvents() ([]evmRelayTypes.OracleRequest, []evmR
}
}
- l.lggr.Debugw("LatestEvents: done", "nRequestLogs", len(resultsReq), "nResponseLogs", len(resultsResp), "nextBlock", nextBlock, "latest", latest)
+ l.lggr.Debugw("LatestEvents: done", "nRequestLogs", len(resultsReq), "nResponseLogs", len(resultsResp), "startBlock", startBlockNum, "endBlock", latestBlockNum)
return resultsReq, resultsResp, nil
}
+func (l *logPollerWrapper) filterPreviouslyDetectedEvents(logs []logpoller.Log, detectedEvents *detectedEvents, filterType string) []logpoller.Log {
+ if len(logs) > maxLogsToProcess {
+ l.lggr.Errorw("filterPreviouslyDetectedEvents: too many logs to process, only processing latest maxLogsToProcess logs", "filterType", filterType, "nLogs", len(logs), "maxLogsToProcess", maxLogsToProcess)
+ logs = logs[len(logs)-maxLogsToProcess:]
+ }
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ filteredLogs := []logpoller.Log{}
+ for _, log := range logs {
+ var requestId [32]byte
+ if len(log.Topics) < 2 || len(log.Topics[1]) != 32 {
+ l.lggr.Errorw("filterPreviouslyDetectedEvents: invalid log, skipping", "filterType", filterType, "log", log)
+ continue
+ }
+ copy(requestId[:], log.Topics[1]) // requestId is the second topic (1st topic is the event signature)
+ if _, ok := detectedEvents.isPreviouslyDetected[requestId]; !ok {
+ filteredLogs = append(filteredLogs, log)
+ detectedEvents.isPreviouslyDetected[requestId] = struct{}{}
+ detectedEvents.detectedEventsOrdered = append(detectedEvents.detectedEventsOrdered, detectedEvent{requestId: requestId, timeDetected: time.Now()})
+ }
+ }
+ expiredRequests := 0
+ for _, detectedEvent := range detectedEvents.detectedEventsOrdered {
+ expirationTime := time.Now().Add(-time.Second * time.Duration(l.logPollerCacheDurationSec))
+ if detectedEvent.timeDetected.Before(expirationTime) {
+ delete(detectedEvents.isPreviouslyDetected, detectedEvent.requestId)
+ expiredRequests++
+ } else {
+ break
+ }
+ }
+ detectedEvents.detectedEventsOrdered = detectedEvents.detectedEventsOrdered[expiredRequests:]
+ l.lggr.Debugw("filterPreviouslyDetectedEvents: done", "filterType", filterType, "nLogs", len(logs), "nFilteredLogs", len(filteredLogs), "nExpiredRequests", expiredRequests, "previouslyDetectedCacheSize", len(detectedEvents.detectedEventsOrdered))
+ return filteredLogs
+}
+
// "internal" method called only by EVM relayer components
func (l *logPollerWrapper) SubscribeToUpdates(subscriberName string, subscriber evmRelayTypes.RouteUpdateSubscriber) {
if l.pluginConfig.ContractVersion == 0 {
diff --git a/core/services/relay/evm/functions/logpoller_wrapper_test.go b/core/services/relay/evm/functions/logpoller_wrapper_test.go
index c91c3c49aa..2108e822d5 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper_test.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper_test.go
@@ -1,22 +1,24 @@
-package functions_test
+package functions
import (
+ "crypto/rand"
"encoding/hex"
"sync"
"testing"
+ "time"
"github.com/ethereum/go-ethereum/common"
- gethcommon "github.com/ethereum/go-ethereum/common"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
)
@@ -57,17 +59,34 @@ func setUp(t *testing.T, updateFrequencySec uint32) (*lpmocks.LogPoller, types.L
ContractUpdateCheckFrequencySec: updateFrequencySec,
ContractVersion: 1,
}
- lpWrapper, err := functions.NewLogPollerWrapper(gethcommon.Address{}, config, client, lp, lggr)
+ lpWrapper, err := NewLogPollerWrapper(common.Address{}, config, client, lp, lggr)
require.NoError(t, err)
- lp.On("LatestBlock").Return(logpoller.LogPollerBlock{BlockNumber: int64(100)}, nil)
-
return lp, lpWrapper, client
}
+func getMockedRequestLog(t *testing.T) logpoller.Log {
+ // NOTE: Change this to be a more readable log generation
+ data, err := hex.DecodeString("000000000000000000000000c113ba31b0080f940ca5812bbccc1e038ea9efb40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c113ba31b0080f940ca5812bbccc1e038ea9efb4000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001117082cd81744eb9504dc37f53a86db7e3fb24929b8e7507b097d501ab5b315fb20e0000000000000000000000001b4f2b0e6363097f413c249910d5bc632993ed08000000000000000000000000000000000000000000000000015bcf880382c000000000000000000000000000665785a800593e8fa915208c1ce62f6e57fd75ba0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001117000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004f588000000000000000000000000000000000000000000000000000000000000c350000000000000000000000000000000000000000000000000000000000000021c00000000000000000000000000000000000000000000000000000000000008866c636f64654c6f636174696f6ec258200000000000000000000000000000000000000000000000000000000000000000686c616e6775616765c25820000000000000000000000000000000000000000000000000000000000000000066736f757263657907d0633836366665643238326533313137636466303836633934396662613133643834666331376131656335353934656361643034353133646632326137623538356333363763633132326236373138306334383737303435616235383033373463353066313862346564386132346131323437383532363731623030633035663237373163663036363632333663333236393939323139363866323833346438626462616266306661643165313237613837643237363936323831643965656539326134646263316337356137316136656333613135356438633230616661643064623432383362613433353736303734653035633433633561653061656466643332323838346536613231386466323430323630316436356437316131303061633065376563643037663565646364633535643562373932646130626632353665623038363139336463376431333965613764373965653531653831356465333834386565643363366330353837393265366461333434363738626436373239346636643639656564356132663836323835343965616530323235323835346232666361333635646265623032383433386537326234383465383864316136646563373933633739656265353834666465363465663831383363313365386231623735663037636532303963393138633532643637613735343862653236366433663964316439656132613162303166633838376231316162383739663164333861373833303563373031316533643938346130393863663634383931316536653065383038396365306130363230393136663134323935343036336630376239343931326435666331393366303138633764616135363136323562313966376463323036663930353365623234643036323234616164326338623430646162663631656166666635326234653831373239353837333830313561643730663739316663643864333739343035353737393563383937363164636665333639373938373437353439633234643530646464303563623337613465613863353162306530313032363738643433653766306563353039653434633564343764353335626261363831303936383264643864653439326532363633646336653133653532383539663664336565306533633430336236366362653338643236366137356163373639363863613465653331396166363965373431333137393162653630376537353832373430366164653038306335623239653665343262386563386137373761663865383166336234616337626263666531643066616633393338613664353061316561633835643933643234343066313863333037356237306433626134663930323836396439383937663266636562626262366263646439333436633336633663643838626434336265306562333134323562343665613765386338336638386230363933343836383666366134313839623535666132666431396634326264333730313634616339356530303635656461663130373761633131366632393930303833616631333839636661666336613433323439376531363437393762633738616633366335613435366136646661326636626430626639326136613930366130653930313130626266323265613066333163663364353132663466303331653236343330633831663935656431323362323938356266623830623161396432646337306232356264613961386261303839323833666166663634383661316231646235613938353564346237363966623835663531353063393935306462303964373536326537353133633234653531636163366634366634633231636234373561613937363166666466626434656138613531626465613432383037313466363538393630656336643139656539373237626339316635313665346466306665346264613762623035343161393462326334396636323938616132396337656130646662653635346632306437663164323239633066303262356535326137363031376237306439383232643533383166623966613166393361353861376338383632326631326462643363623937323363626132313639633337643538303939336333663666393065323039336331336130363132323334303064393731363031656262313631343332613966666333373033396562663537326364326566666635636562323539346236346462336261616431633734663532653938343938353964383363313238353465376263393764363432363464653931343735386333386438383739343132333937653263643534653431366234373962363331623830626633306266653062366239353564393066356362303435346361373531303963393938366330636536316165356566376534653433353036313432633633646235363862383634353139623463306636366137633161376661336538666431323231376666336665383164663830643138386232646334343833356132663332323733666133353139633531343764643233353763326161346336326461386238353232306535386130333565373662633133316634623734376632663731643263663933376431303832356138316533623963323136663962316134646431663239383463656635656363656265353530363662363061373263363063323864303336653766386635323131343735386638326366323330646636363930636364617267739f64617267316461726732ff6f736563726574734c6f636174696f6ec2582000000000000000000000000000000000000000000000000000000000000000016773656372657473430102030000000000000000000000000000000000000000000000000000")
+ require.NoError(t, err)
+ topic0, err := hex.DecodeString("bf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff")
+ require.NoError(t, err)
+ // Create a random requestID
+ topic1 := make([]byte, 32)
+ _, err = rand.Read(topic1)
+ require.NoError(t, err)
+ topic2, err := hex.DecodeString("000000000000000000000000665785a800593e8fa915208c1ce62f6e57fd75ba")
+ require.NoError(t, err)
+ return logpoller.Log{
+ Topics: [][]byte{topic0, topic1, topic2},
+ Data: data,
+ }
+}
+
func TestLogPollerWrapper_SingleSubscriberEmptyEvents(t *testing.T) {
t.Parallel()
lp, lpWrapper, client := setUp(t, 100_000) // check only once
+ lp.On("LatestBlock").Return(logpoller.LogPollerBlock{BlockNumber: int64(100)}, nil)
lp.On("Logs", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]logpoller.Log{}, nil)
client.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(addr(t, "01"), nil)
@@ -87,7 +106,8 @@ func TestLogPollerWrapper_SingleSubscriberEmptyEvents(t *testing.T) {
func TestLogPollerWrapper_ErrorOnZeroAddresses(t *testing.T) {
t.Parallel()
- _, lpWrapper, client := setUp(t, 100_000) // check only once
+ lp, lpWrapper, client := setUp(t, 100_000) // check only once
+ lp.On("LatestBlock").Return(logpoller.LogPollerBlock{BlockNumber: int64(100)}, nil)
client.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(addr(t, "00"), nil)
@@ -96,3 +116,96 @@ func TestLogPollerWrapper_ErrorOnZeroAddresses(t *testing.T) {
require.Error(t, err)
lpWrapper.Close()
}
+
+func TestLogPollerWrapper_LatestEvents_ReorgHandling(t *testing.T) {
+ t.Parallel()
+ lp, lpWrapper, client := setUp(t, 100_000)
+ lp.On("LatestBlock").Return(logpoller.LogPollerBlock{BlockNumber: int64(100)}, nil)
+ client.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(addr(t, "01"), nil)
+ lp.On("RegisterFilter", mock.Anything).Return(nil)
+ subscriber := newSubscriber(1)
+ lpWrapper.SubscribeToUpdates("mock_subscriber", subscriber)
+ mockedLog := getMockedRequestLog(t)
+ // All logPoller queries for responses return none
+ lp.On("Logs", mock.Anything, mock.Anything, functions_coordinator.FunctionsCoordinatorOracleResponse{}.Topic(), mock.Anything).Return([]logpoller.Log{}, nil)
+ // On the first logPoller query for requests, the request log appears
+ lp.On("Logs", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]logpoller.Log{mockedLog}, nil).Once()
+ // On the 2nd query, the request log disappears
+ lp.On("Logs", mock.Anything, mock.Anything, functions_coordinator.FunctionsCoordinatorOracleRequest{}.Topic(), mock.Anything).Return([]logpoller.Log{}, nil).Once()
+ // On the 3rd query, the original request log appears again
+ lp.On("Logs", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]logpoller.Log{mockedLog}, nil).Once()
+
+ require.NoError(t, lpWrapper.Start(testutils.Context(t)))
+ subscriber.updates.Wait()
+
+ oracleRequests, _, err := lpWrapper.LatestEvents()
+ require.NoError(t, err)
+ assert.Equal(t, 1, len(oracleRequests))
+ oracleRequests, _, err = lpWrapper.LatestEvents()
+ require.NoError(t, err)
+ assert.Equal(t, 0, len(oracleRequests))
+ require.NoError(t, err)
+ oracleRequests, _, err = lpWrapper.LatestEvents()
+ require.NoError(t, err)
+ assert.Equal(t, 0, len(oracleRequests))
+}
+
+func TestLogPollerWrapper_FilterPreviouslyDetectedEvents_TruncatesLogs(t *testing.T) {
+ t.Parallel()
+ _, lpWrapper, _ := setUp(t, 100_000)
+
+ inputLogs := make([]logpoller.Log, maxLogsToProcess+100)
+ for i := 0; i < 1100; i++ {
+ inputLogs[i] = getMockedRequestLog(t)
+ }
+
+ functionsLpWrapper := lpWrapper.(*logPollerWrapper)
+ mockedDetectedEvents := detectedEvents{isPreviouslyDetected: make(map[[32]byte]struct{})}
+ outputLogs := functionsLpWrapper.filterPreviouslyDetectedEvents(inputLogs, &mockedDetectedEvents, "request")
+
+ assert.Equal(t, maxLogsToProcess, len(outputLogs))
+ assert.Equal(t, 1000, len(mockedDetectedEvents.detectedEventsOrdered))
+ assert.Equal(t, 1000, len(mockedDetectedEvents.isPreviouslyDetected))
+}
+
+func TestLogPollerWrapper_FilterPreviouslyDetectedEvents_SkipsInvalidLog(t *testing.T) {
+ t.Parallel()
+ _, lpWrapper, _ := setUp(t, 100_000)
+ inputLogs := []logpoller.Log{getMockedRequestLog(t)}
+ inputLogs[0].Topics = [][]byte{[]byte("invalid topic")}
+ mockedDetectedEvents := detectedEvents{isPreviouslyDetected: make(map[[32]byte]struct{})}
+
+ functionsLpWrapper := lpWrapper.(*logPollerWrapper)
+ outputLogs := functionsLpWrapper.filterPreviouslyDetectedEvents(inputLogs, &mockedDetectedEvents, "request")
+
+ assert.Equal(t, 0, len(outputLogs))
+ assert.Equal(t, 0, len(mockedDetectedEvents.detectedEventsOrdered))
+ assert.Equal(t, 0, len(mockedDetectedEvents.isPreviouslyDetected))
+}
+
+func TestLogPollerWrapper_FilterPreviouslyDetectedEvents_FiltersPreviouslyDetectedEvent(t *testing.T) {
+ t.Parallel()
+ _, lpWrapper, _ := setUp(t, 100_000)
+ mockedRequestLog := getMockedRequestLog(t)
+ inputLogs := []logpoller.Log{mockedRequestLog}
+ var mockedRequestId [32]byte
+ copy(mockedRequestId[:], mockedRequestLog.Topics[1])
+
+ mockedDetectedEvents := detectedEvents{
+ isPreviouslyDetected: make(map[[32]byte]struct{}),
+ detectedEventsOrdered: make([]detectedEvent, 1),
+ }
+ mockedDetectedEvents.isPreviouslyDetected[mockedRequestId] = struct{}{}
+ mockedDetectedEvents.detectedEventsOrdered[0] = detectedEvent{
+ requestId: mockedRequestId,
+ timeDetected: time.Now().Add(-time.Second * time.Duration(logPollerCacheDurationSecDefault+1)),
+ }
+
+ functionsLpWrapper := lpWrapper.(*logPollerWrapper)
+ outputLogs := functionsLpWrapper.filterPreviouslyDetectedEvents(inputLogs, &mockedDetectedEvents, "request")
+
+ assert.Equal(t, 0, len(outputLogs))
+ // Ensure that expired events are removed from the cache
+ assert.Equal(t, 0, len(mockedDetectedEvents.detectedEventsOrdered))
+ assert.Equal(t, 0, len(mockedDetectedEvents.isPreviouslyDetected))
+}
From 45844de10fcc4a31436cf8f9f84ab555e2a0f044 Mon Sep 17 00:00:00 2001
From: David Cauchi <13139524+davidcauchi@users.noreply.github.com>
Date: Wed, 1 Nov 2023 15:06:12 +0100
Subject: [PATCH 046/327] Add base goerli benchmark option (#11089)
* Add base goerli benchmark option
* Add config
* Add to op stack deployer
* Add FlatFeeMicroLink
---
.github/workflows/automation-benchmark-tests.yml | 1 +
integration-tests/benchmark/keeper_test.go | 7 +++++++
integration-tests/contracts/contract_deployer.go | 2 ++
3 files changed, 10 insertions(+)
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index f23102f1ee..5c4dced934 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -24,6 +24,7 @@ on:
- OPTIMISM_GOERLI
- MUMBAI
- SEPOLIA
+ - BASE_GOERLI
TestInputs:
description: TestInputs
required: false
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index 6fbf929e47..55f769e73b 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -161,6 +161,7 @@ func TestAutomationBenchmark(t *testing.T) {
RegistryVersions: registryVersions,
KeeperRegistrySettings: &contracts.KeeperRegistrySettings{
PaymentPremiumPPB: uint32(0),
+ FlatFeeMicroLINK: uint32(40000),
BlockCountPerTurn: big.NewInt(100),
CheckGasLimit: uint32(45_000_000), //45M
StalenessSeconds: big.NewInt(90_000),
@@ -282,6 +283,12 @@ var networkConfig = map[string]NetworkConfig{
deltaStage: time.Duration(0),
funding: big.NewFloat(ChainlinkNodeFunding),
},
+ "BaseGoerli": {
+ upkeepSLA: int64(60),
+ blockTime: 2 * time.Second,
+ deltaStage: 20 * time.Second,
+ funding: big.NewFloat(ChainlinkNodeFunding),
+ },
}
func getEnv(key, fallback string) string {
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index 710422891c..94f6c73386 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -883,6 +883,8 @@ func (e *EthereumContractDeployer) DeployKeeperRegistry(
//Optimism payment model
case big.NewInt(420):
mode = uint8(2)
+ case big.NewInt(84531):
+ mode = uint8(2)
default:
mode = uint8(0)
}
From fda43935a2582cbe75d38088ef523bcf6091841f Mon Sep 17 00:00:00 2001
From: Lei
Date: Wed, 1 Nov 2023 12:40:55 -0700
Subject: [PATCH 047/327] add an empty index.html under core/web/assets to
avoid running make commands (#11114)
---
.github/workflows/automation-ondemand-tests.yml | 2 +-
.github/workflows/integration-chaos-tests.yml | 2 +-
.github/workflows/integration-tests.yml | 8 ++++----
GNUmakefile | 4 ----
core/web/assets/index.html | 0
integration-tests/Makefile | 2 +-
6 files changed, 7 insertions(+), 11 deletions(-)
create mode 100644 core/web/assets/index.html
diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml
index ac0e34e083..fb8adcfdb6 100644
--- a/.github/workflows/automation-ondemand-tests.yml
+++ b/.github/workflows/automation-ondemand-tests.yml
@@ -182,7 +182,7 @@ jobs:
UPGRADE_VERSION: ${{ steps.determine-build.outputs.upgrade_version }}
UPGRADE_IMAGE: ${{ steps.determine-build.outputs.upgrade_image }}
with:
- test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 60m -count=1 -json -test.parallel=${{ matrix.tests.nodes }} ${{ matrix.tests.command }} 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 60m -count=1 -json -test.parallel=${{ matrix.tests.nodes }} ${{ matrix.tests.command }} 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ steps.determine-build.outputs.image }}
cl_image_tag: ${{ steps.determine-build.outputs.version }}
diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml
index 648d5f9daa..4ad985e915 100644
--- a/.github/workflows/integration-chaos-tests.yml
+++ b/.github/workflows/integration-chaos-tests.yml
@@ -111,7 +111,7 @@ jobs:
- name: Run Tests
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
with:
- test_command_to_run: make test_need_operator_assets && cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 ./chaos 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 ./chaos 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 5074fc35b9..b66ab58d55 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -218,7 +218,7 @@ jobs:
PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }}
PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
with:
- test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
@@ -417,7 +417,7 @@ jobs:
PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }}
PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
with:
- test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}${{ matrix.product.tag_suffix }}
@@ -574,7 +574,7 @@ jobs:
- name: Run Migration Tests
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
with:
- test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 30m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestfmt
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 }}
@@ -935,7 +935,7 @@ jobs:
PYROSCOPE_ENVIRONMENT: ci-smoke-ocr-evm-${{ matrix.testnet }} # TODO: Only for OCR for now
PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
with:
- test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/ocr_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/ocr_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
diff --git a/GNUmakefile b/GNUmakefile
index 957df96ce4..32f74e285e 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -127,10 +127,6 @@ telemetry-protobuf: $(telemetry-protobuf) ## Generate telemetry protocol buffers
--go-wsrpc_opt=paths=source_relative \
./core/services/synchronization/telem/*.proto
-.PHONY: test_need_operator_assets
-test_need_operator_assets: ## Add blank file in web assets if operator ui has not been built
- [ -f "./core/web/assets/index.html" ] || mkdir ./core/web/assets && touch ./core/web/assets/index.html
-
.PHONY: config-docs
config-docs: ## Generate core node configuration documentation
go run ./core/config/docs/cmd/generate -o ./docs/
diff --git a/core/web/assets/index.html b/core/web/assets/index.html
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/integration-tests/Makefile b/integration-tests/Makefile
index f26518c007..257331afcf 100644
--- a/integration-tests/Makefile
+++ b/integration-tests/Makefile
@@ -118,7 +118,7 @@ test_chaos_verbose: ## Run all smoke tests with verbose logging
# Performance
.PHONY: test_perf
-test_perf: test_need_operator_assets ## Run core node performance tests.
+test_perf: ## Run core node performance tests.
TEST_LOG_LEVEL="disabled" \
SELECTED_NETWORKS="SIMULATED,SIMULATED_1,SIMULATED_2" \
go test -timeout 1h -count=1 -json $(args) ./performance 2>&1 | tee /tmp/gotest.log | gotestfmt
From 08c9f89bcabbde28d40349e010f629ea840bfd9a Mon Sep 17 00:00:00 2001
From: Dimitris Grigoriou
Date: Wed, 1 Nov 2023 22:41:45 +0200
Subject: [PATCH 048/327] Introduce generalized multi node client (#10907)
* Introduce generalized multi node client
* Export EVM RPC client
* Unexport clientAPI interface
* Add BlockDifficulty to mocks
* Unexport node state
* Rename error parsing
* Nit fixes
* Rename error classification functions
* Update NodeSelection names
* Deprecate StartStopOnce
---
common/chains/client/models.go | 22 +
common/client/multi_node.go | 669 +++++++++++
common/client/node.go | 282 +++++
common/client/node_fsm.go | 266 +++++
common/client/node_lifecycle.go | 431 +++++++
common/client/node_selector_highest_head.go | 41 +
common/client/node_selector_priority_level.go | 129 ++
common/client/node_selector_round_robin.go | 50 +
.../client/node_selector_total_difficulty.go | 54 +
common/client/send_only_node.go | 183 +++
common/client/send_only_node_lifecycle.go | 66 ++
common/client/types.go | 133 +++
common/headtracker/types/mocks/head.go | 17 +
common/types/head.go | 6 +
common/types/mocks/head.go | 17 +
common/types/receipt.go | 14 +
core/chains/evm/chain.go | 18 +
core/chains/evm/client/chain_client.go | 274 +++++
core/chains/evm/client/client.go | 2 +-
core/chains/evm/client/client_test.go | 442 ++++---
core/chains/evm/client/errors.go | 14 +-
core/chains/evm/client/helpers_test.go | 65 +
core/chains/evm/client/rpc_client.go | 1046 +++++++++++++++++
core/chains/evm/txmgr/client.go | 2 +-
core/chains/evm/types/models.go | 4 +
25 files changed, 4110 insertions(+), 137 deletions(-)
create mode 100644 common/client/multi_node.go
create mode 100644 common/client/node.go
create mode 100644 common/client/node_fsm.go
create mode 100644 common/client/node_lifecycle.go
create mode 100644 common/client/node_selector_highest_head.go
create mode 100644 common/client/node_selector_priority_level.go
create mode 100644 common/client/node_selector_round_robin.go
create mode 100644 common/client/node_selector_total_difficulty.go
create mode 100644 common/client/send_only_node.go
create mode 100644 common/client/send_only_node_lifecycle.go
create mode 100644 common/client/types.go
create mode 100644 common/types/receipt.go
create mode 100644 core/chains/evm/client/chain_client.go
create mode 100644 core/chains/evm/client/rpc_client.go
diff --git a/common/chains/client/models.go b/common/chains/client/models.go
index ebe7bb7576..bd974f901f 100644
--- a/common/chains/client/models.go
+++ b/common/chains/client/models.go
@@ -1,5 +1,9 @@
package client
+import (
+ "fmt"
+)
+
type SendTxReturnCode int
// SendTxReturnCode is a generalized client error that dictates what should be the next action, depending on the RPC error response.
@@ -15,3 +19,21 @@ const (
ExceedsMaxFee // Attempt's fee was higher than the node's limit and got rejected.
FeeOutOfValidRange // This error is returned when we use a fee price suggested from an RPC, but the network rejects the attempt due to an invalid range(mostly used by L2 chains). Retry by requesting a new suggested fee price.
)
+
+type NodeTier int
+
+const (
+ Primary = NodeTier(iota)
+ Secondary
+)
+
+func (n NodeTier) String() string {
+ switch n {
+ case Primary:
+ return "primary"
+ case Secondary:
+ return "secondary"
+ default:
+ return fmt.Sprintf("NodeTier(%d)", n)
+ }
+}
diff --git a/common/client/multi_node.go b/common/client/multi_node.go
new file mode 100644
index 0000000000..0da3b89076
--- /dev/null
+++ b/common/client/multi_node.go
@@ -0,0 +1,669 @@
+package client
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+ "sync"
+ "time"
+
+ "github.com/pkg/errors"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
+ "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+var (
+ // PromMultiNodeRPCNodeStates reports current RPC node state
+ PromMultiNodeRPCNodeStates = promauto.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "multi_node_states",
+ Help: "The number of RPC nodes currently in the given state for the given chain",
+ }, []string{"network", "chainId", "state"})
+ ErroringNodeError = fmt.Errorf("no live nodes available")
+)
+
+const (
+ NodeSelectionModeHighestHead = "HighestHead"
+ NodeSelectionModeRoundRobin = "RoundRobin"
+ NodeSelectionModeTotalDifficulty = "TotalDifficulty"
+ NodeSelectionModePriorityLevel = "PriorityLevel"
+)
+
+type NodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] interface {
+ // Select returns a Node, or nil if none can be selected.
+ // Implementation must be thread-safe.
+ Select() Node[CHAIN_ID, HEAD, RPC]
+ // Name returns the strategy name, e.g. "HighestHead" or "RoundRobin"
+ Name() string
+}
+
+// MultiNode is a generalized multi node client interface that includes methods to interact with different chains.
+// It also handles multiple node RPC connections simultaneously.
+type MultiNode[
+ CHAIN_ID types.ID,
+ SEQ types.Sequence,
+ ADDR types.Hashable,
+ BLOCK_HASH types.Hashable,
+ TX any,
+ TX_HASH types.Hashable,
+ EVENT any,
+ EVENT_OPS any,
+ TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
+ FEE feetypes.Fee,
+ HEAD types.Head[BLOCK_HASH],
+ RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD],
+] interface {
+ clientAPI[
+ CHAIN_ID,
+ SEQ,
+ ADDR,
+ BLOCK_HASH,
+ TX,
+ TX_HASH,
+ EVENT,
+ EVENT_OPS,
+ TX_RECEIPT,
+ FEE,
+ HEAD,
+ ]
+ Close() error
+ NodeStates() map[string]string
+ SelectNodeRPC() (RPC_CLIENT, error)
+
+ BatchCallContextAll(ctx context.Context, b []any) error
+ ConfiguredChainID() CHAIN_ID
+ IsL2() bool
+}
+
+type multiNode[
+ CHAIN_ID types.ID,
+ SEQ types.Sequence,
+ ADDR types.Hashable,
+ BLOCK_HASH types.Hashable,
+ TX any,
+ TX_HASH types.Hashable,
+ EVENT any,
+ EVENT_OPS any,
+ TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
+ FEE feetypes.Fee,
+ HEAD types.Head[BLOCK_HASH],
+ RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD],
+] struct {
+ services.StateMachine
+ nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT]
+ sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT]
+ chainID CHAIN_ID
+ chainType config.ChainType
+ logger logger.Logger
+ selectionMode string
+ noNewHeadsThreshold time.Duration
+ nodeSelector NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT]
+ leaseDuration time.Duration
+ leaseTicker *time.Ticker
+ chainFamily string
+
+ activeMu sync.RWMutex
+ activeNode Node[CHAIN_ID, HEAD, RPC_CLIENT]
+
+ chStop utils.StopChan
+ wg sync.WaitGroup
+
+ sendOnlyErrorParser func(err error) client.SendTxReturnCode
+}
+
+func NewMultiNode[
+ CHAIN_ID types.ID,
+ SEQ types.Sequence,
+ ADDR types.Hashable,
+ BLOCK_HASH types.Hashable,
+ TX any,
+ TX_HASH types.Hashable,
+ EVENT any,
+ EVENT_OPS any,
+ TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
+ FEE feetypes.Fee,
+ HEAD types.Head[BLOCK_HASH],
+ RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD],
+](
+ logger logger.Logger,
+ selectionMode string,
+ leaseDuration time.Duration,
+ noNewHeadsThreshold time.Duration,
+ nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT],
+ sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT],
+ chainID CHAIN_ID,
+ chainType config.ChainType,
+ chainFamily string,
+ sendOnlyErrorParser func(err error) client.SendTxReturnCode,
+) MultiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT] {
+ nodeSelector := func() NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] {
+ switch selectionMode {
+ case NodeSelectionModeHighestHead:
+ return NewHighestHeadNodeSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
+ case NodeSelectionModeRoundRobin:
+ return NewRoundRobinSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
+ case NodeSelectionModeTotalDifficulty:
+ return NewTotalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
+ case NodeSelectionModePriorityLevel:
+ return NewPriorityLevelNodeSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
+ default:
+ panic(fmt.Sprintf("unsupported NodeSelectionMode: %s", selectionMode))
+ }
+ }()
+
+ lggr := logger.Named("MultiNode").With("chainID", chainID.String())
+
+ c := &multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]{
+ nodes: nodes,
+ sendonlys: sendonlys,
+ chainID: chainID,
+ chainType: chainType,
+ logger: lggr,
+ selectionMode: selectionMode,
+ noNewHeadsThreshold: noNewHeadsThreshold,
+ nodeSelector: nodeSelector,
+ chStop: make(chan struct{}),
+ leaseDuration: leaseDuration,
+ chainFamily: chainFamily,
+ sendOnlyErrorParser: sendOnlyErrorParser,
+ }
+
+ c.logger.Debugf("The MultiNode is configured to use NodeSelectionMode: %s", selectionMode)
+
+ return c
+}
+
+// Dial starts every node in the pool
+//
+// Nodes handle their own redialing and runloops, so this function does not
+// return any error if the nodes aren't available
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) Dial(ctx context.Context) error {
+ return c.StartOnce("MultiNode", func() (merr error) {
+ if len(c.nodes) == 0 {
+ return errors.Errorf("no available nodes for chain %s", c.chainID.String())
+ }
+ var ms services.MultiStart
+ for _, n := range c.nodes {
+ if n.ConfiguredChainID().String() != c.chainID.String() {
+ return ms.CloseBecause(errors.Errorf("node %s has configured chain ID %s which does not match multinode configured chain ID of %s", n.String(), n.ConfiguredChainID().String(), c.chainID.String()))
+ }
+ rawNode, ok := n.(*node[CHAIN_ID, HEAD, RPC_CLIENT])
+ if ok {
+ // This is a bit hacky but it allows the node to be aware of
+ // pool state and prevent certain state transitions that might
+ // otherwise leave no nodes available. It is better to have one
+ // node in a degraded state than no nodes at all.
+ rawNode.nLiveNodes = c.nLiveNodes
+ }
+ // node will handle its own redialing and automatic recovery
+ if err := ms.Start(ctx, n); err != nil {
+ return err
+ }
+ }
+ for _, s := range c.sendonlys {
+ if s.ConfiguredChainID().String() != c.chainID.String() {
+ return ms.CloseBecause(errors.Errorf("sendonly node %s has configured chain ID %s which does not match multinode configured chain ID of %s", s.String(), s.ConfiguredChainID().String(), c.chainID.String()))
+ }
+ if err := ms.Start(ctx, s); err != nil {
+ return err
+ }
+ }
+ c.wg.Add(1)
+ go c.runLoop()
+
+ if c.leaseDuration.Seconds() > 0 && c.selectionMode != NodeSelectionModeRoundRobin {
+ c.logger.Infof("The MultiNode will switch to best node every %s", c.leaseDuration.String())
+ c.wg.Add(1)
+ go c.checkLeaseLoop()
+ } else {
+ c.logger.Info("Best node switching is disabled")
+ }
+
+ return nil
+ })
+}
+
+// Close tears down the MultiNode and closes all nodes
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) Close() error {
+ return c.StopOnce("MultiNode", func() error {
+ close(c.chStop)
+ c.wg.Wait()
+
+ return services.CloseAll(services.MultiCloser(c.nodes), services.MultiCloser(c.sendonlys))
+ })
+}
+
+// SelectNodeRPC returns an RPC of an active node. If there are no active nodes it returns an error.
+// Call this method from your chain-specific client implementation to access any chain-specific rpc calls.
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) SelectNodeRPC() (rpc RPC_CLIENT, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return rpc, err
+ }
+ return n.RPC(), nil
+
+}
+
+// selectNode returns the active Node, if it is still nodeStateAlive, otherwise it selects a new one from the NodeSelector.
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) selectNode() (node Node[CHAIN_ID, HEAD, RPC_CLIENT], err error) {
+ c.activeMu.RLock()
+ node = c.activeNode
+ c.activeMu.RUnlock()
+ if node != nil && node.State() == nodeStateAlive {
+ return // still alive
+ }
+
+ // select a new one
+ c.activeMu.Lock()
+ defer c.activeMu.Unlock()
+ node = c.activeNode
+ if node != nil && node.State() == nodeStateAlive {
+ return // another goroutine beat us here
+ }
+
+ c.activeNode = c.nodeSelector.Select()
+
+ if c.activeNode == nil {
+ c.logger.Criticalw("No live RPC nodes available", "NodeSelectionMode", c.nodeSelector.Name())
+ errmsg := fmt.Errorf("no live nodes available for chain %s", c.chainID.String())
+ c.SvcErrBuffer.Append(errmsg)
+ err = ErroringNodeError
+ }
+
+ return c.activeNode, err
+}
+
+// nLiveNodes returns the number of currently alive nodes, as well as the highest block number and greatest total difficulty.
+// totalDifficulty will be 0 if all nodes return nil.
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) nLiveNodes() (nLiveNodes int, blockNumber int64, totalDifficulty *utils.Big) {
+ totalDifficulty = utils.NewBigI(0)
+ for _, n := range c.nodes {
+ if s, num, td := n.StateAndLatest(); s == nodeStateAlive {
+ nLiveNodes++
+ if num > blockNumber {
+ blockNumber = num
+ }
+ if td != nil && td.Cmp(totalDifficulty) > 0 {
+ totalDifficulty = td
+ }
+ }
+ }
+ return
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) checkLease() {
+ bestNode := c.nodeSelector.Select()
+ for _, n := range c.nodes {
+ // Terminate client subscriptions. Services are responsible for reconnecting, which will be routed to the new
+ // best node. Only terminate connections with more than 1 subscription to account for the aliveLoop subscription
+ if n.State() == nodeStateAlive && n != bestNode && n.SubscribersCount() > 1 {
+ c.logger.Infof("Switching to best node from %q to %q", n.String(), bestNode.String())
+ n.UnsubscribeAllExceptAliveLoop()
+ }
+ }
+
+ c.activeMu.Lock()
+ if bestNode != c.activeNode {
+ c.activeNode = bestNode
+ }
+ c.activeMu.Unlock()
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) checkLeaseLoop() {
+ defer c.wg.Done()
+ c.leaseTicker = time.NewTicker(c.leaseDuration)
+ defer c.leaseTicker.Stop()
+
+ for {
+ select {
+ case <-c.leaseTicker.C:
+ c.checkLease()
+ case <-c.chStop:
+ return
+ }
+ }
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) runLoop() {
+ defer c.wg.Done()
+
+ c.report()
+
+ // Prometheus' default interval is 15s, set this to under 7.5s to avoid
+ // aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency)
+ reportInterval := 6500 * time.Millisecond
+ monitor := time.NewTicker(utils.WithJitter(reportInterval))
+ defer monitor.Stop()
+
+ for {
+ select {
+ case <-monitor.C:
+ c.report()
+ case <-c.chStop:
+ return
+ }
+ }
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) report() {
+ type nodeWithState struct {
+ Node string
+ State string
+ }
+
+ var total, dead int
+ counts := make(map[nodeState]int)
+ nodeStates := make([]nodeWithState, len(c.nodes))
+ for i, n := range c.nodes {
+ state := n.State()
+ nodeStates[i] = nodeWithState{n.String(), state.String()}
+ total++
+ if state != nodeStateAlive {
+ dead++
+ }
+ counts[state]++
+ }
+ for _, state := range allNodeStates {
+ count := counts[state]
+ PromMultiNodeRPCNodeStates.WithLabelValues(c.chainFamily, c.chainID.String(), state.String()).Set(float64(count))
+ }
+
+ live := total - dead
+ c.logger.Tracew(fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodeStates)
+ if total == dead {
+ rerr := fmt.Errorf("no primary nodes available: 0/%d nodes are alive", total)
+ c.logger.Criticalw(rerr.Error(), "nodeStates", nodeStates)
+ c.SvcErrBuffer.Append(rerr)
+ } else if dead > 0 {
+ c.logger.Errorw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodeStates)
+ }
+}
+
+// ClientAPI methods
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) BalanceAt(ctx context.Context, account ADDR, blockNumber *big.Int) (*big.Int, error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return nil, err
+ }
+ return n.RPC().BalanceAt(ctx, account, blockNumber)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) BatchCallContext(ctx context.Context, b []any) error {
+ n, err := c.selectNode()
+ if err != nil {
+ return err
+ }
+ return n.RPC().BatchCallContext(ctx, b)
+}
+
+// BatchCallContextAll calls BatchCallContext for every single node including
+// sendonlys.
+// CAUTION: This should only be used for mass re-transmitting transactions, it
+// might have unexpected effects to use it for anything else.
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) BatchCallContextAll(ctx context.Context, b []any) error {
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ main, selectionErr := c.selectNode()
+ var all []SendOnlyNode[CHAIN_ID, RPC_CLIENT]
+ for _, n := range c.nodes {
+ all = append(all, n)
+ }
+ all = append(all, c.sendonlys...)
+ for _, n := range all {
+ if n == main {
+ // main node is used at the end for the return value
+ continue
+ }
+ // Parallel call made to all other nodes with ignored return value
+ wg.Add(1)
+ go func(n SendOnlyNode[CHAIN_ID, RPC_CLIENT]) {
+ defer wg.Done()
+ err := n.RPC().BatchCallContext(ctx, b)
+ if err != nil {
+ c.logger.Debugw("Secondary node BatchCallContext failed", "err", err)
+ } else {
+ c.logger.Trace("Secondary node BatchCallContext success")
+ }
+ }(n)
+ }
+
+ if selectionErr != nil {
+ return selectionErr
+ }
+ return main.RPC().BatchCallContext(ctx, b)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) BlockByHash(ctx context.Context, hash BLOCK_HASH) (h HEAD, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return h, err
+ }
+ return n.RPC().BlockByHash(ctx, hash)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) BlockByNumber(ctx context.Context, number *big.Int) (h HEAD, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return h, err
+ }
+ return n.RPC().BlockByNumber(ctx, number)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
+ n, err := c.selectNode()
+ if err != nil {
+ return err
+ }
+ return n.RPC().CallContext(ctx, result, method, args...)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) CallContract(
+ ctx context.Context,
+ attempt interface{},
+ blockNumber *big.Int,
+) (rpcErr []byte, extractErr error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return rpcErr, err
+ }
+ return n.RPC().CallContract(ctx, attempt, blockNumber)
+}
+
+// ChainID makes a direct RPC call. In most cases it should be better to use the configured chain id instead by
+// calling ConfiguredChainID.
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) ChainID(ctx context.Context) (id CHAIN_ID, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return id, err
+ }
+ return n.RPC().ChainID(ctx)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) ChainType() config.ChainType {
+ return c.chainType
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) (code []byte, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return code, err
+ }
+ return n.RPC().CodeAt(ctx, account, blockNumber)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) ConfiguredChainID() CHAIN_ID {
+ return c.chainID
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) EstimateGas(ctx context.Context, call any) (gas uint64, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return gas, err
+ }
+ return n.RPC().EstimateGas(ctx, call)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) FilterEvents(ctx context.Context, query EVENT_OPS) (e []EVENT, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return e, err
+ }
+ return n.RPC().FilterEvents(ctx, query)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) IsL2() bool {
+ return c.ChainType().IsL2()
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) LatestBlockHeight(ctx context.Context) (h *big.Int, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return h, err
+ }
+ return n.RPC().LatestBlockHeight(ctx)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) LINKBalance(ctx context.Context, accountAddress ADDR, linkAddress ADDR) (b *assets.Link, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return b, err
+ }
+ return n.RPC().LINKBalance(ctx, accountAddress, linkAddress)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) NodeStates() (states map[string]string) {
+ states = make(map[string]string)
+ for _, n := range c.nodes {
+ states[n.Name()] = n.State().String()
+ }
+ for _, s := range c.sendonlys {
+ states[s.Name()] = s.State().String()
+ }
+ return
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) PendingSequenceAt(ctx context.Context, addr ADDR) (s SEQ, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return s, err
+ }
+ return n.RPC().PendingSequenceAt(ctx, addr)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) SendEmptyTransaction(
+ ctx context.Context,
+ newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt any, err error),
+ seq SEQ,
+ gasLimit uint32,
+ fee FEE,
+ fromAddress ADDR,
+) (txhash string, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return txhash, err
+ }
+ return n.RPC().SendEmptyTransaction(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) SendTransaction(ctx context.Context, tx TX) error {
+ main, nodeError := c.selectNode()
+ var all []SendOnlyNode[CHAIN_ID, RPC_CLIENT]
+ for _, n := range c.nodes {
+ all = append(all, n)
+ }
+ all = append(all, c.sendonlys...)
+ for _, n := range all {
+ if n == main {
+ // main node is used at the end for the return value
+ continue
+ }
+ // Parallel send to all other nodes with ignored return value
+ // Async - we do not want to block the main thread with secondary nodes
+ // in case they are unreliable/slow.
+ // It is purely a "best effort" send.
+ // Resource is not unbounded because the default context has a timeout.
+ ok := c.IfNotStopped(func() {
+ // Must wrap inside IfNotStopped to avoid waitgroup racing with Close
+ c.wg.Add(1)
+ go func(n SendOnlyNode[CHAIN_ID, RPC_CLIENT]) {
+ defer c.wg.Done()
+
+ txErr := n.RPC().SendTransaction(ctx, tx)
+ c.logger.Debugw("Sendonly node sent transaction", "name", n.String(), "tx", tx, "err", txErr)
+ sendOnlyError := c.sendOnlyErrorParser(txErr)
+ if sendOnlyError != client.Successful {
+ c.logger.Warnw("RPC returned error", "name", n.String(), "tx", tx, "err", txErr)
+ }
+ }(n)
+ })
+ if !ok {
+ c.logger.Debug("Cannot send transaction on sendonly node; MultiNode is stopped", "node", n.String())
+ }
+ }
+ if nodeError != nil {
+ return nodeError
+ }
+ return main.RPC().SendTransaction(ctx, tx)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) SequenceAt(ctx context.Context, account ADDR, blockNumber *big.Int) (s SEQ, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return s, err
+ }
+ return n.RPC().SequenceAt(ctx, account, blockNumber)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) SimulateTransaction(ctx context.Context, tx TX) error {
+ n, err := c.selectNode()
+ if err != nil {
+ return err
+ }
+ return n.RPC().SimulateTransaction(ctx, tx)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (s types.Subscription, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return s, err
+ }
+ return n.RPC().Subscribe(ctx, channel, args...)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) TokenBalance(ctx context.Context, account ADDR, tokenAddr ADDR) (b *big.Int, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return b, err
+ }
+ return n.RPC().TokenBalance(ctx, account, tokenAddr)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) TransactionByHash(ctx context.Context, txHash TX_HASH) (tx TX, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return tx, err
+ }
+ return n.RPC().TransactionByHash(ctx, txHash)
+}
+
+func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) TransactionReceipt(ctx context.Context, txHash TX_HASH) (txr TX_RECEIPT, err error) {
+ n, err := c.selectNode()
+ if err != nil {
+ return txr, err
+ }
+ return n.RPC().TransactionReceipt(ctx, txHash)
+}
diff --git a/common/client/node.go b/common/client/node.go
new file mode 100644
index 0000000000..71b34452f0
--- /dev/null
+++ b/common/client/node.go
@@ -0,0 +1,282 @@
+package client
+
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "sync"
+ "time"
+
+ "github.com/pkg/errors"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
+ "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+const QueryTimeout = 10 * time.Second
+
+var errInvalidChainID = errors.New("invalid chain id")
+
+var (
+ promPoolRPCNodeVerifies = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_verifies",
+ Help: "The total number of chain ID verifications for the given RPC node",
+ }, []string{"network", "chainID", "nodeName"})
+ promPoolRPCNodeVerifiesFailed = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_verifies_failed",
+ Help: "The total number of failed chain ID verifications for the given RPC node",
+ }, []string{"network", "chainID", "nodeName"})
+ promPoolRPCNodeVerifiesSuccess = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_verifies_success",
+ Help: "The total number of successful chain ID verifications for the given RPC node",
+ }, []string{"network", "chainID", "nodeName"})
+)
+
+type NodeConfig interface {
+ PollFailureThreshold() uint32
+ PollInterval() time.Duration
+ SelectionMode() string
+ SyncThreshold() uint32
+}
+
+type Node[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] interface {
+ // State returns nodeState
+ State() nodeState
+ // StateAndLatest returns nodeState with the latest received block number & total difficulty.
+ StateAndLatest() (nodeState, int64, *utils.Big)
+ // Name is a unique identifier for this node.
+ Name() string
+ String() string
+ RPC() RPC
+ SubscribersCount() int32
+ UnsubscribeAllExceptAliveLoop()
+ ConfiguredChainID() CHAIN_ID
+ Order() int32
+ Start(context.Context) error
+ Close() error
+}
+
+type node[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] struct {
+ services.StateMachine
+ lfcLog logger.Logger
+ name string
+ id int32
+ chainID CHAIN_ID
+ nodePoolCfg NodeConfig
+ noNewHeadsThreshold time.Duration
+ order int32
+ chainFamily string
+
+ ws url.URL
+ http *url.URL
+
+ rpc RPC
+
+ stateMu sync.RWMutex // protects state* fields
+ state nodeState
+ // Each node is tracking the last received head number and total difficulty
+ stateLatestBlockNumber int64
+ stateLatestTotalDifficulty *utils.Big
+
+ // nodeCtx is the node lifetime's context
+ nodeCtx context.Context
+ // cancelNodeCtx cancels nodeCtx when stopping the node
+ cancelNodeCtx context.CancelFunc
+ // wg waits for subsidiary goroutines
+ wg sync.WaitGroup
+
+ // nLiveNodes is a passed in function that allows this node to:
+ // 1. see how many live nodes there are in total, so we can prevent the last alive node in a pool from being
+ // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all.
+ // 2. compare against the highest head (by number or difficulty) to ensure we don't fall behind too far.
+ nLiveNodes func() (count int, blockNumber int64, totalDifficulty *utils.Big)
+}
+
+func NewNode[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](
+ nodeCfg NodeConfig,
+ noNewHeadsThreshold time.Duration,
+ lggr logger.Logger,
+ wsuri url.URL,
+ httpuri *url.URL,
+ name string,
+ id int32,
+ chainID CHAIN_ID,
+ nodeOrder int32,
+ rpc RPC,
+ chainFamily string,
+) Node[CHAIN_ID, HEAD, RPC] {
+ n := new(node[CHAIN_ID, HEAD, RPC])
+ n.name = name
+ n.id = id
+ n.chainID = chainID
+ n.nodePoolCfg = nodeCfg
+ n.noNewHeadsThreshold = noNewHeadsThreshold
+ n.ws = wsuri
+ n.order = nodeOrder
+ if httpuri != nil {
+ n.http = httpuri
+ }
+ n.nodeCtx, n.cancelNodeCtx = context.WithCancel(context.Background())
+ lggr = lggr.Named("Node").With(
+ "nodeTier", client.Primary.String(),
+ "nodeName", name,
+ "node", n.String(),
+ "chainID", chainID,
+ "nodeOrder", n.order,
+ )
+ n.lfcLog = lggr.Named("Lifecycle")
+ n.stateLatestBlockNumber = -1
+ n.rpc = rpc
+ n.chainFamily = chainFamily
+ return n
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) String() string {
+ s := fmt.Sprintf("(%s)%s:%s", client.Primary.String(), n.name, n.ws.String())
+ if n.http != nil {
+ s = s + fmt.Sprintf(":%s", n.http.String())
+ }
+ return s
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() (chainID CHAIN_ID) {
+ return n.chainID
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) Name() string {
+ return n.name
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) RPC() RPC {
+ return n.rpc
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) SubscribersCount() int32 {
+ return n.rpc.SubscribersCount()
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() {
+ n.rpc.UnsubscribeAllExceptAliveLoop()
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) Close() error {
+ return n.StopOnce(n.name, func() error {
+ defer func() {
+ n.wg.Wait()
+ n.rpc.Close()
+ }()
+
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+
+ n.cancelNodeCtx()
+ n.state = nodeStateClosed
+ return nil
+ })
+}
+
+// Start dials and verifies the node
+// Should only be called once in a node's lifecycle
+// Return value is necessary to conform to interface but this will never
+// actually return an error.
+func (n *node[CHAIN_ID, HEAD, RPC]) Start(startCtx context.Context) error {
+ return n.StartOnce(n.name, func() error {
+ n.start(startCtx)
+ return nil
+ })
+}
+
+// start initially dials the node and verifies chain ID
+// This spins off lifecycle goroutines.
+// Not thread-safe.
+// Node lifecycle is synchronous: only one goroutine should be running at a
+// time.
+func (n *node[CHAIN_ID, HEAD, RPC]) start(startCtx context.Context) {
+ if n.state != nodeStateUndialed {
+ panic(fmt.Sprintf("cannot dial node with state %v", n.state))
+ }
+
+ if err := n.rpc.Dial(startCtx); err != nil {
+ n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err)
+ n.declareUnreachable()
+ return
+ }
+ n.setState(nodeStateDialed)
+
+ if err := n.verify(startCtx); errors.Is(err, errInvalidChainID) {
+ n.lfcLog.Errorw("Verify failed: Node has the wrong chain ID", "err", err)
+ n.declareInvalidChainID()
+ return
+ } else if err != nil {
+ n.lfcLog.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err)
+ n.declareUnreachable()
+ return
+ }
+
+ n.declareAlive()
+}
+
+// verify checks that all connections to eth nodes match the given chain ID
+// Not thread-safe
+// Pure verify: does not mutate node "state" field.
+func (n *node[CHAIN_ID, HEAD, RPC]) verify(callerCtx context.Context) (err error) {
+ promPoolRPCNodeVerifies.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc()
+ promFailed := func() {
+ promPoolRPCNodeVerifiesFailed.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc()
+ }
+
+ st := n.State()
+ switch st {
+ case nodeStateDialed, nodeStateOutOfSync, nodeStateInvalidChainID:
+ default:
+ panic(fmt.Sprintf("cannot verify node in state %v", st))
+ }
+
+ var chainID CHAIN_ID
+ if chainID, err = n.rpc.ChainID(callerCtx); err != nil {
+ promFailed()
+ return errors.Wrapf(err, "failed to verify chain ID for node %s", n.name)
+ } else if chainID.String() != n.chainID.String() {
+ promFailed()
+ return errors.Wrapf(
+ errInvalidChainID,
+ "rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s",
+ chainID.String(),
+ n.chainID.String(),
+ n.name,
+ )
+ }
+
+ promPoolRPCNodeVerifiesSuccess.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc()
+
+ return nil
+}
+
+// disconnectAll disconnects all clients connected to the node
+// WARNING: NOT THREAD-SAFE
+// This must be called from within the n.stateMu lock
+func (n *node[CHAIN_ID, HEAD, RPC]) disconnectAll() {
+ n.rpc.DisconnectAll()
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) Order() int32 {
+ return n.order
+}
diff --git a/common/client/node_fsm.go b/common/client/node_fsm.go
new file mode 100644
index 0000000000..d4fc19140e
--- /dev/null
+++ b/common/client/node_fsm.go
@@ -0,0 +1,266 @@
+package client
+
+import (
+ "fmt"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
+
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+var (
+ promPoolRPCNodeTransitionsToAlive = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_transitions_to_alive",
+ Help: transitionString(nodeStateAlive),
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodeTransitionsToInSync = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_transitions_to_in_sync",
+ Help: fmt.Sprintf("%s to %s", transitionString(nodeStateOutOfSync), nodeStateAlive),
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodeTransitionsToOutOfSync = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_transitions_to_out_of_sync",
+ Help: transitionString(nodeStateOutOfSync),
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodeTransitionsToUnreachable = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_transitions_to_unreachable",
+ Help: transitionString(nodeStateUnreachable),
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodeTransitionsToInvalidChainID = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_transitions_to_invalid_chain_id",
+ Help: transitionString(nodeStateInvalidChainID),
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodeTransitionsToUnusable = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_transitions_to_unusable",
+ Help: transitionString(nodeStateUnusable),
+ }, []string{"chainID", "nodeName"})
+)
+
+// nodeState represents the current state of the node
+// Node is a FSM (finite state machine)
+type nodeState int
+
+func (n nodeState) String() string {
+ switch n {
+ case nodeStateUndialed:
+ return "Undialed"
+ case nodeStateDialed:
+ return "Dialed"
+ case nodeStateInvalidChainID:
+ return "InvalidChainID"
+ case nodeStateAlive:
+ return "Alive"
+ case nodeStateUnreachable:
+ return "Unreachable"
+ case nodeStateUnusable:
+ return "Unusable"
+ case nodeStateOutOfSync:
+ return "OutOfSync"
+ case nodeStateClosed:
+ return "Closed"
+ default:
+ return fmt.Sprintf("nodeState(%d)", n)
+ }
+}
+
+// GoString prints a prettier state
+func (n nodeState) GoString() string {
+ return fmt.Sprintf("nodeState%s(%d)", n.String(), n)
+}
+
+const (
+ // nodeStateUndialed is the first state of a virgin node
+ nodeStateUndialed = nodeState(iota)
+ // nodeStateDialed is after a node has successfully dialed but before it has verified the correct chain ID
+ nodeStateDialed
+ // nodeStateInvalidChainID is after chain ID verification failed
+ nodeStateInvalidChainID
+ // nodeStateAlive is a healthy node after chain ID verification succeeded
+ nodeStateAlive
+ // nodeStateUnreachable is a node that cannot be dialed or has disconnected
+ nodeStateUnreachable
+ // nodeStateOutOfSync is a node that is accepting connections but exceeded
+ // the failure threshold without sending any new heads. It will be
+ // disconnected, then put into a revive loop and re-awakened after redial
+ // if a new head arrives
+ nodeStateOutOfSync
+ // nodeStateUnusable is a sendonly node that has an invalid URL that can never be reached
+ nodeStateUnusable
+ // nodeStateClosed is after the connection has been closed and the node is at the end of its lifecycle
+ nodeStateClosed
+ // nodeStateLen tracks the number of states
+ nodeStateLen
+)
+
+// allNodeStates represents all possible states a node can be in
+var allNodeStates []nodeState
+
+func init() {
+ for s := nodeState(0); s < nodeStateLen; s++ {
+ allNodeStates = append(allNodeStates, s)
+ }
+}
+
+// FSM methods
+
+// State allows reading the current state of the node.
+func (n *node[CHAIN_ID, HEAD, RPC]) State() nodeState {
+ n.stateMu.RLock()
+ defer n.stateMu.RUnlock()
+ return n.state
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *utils.Big) {
+ n.stateMu.RLock()
+ defer n.stateMu.RUnlock()
+ return n.state, n.stateLatestBlockNumber, n.stateLatestTotalDifficulty
+}
+
+// setState is only used by internal state management methods.
+// This is low-level; care should be taken by the caller to ensure the new state is a valid transition.
+// State changes should always be synchronous: only one goroutine at a time should change state.
+// n.stateMu should not be locked for long periods of time because external clients expect a timely response from n.State()
+func (n *node[CHAIN_ID, HEAD, RPC]) setState(s nodeState) {
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ n.state = s
+}
+
+// declareXXX methods change the state and pass conrol off the new state
+// management goroutine
+
+func (n *node[CHAIN_ID, HEAD, RPC]) declareAlive() {
+ n.transitionToAlive(func() {
+ n.lfcLog.Infow("RPC Node is online", "nodeState", n.state)
+ n.wg.Add(1)
+ go n.aliveLoop()
+ })
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) transitionToAlive(fn func()) {
+ promPoolRPCNodeTransitionsToAlive.WithLabelValues(n.chainID.String(), n.name).Inc()
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ if n.state == nodeStateClosed {
+ return
+ }
+ switch n.state {
+ case nodeStateDialed, nodeStateInvalidChainID:
+ n.state = nodeStateAlive
+ default:
+ panic(transitionFail(n.state, nodeStateAlive))
+ }
+ fn()
+}
+
+// declareInSync puts a node back into Alive state, allowing it to be used by
+// pool consumers again
+func (n *node[CHAIN_ID, HEAD, RPC]) declareInSync() {
+ n.transitionToInSync(func() {
+ n.lfcLog.Infow("RPC Node is back in sync", "nodeState", n.state)
+ n.wg.Add(1)
+ go n.aliveLoop()
+ })
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInSync(fn func()) {
+ promPoolRPCNodeTransitionsToAlive.WithLabelValues(n.chainID.String(), n.name).Inc()
+ promPoolRPCNodeTransitionsToInSync.WithLabelValues(n.chainID.String(), n.name).Inc()
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ if n.state == nodeStateClosed {
+ return
+ }
+ switch n.state {
+ case nodeStateOutOfSync:
+ n.state = nodeStateAlive
+ default:
+ panic(transitionFail(n.state, nodeStateAlive))
+ }
+ fn()
+}
+
+// declareOutOfSync puts a node into OutOfSync state, disconnecting all current
+// clients and making it unavailable for use until back in-sync.
+func (n *node[CHAIN_ID, HEAD, RPC]) declareOutOfSync(isOutOfSync func(num int64, td *utils.Big) bool) {
+ n.transitionToOutOfSync(func() {
+ n.lfcLog.Errorw("RPC Node is out of sync", "nodeState", n.state)
+ n.wg.Add(1)
+ go n.outOfSyncLoop(isOutOfSync)
+ })
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) transitionToOutOfSync(fn func()) {
+ promPoolRPCNodeTransitionsToOutOfSync.WithLabelValues(n.chainID.String(), n.name).Inc()
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ if n.state == nodeStateClosed {
+ return
+ }
+ switch n.state {
+ case nodeStateAlive:
+ n.disconnectAll()
+ n.state = nodeStateOutOfSync
+ default:
+ panic(transitionFail(n.state, nodeStateOutOfSync))
+ }
+ fn()
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) declareUnreachable() {
+ n.transitionToUnreachable(func() {
+ n.lfcLog.Errorw("RPC Node is unreachable", "nodeState", n.state)
+ n.wg.Add(1)
+ go n.unreachableLoop()
+ })
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) transitionToUnreachable(fn func()) {
+ promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(n.chainID.String(), n.name).Inc()
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ if n.state == nodeStateClosed {
+ return
+ }
+ switch n.state {
+ case nodeStateUndialed, nodeStateDialed, nodeStateAlive, nodeStateOutOfSync, nodeStateInvalidChainID:
+ n.disconnectAll()
+ n.state = nodeStateUnreachable
+ default:
+ panic(transitionFail(n.state, nodeStateUnreachable))
+ }
+ fn()
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) declareInvalidChainID() {
+ n.transitionToInvalidChainID(func() {
+ n.lfcLog.Errorw("RPC Node has the wrong chain ID", "nodeState", n.state)
+ n.wg.Add(1)
+ go n.invalidChainIDLoop()
+ })
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInvalidChainID(fn func()) {
+ promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(n.chainID.String(), n.name).Inc()
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ if n.state == nodeStateClosed {
+ return
+ }
+ switch n.state {
+ case nodeStateDialed, nodeStateOutOfSync:
+ n.disconnectAll()
+ n.state = nodeStateInvalidChainID
+ default:
+ panic(transitionFail(n.state, nodeStateInvalidChainID))
+ }
+ fn()
+}
+
+func transitionString(state nodeState) string {
+ return fmt.Sprintf("Total number of times node has transitioned to %s", state)
+}
+
+func transitionFail(from nodeState, to nodeState) string {
+ return fmt.Sprintf("cannot transition from %#v to %#v", from, to)
+}
diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go
new file mode 100644
index 0000000000..149c5f01a6
--- /dev/null
+++ b/common/client/node_lifecycle.go
@@ -0,0 +1,431 @@
+package client
+
+import (
+ "context"
+ "fmt"
+ "math"
+ "time"
+
+ "github.com/pkg/errors"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
+
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+var (
+ promPoolRPCNodeHighestSeenBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pool_rpc_node_highest_seen_block",
+ Help: "The highest seen block for the given RPC node",
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodeNumSeenBlocks = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_num_seen_blocks",
+ Help: "The total number of new blocks seen by the given RPC node",
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodePolls = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_polls_total",
+ Help: "The total number of poll checks for the given RPC node",
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodePollsFailed = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_polls_failed",
+ Help: "The total number of failed poll checks for the given RPC node",
+ }, []string{"chainID", "nodeName"})
+ promPoolRPCNodePollsSuccess = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "pool_rpc_node_polls_success",
+ Help: "The total number of successful poll checks for the given RPC node",
+ }, []string{"chainID", "nodeName"})
+)
+
+// zombieNodeCheckInterval controls how often to re-check to see if we need to
+// state change in case we have to force a state transition due to no available
+// nodes.
+// NOTE: This only applies to out-of-sync nodes if they are the last available node
+func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration {
+ interval := noNewHeadsThreshold
+ if interval <= 0 || interval > QueryTimeout {
+ interval = QueryTimeout
+ }
+ return utils.WithJitter(interval)
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) setLatestReceived(blockNumber int64, totalDifficulty *utils.Big) {
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+ n.stateLatestBlockNumber = blockNumber
+ n.stateLatestTotalDifficulty = totalDifficulty
+}
+
+const (
+ msgCannotDisable = "but cannot disable this connection because there are no other RPC endpoints, or all other RPC endpoints are dead."
+ msgDegradedState = "Chainlink is now operating in a degraded state and urgent action is required to resolve the issue"
+)
+
+// Node is a FSM
+// Each state has a loop that goes with it, which monitors the node and moves it into another state as necessary.
+// Only one loop must run at a time.
+// Each loop passes control onto the next loop as it exits, except when the node is Closed which terminates the loop permanently.
+
+// This handles node lifecycle for the ALIVE state
+// Should only be run ONCE per node, after a successful Dial
+func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() {
+ defer n.wg.Done()
+
+ {
+ // sanity check
+ state := n.State()
+ switch state {
+ case nodeStateAlive:
+ case nodeStateClosed:
+ return
+ default:
+ panic(fmt.Sprintf("aliveLoop can only run for node in Alive state, got: %s", state))
+ }
+ }
+
+ noNewHeadsTimeoutThreshold := n.noNewHeadsThreshold
+ pollFailureThreshold := n.nodePoolCfg.PollFailureThreshold()
+ pollInterval := n.nodePoolCfg.PollInterval()
+
+ lggr := n.lfcLog.Named("Alive").With("noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold)
+ lggr.Tracew("Alive loop starting", "nodeState", n.State())
+
+ headsC := make(chan HEAD)
+ sub, err := n.rpc.Subscribe(n.nodeCtx, headsC, "newHeads")
+ if err != nil {
+ lggr.Errorw("Initial subscribe for heads failed", "nodeState", n.State())
+ n.declareUnreachable()
+ return
+ }
+ n.rpc.SetAliveLoopSub(sub)
+ defer sub.Unsubscribe()
+
+ var outOfSyncT *time.Ticker
+ var outOfSyncTC <-chan time.Time
+ if noNewHeadsTimeoutThreshold > 0 {
+ lggr.Debugw("Head liveness checking enabled", "nodeState", n.State())
+ outOfSyncT = time.NewTicker(noNewHeadsTimeoutThreshold)
+ defer outOfSyncT.Stop()
+ outOfSyncTC = outOfSyncT.C
+ } else {
+ lggr.Debug("Head liveness checking disabled")
+ }
+
+ var pollCh <-chan time.Time
+ if pollInterval > 0 {
+ lggr.Debug("Polling enabled")
+ pollT := time.NewTicker(pollInterval)
+ defer pollT.Stop()
+ pollCh = pollT.C
+ if pollFailureThreshold > 0 {
+ // polling can be enabled with no threshold to enable polling but
+ // the node will not be marked offline regardless of the number of
+ // poll failures
+ lggr.Debug("Polling liveness checking enabled")
+ }
+ } else {
+ lggr.Debug("Polling disabled")
+ }
+
+ _, highestReceivedBlockNumber, _ := n.StateAndLatest()
+ var pollFailures uint32
+
+ for {
+ select {
+ case <-n.nodeCtx.Done():
+ return
+ case <-pollCh:
+ var version string
+ promPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc()
+ lggr.Tracew("Polling for version", "nodeState", n.State(), "pollFailures", pollFailures)
+ ctx, cancel := context.WithTimeout(n.nodeCtx, pollInterval)
+ version, err := n.RPC().ClientVersion(ctx)
+ cancel()
+ if err != nil {
+ // prevent overflow
+ if pollFailures < math.MaxUint32 {
+ promPoolRPCNodePollsFailed.WithLabelValues(n.chainID.String(), n.name).Inc()
+ pollFailures++
+ }
+ lggr.Warnw(fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", n.String()), "err", err, "pollFailures", pollFailures, "nodeState", n.State())
+ } else {
+ lggr.Debugw("Version poll successful", "nodeState", n.State(), "clientVersion", version)
+ promPoolRPCNodePollsSuccess.WithLabelValues(n.chainID.String(), n.name).Inc()
+ pollFailures = 0
+ }
+ if pollFailureThreshold > 0 && pollFailures >= pollFailureThreshold {
+ lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.State())
+ if n.nLiveNodes != nil {
+ if l, _, _ := n.nLiveNodes(); l < 2 {
+ lggr.Criticalf("RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState)
+ continue
+ }
+ }
+ n.declareUnreachable()
+ return
+ }
+ _, num, td := n.StateAndLatest()
+ if outOfSync, liveNodes := n.syncStatus(num, td); outOfSync {
+ // note: there must be another live node for us to be out of sync
+ lggr.Errorw("RPC endpoint has fallen behind", "blockNumber", num, "totalDifficulty", td, "nodeState", n.State())
+ if liveNodes < 2 {
+ lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState)
+ continue
+ }
+ n.declareOutOfSync(n.isOutOfSync)
+ return
+ }
+ case bh, open := <-headsC:
+ if !open {
+ lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.State())
+ n.declareUnreachable()
+ return
+ }
+ promPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc()
+ lggr.Tracew("Got head", "head", bh)
+ if bh.BlockNumber() > highestReceivedBlockNumber {
+ promPoolRPCNodeHighestSeenBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(bh.BlockNumber()))
+ lggr.Tracew("Got higher block number, resetting timer", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State())
+ highestReceivedBlockNumber = bh.BlockNumber()
+ } else {
+ lggr.Tracew("Ignoring previously seen block number", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State())
+ }
+ if outOfSyncT != nil {
+ outOfSyncT.Reset(noNewHeadsTimeoutThreshold)
+ }
+ n.setLatestReceived(bh.BlockNumber(), bh.BlockDifficulty())
+ case err := <-sub.Err():
+ lggr.Errorw("Subscription was terminated", "err", err, "nodeState", n.State())
+ n.declareUnreachable()
+ return
+ case <-outOfSyncTC:
+ // We haven't received a head on the channel for at least the
+ // threshold amount of time, mark it broken
+ lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, highestReceivedBlockNumber), "nodeState", n.State(), "latestReceivedBlockNumber", highestReceivedBlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold)
+ if n.nLiveNodes != nil {
+ if l, _, _ := n.nLiveNodes(); l < 2 {
+ lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState)
+ // We don't necessarily want to wait the full timeout to check again, we should
+ // check regularly and log noisily in this state
+ outOfSyncT.Reset(zombieNodeCheckInterval(n.noNewHeadsThreshold))
+ continue
+ }
+ }
+ n.declareOutOfSync(func(num int64, td *utils.Big) bool { return num < highestReceivedBlockNumber })
+ return
+ }
+ }
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSync(num int64, td *utils.Big) (outOfSync bool) {
+ outOfSync, _ = n.syncStatus(num, td)
+ return
+}
+
+// syncStatus returns outOfSync true if num or td is more than SyncThresold behind the best node.
+// Always returns outOfSync false for SyncThreshold 0.
+// liveNodes is only included when outOfSync is true.
+func (n *node[CHAIN_ID, HEAD, RPC]) syncStatus(num int64, td *utils.Big) (outOfSync bool, liveNodes int) {
+ if n.nLiveNodes == nil {
+ return // skip for tests
+ }
+ threshold := n.nodePoolCfg.SyncThreshold()
+ if threshold == 0 {
+ return // disabled
+ }
+ // Check against best node
+ ln, highest, greatest := n.nLiveNodes()
+ mode := n.nodePoolCfg.SelectionMode()
+ switch mode {
+ case NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel:
+ return num < highest-int64(threshold), ln
+ case NodeSelectionModeTotalDifficulty:
+ bigThreshold := utils.NewBigI(int64(threshold))
+ return td.Cmp(greatest.Sub(bigThreshold)) < 0, ln
+ default:
+ panic("unrecognized NodeSelectionMode: " + mode)
+ }
+}
+
+const (
+ msgReceivedBlock = "Received block for RPC node, waiting until back in-sync to mark as live again"
+ msgInSync = "RPC node back in sync"
+)
+
+// outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status
+func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td *utils.Big) bool) {
+ defer n.wg.Done()
+
+ {
+ // sanity check
+ state := n.State()
+ switch state {
+ case nodeStateOutOfSync:
+ case nodeStateClosed:
+ return
+ default:
+ panic(fmt.Sprintf("outOfSyncLoop can only run for node in OutOfSync state, got: %s", state))
+ }
+ }
+
+ outOfSyncAt := time.Now()
+
+ lggr := n.lfcLog.Named("OutOfSync")
+ lggr.Debugw("Trying to revive out-of-sync RPC node", "nodeState", n.State())
+
+ // Need to redial since out-of-sync nodes are automatically disconnected
+ if err := n.rpc.Dial(n.nodeCtx); err != nil {
+ lggr.Errorw("Failed to dial out-of-sync RPC node", "nodeState", n.State())
+ n.declareUnreachable()
+ return
+ }
+
+ // Manually re-verify since out-of-sync nodes are automatically disconnected
+ if err := n.verify(n.nodeCtx); err != nil {
+ lggr.Errorw(fmt.Sprintf("Failed to verify out-of-sync RPC node: %v", err), "err", err)
+ n.declareInvalidChainID()
+ return
+ }
+
+ lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State())
+
+ ch := make(chan HEAD)
+ sub, err := n.rpc.Subscribe(n.nodeCtx, ch, "newHeads")
+ if err != nil {
+ lggr.Errorw("Failed to subscribe heads on out-of-sync RPC node", "nodeState", n.State(), "err", err)
+ n.declareUnreachable()
+ return
+ }
+ defer sub.Unsubscribe()
+
+ for {
+ select {
+ case <-n.nodeCtx.Done():
+ return
+ case head, open := <-ch:
+ if !open {
+ lggr.Error("Subscription channel unexpectedly closed", "nodeState", n.State())
+ n.declareUnreachable()
+ return
+ }
+ n.setLatestReceived(head.BlockNumber(), head.BlockDifficulty())
+ if !isOutOfSync(head.BlockNumber(), head.BlockDifficulty()) {
+ // back in-sync! flip back into alive loop
+ lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt)), "blockNumber", head.BlockNumber(), "totalDifficulty", "nodeState", n.State())
+ n.declareInSync()
+ return
+ }
+ lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "totalDifficulty", "nodeState", n.State())
+ case <-time.After(zombieNodeCheckInterval(n.noNewHeadsThreshold)):
+ if n.nLiveNodes != nil {
+ if l, _, _ := n.nLiveNodes(); l < 1 {
+ lggr.Critical("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state")
+ n.declareInSync()
+ return
+ }
+ }
+ case err := <-sub.Err():
+ lggr.Errorw("Subscription was terminated", "nodeState", n.State(), "err", err)
+ n.declareUnreachable()
+ return
+ }
+ }
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() {
+ defer n.wg.Done()
+
+ {
+ // sanity check
+ state := n.State()
+ switch state {
+ case nodeStateUnreachable:
+ case nodeStateClosed:
+ return
+ default:
+ panic(fmt.Sprintf("unreachableLoop can only run for node in Unreachable state, got: %s", state))
+ }
+ }
+
+ unreachableAt := time.Now()
+
+ lggr := n.lfcLog.Named("Unreachable")
+ lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.State())
+
+ dialRetryBackoff := utils.NewRedialBackoff()
+
+ for {
+ select {
+ case <-n.nodeCtx.Done():
+ return
+ case <-time.After(dialRetryBackoff.Duration()):
+ lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.State())
+
+ err := n.rpc.Dial(n.nodeCtx)
+ if err != nil {
+ lggr.Errorw(fmt.Sprintf("Failed to redial RPC node; still unreachable: %v", err), "err", err, "nodeState", n.State())
+ continue
+ }
+
+ n.setState(nodeStateDialed)
+
+ err = n.verify(n.nodeCtx)
+
+ if errors.Is(err, errInvalidChainID) {
+ lggr.Errorw("Failed to redial RPC node; remote endpoint returned the wrong chain ID", "err", err)
+ n.declareInvalidChainID()
+ return
+ } else if err != nil {
+ lggr.Errorw(fmt.Sprintf("Failed to redial RPC node; verify failed: %v", err), "err", err)
+ n.declareUnreachable()
+ return
+ }
+
+ lggr.Infow(fmt.Sprintf("Successfully redialled and verified RPC node %s. Node was offline for %s", n.String(), time.Since(unreachableAt)), "nodeState", n.State())
+ n.declareAlive()
+ return
+ }
+ }
+}
+
+func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() {
+ defer n.wg.Done()
+
+ {
+ // sanity check
+ state := n.State()
+ switch state {
+ case nodeStateInvalidChainID:
+ case nodeStateClosed:
+ return
+ default:
+ panic(fmt.Sprintf("invalidChainIDLoop can only run for node in InvalidChainID state, got: %s", state))
+ }
+ }
+
+ invalidAt := time.Now()
+
+ lggr := n.lfcLog.Named("InvalidChainID")
+ lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with invalid chain ID", n.String()), "nodeState", n.State())
+
+ chainIDRecheckBackoff := utils.NewRedialBackoff()
+
+ for {
+ select {
+ case <-n.nodeCtx.Done():
+ return
+ case <-time.After(chainIDRecheckBackoff.Duration()):
+ err := n.verify(n.nodeCtx)
+ if errors.Is(err, errInvalidChainID) {
+ lggr.Errorw("Failed to verify RPC node; remote endpoint returned the wrong chain ID", "err", err)
+ continue
+ } else if err != nil {
+ lggr.Errorw(fmt.Sprintf("Unexpected error while verifying RPC node chain ID; %v", err), "err", err)
+ n.declareUnreachable()
+ return
+ }
+ lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was offline for %s", time.Since(invalidAt)), "nodeState", n.State())
+ n.declareAlive()
+ return
+ }
+ }
+}
diff --git a/common/client/node_selector_highest_head.go b/common/client/node_selector_highest_head.go
new file mode 100644
index 0000000000..99a130004a
--- /dev/null
+++ b/common/client/node_selector_highest_head.go
@@ -0,0 +1,41 @@
+package client
+
+import (
+ "math"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+type highestHeadNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] []Node[CHAIN_ID, HEAD, RPC]
+
+func NewHighestHeadNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] {
+ return highestHeadNodeSelector[CHAIN_ID, HEAD, RPC](nodes)
+}
+
+func (s highestHeadNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] {
+ var highestHeadNumber int64 = math.MinInt64
+ var highestHeadNodes []Node[CHAIN_ID, HEAD, RPC]
+ for _, n := range s {
+ state, currentHeadNumber, _ := n.StateAndLatest()
+ if state == nodeStateAlive && currentHeadNumber >= highestHeadNumber {
+ if highestHeadNumber < currentHeadNumber {
+ highestHeadNumber = currentHeadNumber
+ highestHeadNodes = nil
+ }
+ highestHeadNodes = append(highestHeadNodes, n)
+ }
+ }
+ return firstOrHighestPriority(highestHeadNodes)
+}
+
+func (s highestHeadNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string {
+ return NodeSelectionModeHighestHead
+}
diff --git a/common/client/node_selector_priority_level.go b/common/client/node_selector_priority_level.go
new file mode 100644
index 0000000000..45cc62de07
--- /dev/null
+++ b/common/client/node_selector_priority_level.go
@@ -0,0 +1,129 @@
+package client
+
+import (
+ "math"
+ "sort"
+ "sync/atomic"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+type priorityLevelNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] struct {
+ nodes []Node[CHAIN_ID, HEAD, RPC]
+ roundRobinCount []atomic.Uint32
+}
+
+type nodeWithPriority[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] struct {
+ node Node[CHAIN_ID, HEAD, RPC]
+ priority int32
+}
+
+func NewPriorityLevelNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] {
+ return &priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]{
+ nodes: nodes,
+ roundRobinCount: make([]atomic.Uint32, nrOfPriorityTiers(nodes)),
+ }
+}
+
+func (s priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] {
+ nodes := s.getHighestPriorityAliveTier()
+
+ if len(nodes) == 0 {
+ return nil
+ }
+ priorityLevel := nodes[len(nodes)-1].priority
+
+ // NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter
+ count := s.roundRobinCount[priorityLevel].Add(1) - 1
+ idx := int(count % uint32(len(nodes)))
+
+ return nodes[idx].node
+}
+
+func (s priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string {
+ return NodeSelectionModePriorityLevel
+}
+
+// getHighestPriorityAliveTier filters nodes that are not in state nodeStateAlive and
+// returns only the highest tier of alive nodes
+func (s priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]) getHighestPriorityAliveTier() []nodeWithPriority[CHAIN_ID, HEAD, RPC] {
+ var nodes []nodeWithPriority[CHAIN_ID, HEAD, RPC]
+ for _, n := range s.nodes {
+ if n.State() == nodeStateAlive {
+ nodes = append(nodes, nodeWithPriority[CHAIN_ID, HEAD, RPC]{n, n.Order()})
+ }
+ }
+
+ if len(nodes) == 0 {
+ return nil
+ }
+
+ return removeLowerTiers(nodes)
+}
+
+// removeLowerTiers take a slice of nodeWithPriority[CHAIN_ID, BLOCK_HASH, HEAD, RPC] and keeps only the highest tier
+func removeLowerTiers[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []nodeWithPriority[CHAIN_ID, HEAD, RPC]) []nodeWithPriority[CHAIN_ID, HEAD, RPC] {
+ sort.SliceStable(nodes, func(i, j int) bool {
+ return nodes[i].priority > nodes[j].priority
+ })
+
+ var nodes2 []nodeWithPriority[CHAIN_ID, HEAD, RPC]
+ currentPriority := nodes[len(nodes)-1].priority
+
+ for _, n := range nodes {
+ if n.priority == currentPriority {
+ nodes2 = append(nodes2, n)
+ }
+ }
+
+ return nodes2
+}
+
+// nrOfPriorityTiers calculates the total number of priority tiers
+func nrOfPriorityTiers[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []Node[CHAIN_ID, HEAD, RPC]) int32 {
+ highestPriority := int32(0)
+ for _, n := range nodes {
+ priority := n.Order()
+ if highestPriority < priority {
+ highestPriority = priority
+ }
+ }
+ return highestPriority + 1
+}
+
+// firstOrHighestPriority takes a list of nodes and returns the first one with the highest priority
+func firstOrHighestPriority[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []Node[CHAIN_ID, HEAD, RPC]) Node[CHAIN_ID, HEAD, RPC] {
+ hp := int32(math.MaxInt32)
+ var node Node[CHAIN_ID, HEAD, RPC]
+ for _, n := range nodes {
+ if n.Order() < hp {
+ hp = n.Order()
+ node = n
+ }
+ }
+ return node
+}
diff --git a/common/client/node_selector_round_robin.go b/common/client/node_selector_round_robin.go
new file mode 100644
index 0000000000..5cdad7f52e
--- /dev/null
+++ b/common/client/node_selector_round_robin.go
@@ -0,0 +1,50 @@
+package client
+
+import (
+ "sync/atomic"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+type roundRobinSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] struct {
+ nodes []Node[CHAIN_ID, HEAD, RPC]
+ roundRobinCount atomic.Uint32
+}
+
+func NewRoundRobinSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] {
+ return &roundRobinSelector[CHAIN_ID, HEAD, RPC]{
+ nodes: nodes,
+ }
+}
+
+func (s *roundRobinSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] {
+ var liveNodes []Node[CHAIN_ID, HEAD, RPC]
+ for _, n := range s.nodes {
+ if n.State() == nodeStateAlive {
+ liveNodes = append(liveNodes, n)
+ }
+ }
+
+ nNodes := len(liveNodes)
+ if nNodes == 0 {
+ return nil
+ }
+
+ // NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter
+ count := s.roundRobinCount.Add(1) - 1
+ idx := int(count % uint32(nNodes))
+
+ return liveNodes[idx]
+}
+
+func (s *roundRobinSelector[CHAIN_ID, HEAD, RPC]) Name() string {
+ return NodeSelectionModeRoundRobin
+}
diff --git a/common/client/node_selector_total_difficulty.go b/common/client/node_selector_total_difficulty.go
new file mode 100644
index 0000000000..9b29642d03
--- /dev/null
+++ b/common/client/node_selector_total_difficulty.go
@@ -0,0 +1,54 @@
+package client
+
+import (
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+type totalDifficultyNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] []Node[CHAIN_ID, HEAD, RPC]
+
+func NewTotalDifficultyNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] {
+ return totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC](nodes)
+}
+
+func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] {
+ // NodeNoNewHeadsThreshold may not be enabled, in this case all nodes have td == nil
+ var highestTD *utils.Big
+ var nodes []Node[CHAIN_ID, HEAD, RPC]
+ var aliveNodes []Node[CHAIN_ID, HEAD, RPC]
+
+ for _, n := range s {
+ state, _, currentTD := n.StateAndLatest()
+ if state != nodeStateAlive {
+ continue
+ }
+
+ aliveNodes = append(aliveNodes, n)
+ if currentTD != nil && (highestTD == nil || currentTD.Cmp(highestTD) >= 0) {
+ if highestTD == nil || currentTD.Cmp(highestTD) > 0 {
+ highestTD = currentTD
+ nodes = nil
+ }
+ nodes = append(nodes, n)
+ }
+ }
+
+ //If all nodes have td == nil pick one from the nodes that are alive
+ if len(nodes) == 0 {
+ return firstOrHighestPriority(aliveNodes)
+ }
+ return firstOrHighestPriority(nodes)
+}
+
+func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string {
+ return NodeSelectionModeTotalDifficulty
+}
diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go
new file mode 100644
index 0000000000..3b382b2dcb
--- /dev/null
+++ b/common/client/send_only_node.go
@@ -0,0 +1,183 @@
+package client
+
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "sync"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
+ "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type sendOnlyClient[
+ CHAIN_ID types.ID,
+] interface {
+ Close()
+ ChainID(context.Context) (CHAIN_ID, error)
+ DialHTTP() error
+}
+
+// SendOnlyNode represents one node used as a sendonly
+type SendOnlyNode[
+ CHAIN_ID types.ID,
+ RPC sendOnlyClient[CHAIN_ID],
+] interface {
+ // Start may attempt to connect to the node, but should only return error for misconfiguration - never for temporary errors.
+ Start(context.Context) error
+ Close() error
+
+ ConfiguredChainID() CHAIN_ID
+ RPC() RPC
+
+ String() string
+ // State returns nodeState
+ State() nodeState
+ // Name is a unique identifier for this node.
+ Name() string
+}
+
+// It only supports sending transactions
+// It must use an http(s) url
+type sendOnlyNode[
+ CHAIN_ID types.ID,
+ RPC sendOnlyClient[CHAIN_ID],
+] struct {
+ services.StateMachine
+
+ stateMu sync.RWMutex // protects state* fields
+ state nodeState
+
+ rpc RPC
+ uri url.URL
+ log logger.Logger
+ name string
+ chainID CHAIN_ID
+ chStop utils.StopChan
+ wg sync.WaitGroup
+}
+
+// NewSendOnlyNode returns a new sendonly node
+func NewSendOnlyNode[
+ CHAIN_ID types.ID,
+ RPC sendOnlyClient[CHAIN_ID],
+](
+ lggr logger.Logger,
+ httpuri url.URL,
+ name string,
+ chainID CHAIN_ID,
+ rpc RPC,
+) SendOnlyNode[CHAIN_ID, RPC] {
+ s := new(sendOnlyNode[CHAIN_ID, RPC])
+ s.name = name
+ s.log = lggr.Named("SendOnlyNode").Named(name).With(
+ "nodeTier", "sendonly",
+ )
+ s.rpc = rpc
+ s.uri = httpuri
+ s.chainID = chainID
+ s.chStop = make(chan struct{})
+ return s
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) Start(ctx context.Context) error {
+ return s.StartOnce(s.name, func() error {
+ s.start(ctx)
+ return nil
+ })
+}
+
+// Start setups up and verifies the sendonly node
+// Should only be called once in a node's lifecycle
+func (s *sendOnlyNode[CHAIN_ID, RPC]) start(startCtx context.Context) {
+ if s.State() != nodeStateUndialed {
+ panic(fmt.Sprintf("cannot dial node with state %v", s.state))
+ }
+
+ err := s.rpc.DialHTTP()
+ if err != nil {
+ promPoolRPCNodeTransitionsToUnusable.WithLabelValues(s.chainID.String(), s.name).Inc()
+ s.log.Errorw("Dial failed: SendOnly Node is unusable", "err", err)
+ s.setState(nodeStateUnusable)
+ return
+ }
+ s.setState(nodeStateDialed)
+
+ if s.chainID.String() == "0" {
+ // Skip verification if chainID is zero
+ s.log.Warn("sendonly rpc ChainID verification skipped")
+ } else {
+ chainID, err := s.rpc.ChainID(startCtx)
+ if err != nil || chainID.String() != s.chainID.String() {
+ promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc()
+ if err != nil {
+ promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc()
+ s.log.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err)
+ s.setState(nodeStateUnreachable)
+ } else {
+ promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(s.chainID.String(), s.name).Inc()
+ s.log.Errorf(
+ "sendonly rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s",
+ chainID.String(),
+ s.chainID.String(),
+ s.name,
+ )
+ s.setState(nodeStateInvalidChainID)
+ }
+ // Since it has failed, spin up the verifyLoop that will keep
+ // retrying until success
+ s.wg.Add(1)
+ go s.verifyLoop()
+ return
+ }
+ }
+
+ promPoolRPCNodeTransitionsToAlive.WithLabelValues(s.chainID.String(), s.name).Inc()
+ s.setState(nodeStateAlive)
+ s.log.Infow("Sendonly RPC Node is online", "nodeState", s.state)
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) Close() error {
+ return s.StopOnce(s.name, func() error {
+ s.rpc.Close()
+ s.wg.Wait()
+ s.setState(nodeStateClosed)
+ return nil
+ })
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID {
+ return s.chainID
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) RPC() RPC {
+ return s.rpc
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) String() string {
+ return fmt.Sprintf("(%s)%s:%s", client.Secondary.String(), s.name, s.uri.Redacted())
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) setState(state nodeState) (changed bool) {
+ s.stateMu.Lock()
+ defer s.stateMu.Unlock()
+ if s.state == state {
+ return false
+ }
+ s.state = state
+ return true
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) State() nodeState {
+ s.stateMu.RLock()
+ defer s.stateMu.RUnlock()
+ return s.state
+}
+
+func (s *sendOnlyNode[CHAIN_ID, RPC]) Name() string {
+ return s.name
+}
diff --git a/common/client/send_only_node_lifecycle.go b/common/client/send_only_node_lifecycle.go
new file mode 100644
index 0000000000..0f663eab30
--- /dev/null
+++ b/common/client/send_only_node_lifecycle.go
@@ -0,0 +1,66 @@
+package client
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+// verifyLoop may only be triggered once, on Start, if initial chain ID check
+// fails.
+//
+// It will continue checking until success and then exit permanently.
+func (s *sendOnlyNode[CHAIN_ID, RPC]) verifyLoop() {
+ defer s.wg.Done()
+
+ backoff := utils.NewRedialBackoff()
+ for {
+ select {
+ case <-s.chStop:
+ return
+ case <-time.After(backoff.Duration()):
+ }
+ chainID, err := s.rpc.ChainID(context.Background())
+ if err != nil {
+ ok := s.IfStarted(func() {
+ if changed := s.setState(nodeStateUnreachable); changed {
+ promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc()
+ }
+ })
+ if !ok {
+ return
+ }
+ s.log.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err)
+ continue
+ } else if chainID.String() != s.chainID.String() {
+ ok := s.IfStarted(func() {
+ if changed := s.setState(nodeStateInvalidChainID); changed {
+ promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(s.chainID.String(), s.name).Inc()
+ }
+ })
+ if !ok {
+ return
+ }
+ s.log.Errorf(
+ "sendonly rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s",
+ chainID.String(),
+ s.chainID.String(),
+ s.name,
+ )
+
+ continue
+ }
+ ok := s.IfStarted(func() {
+ if changed := s.setState(nodeStateAlive); changed {
+ promPoolRPCNodeTransitionsToAlive.WithLabelValues(s.chainID.String(), s.name).Inc()
+ }
+ })
+ if !ok {
+ return
+ }
+ s.log.Infow("Sendonly RPC Node is online", "nodeState", s.state)
+ return
+ }
+}
diff --git a/common/client/types.go b/common/client/types.go
new file mode 100644
index 0000000000..f3a6029a9e
--- /dev/null
+++ b/common/client/types.go
@@ -0,0 +1,133 @@
+package client
+
+import (
+ "context"
+ "math/big"
+
+ feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+// RPC includes all the necessary methods for a multi-node client to interact directly with any RPC endpoint.
+type RPC[
+ CHAIN_ID types.ID,
+ SEQ types.Sequence,
+ ADDR types.Hashable,
+ BLOCK_HASH types.Hashable,
+ TX any,
+ TX_HASH types.Hashable,
+ EVENT any,
+ EVENT_OPS any,
+ TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
+ FEE feetypes.Fee,
+ HEAD types.Head[BLOCK_HASH],
+
+] interface {
+ NodeClient[
+ CHAIN_ID,
+ HEAD,
+ ]
+ clientAPI[
+ CHAIN_ID,
+ SEQ,
+ ADDR,
+ BLOCK_HASH,
+ TX,
+ TX_HASH,
+ EVENT,
+ EVENT_OPS,
+ TX_RECEIPT,
+ FEE,
+ HEAD,
+ ]
+}
+
+// Head is the interface required by the NodeClient
+type Head interface {
+ BlockNumber() int64
+ BlockDifficulty() *utils.Big
+}
+
+// NodeClient includes all the necessary RPC methods required by a node.
+type NodeClient[
+ CHAIN_ID types.ID,
+ HEAD Head,
+] interface {
+ connection[CHAIN_ID, HEAD]
+
+ DialHTTP() error
+ DisconnectAll()
+ Close()
+ ClientVersion(context.Context) (string, error)
+ SubscribersCount() int32
+ SetAliveLoopSub(types.Subscription)
+ UnsubscribeAllExceptAliveLoop()
+}
+
+// clientAPI includes all the direct RPC methods required by the generalized common client to implement its own.
+type clientAPI[
+ CHAIN_ID types.ID,
+ SEQ types.Sequence,
+ ADDR types.Hashable,
+ BLOCK_HASH types.Hashable,
+ TX any,
+ TX_HASH types.Hashable,
+ EVENT any,
+ EVENT_OPS any, // event filter query options
+ TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
+ FEE feetypes.Fee,
+ HEAD types.Head[BLOCK_HASH],
+] interface {
+ connection[CHAIN_ID, HEAD]
+
+ // Account
+ BalanceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (*big.Int, error)
+ TokenBalance(ctx context.Context, accountAddress ADDR, tokenAddress ADDR) (*big.Int, error)
+ SequenceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (SEQ, error)
+ LINKBalance(ctx context.Context, accountAddress ADDR, linkAddress ADDR) (*assets.Link, error)
+ PendingSequenceAt(ctx context.Context, addr ADDR) (SEQ, error)
+ EstimateGas(ctx context.Context, call any) (gas uint64, err error)
+
+ // Transactions
+ SendTransaction(ctx context.Context, tx TX) error
+ SimulateTransaction(ctx context.Context, tx TX) error
+ TransactionByHash(ctx context.Context, txHash TX_HASH) (TX, error)
+ TransactionReceipt(ctx context.Context, txHash TX_HASH) (TX_RECEIPT, error)
+ SendEmptyTransaction(
+ ctx context.Context,
+ newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt any, err error),
+ seq SEQ,
+ gasLimit uint32,
+ fee FEE,
+ fromAddress ADDR,
+ ) (txhash string, err error)
+
+ // Blocks
+ BlockByNumber(ctx context.Context, number *big.Int) (HEAD, error)
+ BlockByHash(ctx context.Context, hash BLOCK_HASH) (HEAD, error)
+ LatestBlockHeight(context.Context) (*big.Int, error)
+
+ // Events
+ FilterEvents(ctx context.Context, query EVENT_OPS) ([]EVENT, error)
+
+ // Misc
+ BatchCallContext(ctx context.Context, b []any) error
+ CallContract(
+ ctx context.Context,
+ msg interface{},
+ blockNumber *big.Int,
+ ) (rpcErr []byte, extractErr error)
+ CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error
+ CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) ([]byte, error)
+}
+
+type connection[
+ CHAIN_ID types.ID,
+ HEAD Head,
+] interface {
+ ChainID(ctx context.Context) (CHAIN_ID, error)
+ Dial(ctx context.Context) error
+ Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (types.Subscription, error)
+}
diff --git a/common/headtracker/types/mocks/head.go b/common/headtracker/types/mocks/head.go
index edda18d57e..a56590b6ef 100644
--- a/common/headtracker/types/mocks/head.go
+++ b/common/headtracker/types/mocks/head.go
@@ -4,6 +4,7 @@ package mocks
import (
types "github.com/smartcontractkit/chainlink/v2/common/types"
+ utils "github.com/smartcontractkit/chainlink/v2/core/utils"
mock "github.com/stretchr/testify/mock"
)
@@ -12,6 +13,22 @@ type Head[BLOCK_HASH types.Hashable, CHAIN_ID types.ID] struct {
mock.Mock
}
+// BlockDifficulty provides a mock function with given fields:
+func (_m *Head[BLOCK_HASH, CHAIN_ID]) BlockDifficulty() *utils.Big {
+ ret := _m.Called()
+
+ var r0 *utils.Big
+ if rf, ok := ret.Get(0).(func() *utils.Big); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*utils.Big)
+ }
+ }
+
+ return r0
+}
+
// BlockHash provides a mock function with given fields:
func (_m *Head[BLOCK_HASH, CHAIN_ID]) BlockHash() BLOCK_HASH {
ret := _m.Called()
diff --git a/common/types/head.go b/common/types/head.go
index 4d339b1cdd..bef9c30d9e 100644
--- a/common/types/head.go
+++ b/common/types/head.go
@@ -1,5 +1,7 @@
package types
+import "github.com/smartcontractkit/chainlink/v2/core/utils"
+
// Head provides access to a chain's head, as needed by the TxManager.
// This is a generic interface which ALL chains will implement.
//
@@ -24,4 +26,8 @@ type Head[BLOCK_HASH Hashable] interface {
// HashAtHeight returns the hash of the block at the given height, if it is in the chain.
// If not in chain, returns the zero hash
HashAtHeight(blockNum int64) BLOCK_HASH
+
+ // Returns the total difficulty of the block. For chains who do not have a concept of block
+ // difficulty, return 0.
+ BlockDifficulty() *utils.Big
}
diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go
index 3cb303ef26..816a9234a3 100644
--- a/common/types/mocks/head.go
+++ b/common/types/mocks/head.go
@@ -4,6 +4,7 @@ package mocks
import (
types "github.com/smartcontractkit/chainlink/v2/common/types"
+ utils "github.com/smartcontractkit/chainlink/v2/core/utils"
mock "github.com/stretchr/testify/mock"
)
@@ -12,6 +13,22 @@ type Head[BLOCK_HASH types.Hashable] struct {
mock.Mock
}
+// BlockDifficulty provides a mock function with given fields:
+func (_m *Head[BLOCK_HASH]) BlockDifficulty() *utils.Big {
+ ret := _m.Called()
+
+ var r0 *utils.Big
+ if rf, ok := ret.Get(0).(func() *utils.Big); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*utils.Big)
+ }
+ }
+
+ return r0
+}
+
// BlockHash provides a mock function with given fields:
func (_m *Head[BLOCK_HASH]) BlockHash() BLOCK_HASH {
ret := _m.Called()
diff --git a/common/types/receipt.go b/common/types/receipt.go
new file mode 100644
index 0000000000..01d5a72def
--- /dev/null
+++ b/common/types/receipt.go
@@ -0,0 +1,14 @@
+package types
+
+import "math/big"
+
+type Receipt[TX_HASH Hashable, BLOCK_HASH Hashable] interface {
+ GetStatus() uint64
+ GetTxHash() TX_HASH
+ GetBlockNumber() *big.Int
+ IsZero() bool
+ IsUnmined() bool
+ GetFeeUsed() uint64
+ GetTransactionIndex() uint
+ GetBlockHash() BLOCK_HASH
+}
diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go
index 6eed13271e..936abc6216 100644
--- a/core/chains/evm/chain.go
+++ b/core/chains/evm/chain.go
@@ -498,3 +498,21 @@ func newPrimary(cfg evmconfig.NodePool, noNewHeadsThreshold time.Duration, lggr
return evmclient.NewNode(cfg, noNewHeadsThreshold, lggr, (url.URL)(*n.WSURL), (*url.URL)(n.HTTPURL), *n.Name, id, chainID, *n.Order), nil
}
+
+// TODO-1663: replace newEthClientFromChain with the function below once client.go is deprecated.
+//func newEthClientFromChain(cfg evmconfig.NodePool, noNewHeadsThreshold time.Duration, lggr logger.Logger, chainID *big.Int, chainType config.ChainType, nodes []*toml.Node) evmclient.Client {
+// var empty url.URL
+// var primaries []commonclient.Node[*big.Int, *evmtypes.Head, evmclient.RPCCLient]
+// var sendonlys []commonclient.SendOnlyNode[*big.Int, evmclient.RPCCLient]
+// for i, node := range nodes {
+// if node.SendOnly != nil && *node.SendOnly {
+// rpc := evmclient.NewRPCClient(lggr, empty, (*url.URL)(node.HTTPURL), fmt.Sprintf("eth-sendonly-rpc-%d", i), int32(i), chainID, commontypes.Primary)
+// sendonly := commonclient.NewSendOnlyNode[*big.Int, evmclient.RPCCLient](lggr, (url.URL)(*node.HTTPURL), *node.Name, chainID, rpc)
+// sendonlys = append(sendonlys, sendonly)
+// } else {
+// rpc := evmclient.NewRPCClient(lggr, (url.URL)(*node.WSURL), (*url.URL)(node.HTTPURL), fmt.Sprintf("eth-sendonly-rpc-%d", i), int32(i), chainID, commontypes.Primary)
+// primaries = append(primaries, commonclient.NewNode[*big.Int, *evmtypes.Head, evmclient.RPCCLient](cfg, noNewHeadsThreshold, lggr, (url.URL)(*node.WSURL), (*url.URL)(node.HTTPURL), *node.Name, int32(i), chainID, *node.Order, rpc, "EVM"))
+// }
+// }
+// return evmclient.NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), noNewHeadsThreshold, primaries, sendonlys, chainID, chainType)
+//}
diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go
new file mode 100644
index 0000000000..bda028cbf3
--- /dev/null
+++ b/core/chains/evm/client/chain_client.go
@@ -0,0 +1,274 @@
+package client
+
+import (
+ "context"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rpc"
+
+ commontypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+ "github.com/smartcontractkit/chainlink/v2/core/assets"
+ evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+var _ Client = (*chainClient)(nil)
+
+// TODO-1663: rename this to client, once the client.go file is deprecated.
+type chainClient struct {
+ multiNode commonclient.MultiNode[
+ *big.Int,
+ evmtypes.Nonce,
+ common.Address,
+ common.Hash,
+ *types.Transaction,
+ common.Hash,
+ types.Log,
+ ethereum.FilterQuery,
+ *evmtypes.Receipt,
+ *assets.Wei,
+ *evmtypes.Head,
+ RPCCLient,
+ ]
+ logger logger.Logger
+}
+
+func NewChainClient(
+ logger logger.Logger,
+ selectionMode string,
+ leaseDuration time.Duration,
+ noNewHeadsThreshold time.Duration,
+ nodes []commonclient.Node[*big.Int, *evmtypes.Head, RPCCLient],
+ sendonlys []commonclient.SendOnlyNode[*big.Int, RPCCLient],
+ chainID *big.Int,
+ chainType config.ChainType,
+) Client {
+ multiNode := commonclient.NewMultiNode[
+ *big.Int,
+ evmtypes.Nonce,
+ common.Address,
+ common.Hash,
+ *types.Transaction,
+ common.Hash,
+ types.Log,
+ ethereum.FilterQuery,
+ *evmtypes.Receipt,
+ *assets.Wei,
+ *evmtypes.Head,
+ RPCCLient,
+ ](
+ logger,
+ selectionMode,
+ leaseDuration,
+ noNewHeadsThreshold,
+ nodes,
+ sendonlys,
+ chainID,
+ chainType,
+ "EVM",
+ ClassifySendOnlyError,
+ )
+ return &chainClient{
+ multiNode: multiNode,
+ logger: logger,
+ }
+}
+
+func (c *chainClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) {
+ return c.multiNode.BalanceAt(ctx, account, blockNumber)
+}
+
+func (c *chainClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error {
+ batch := make([]any, len(b))
+ for i, arg := range b {
+ batch[i] = any(arg)
+ }
+ return c.multiNode.BatchCallContext(ctx, batch)
+}
+
+func (c *chainClient) BatchCallContextAll(ctx context.Context, b []rpc.BatchElem) error {
+ batch := make([]any, len(b))
+ for i, arg := range b {
+ batch[i] = any(arg)
+ }
+ return c.multiNode.BatchCallContextAll(ctx, batch)
+}
+
+// TODO-1663: return custom Block type instead of geth's once client.go is deprecated.
+func (c *chainClient) BlockByHash(ctx context.Context, hash common.Hash) (b *types.Block, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return b, err
+ }
+ return rpc.BlockByHashGeth(ctx, hash)
+}
+
+// TODO-1663: return custom Block type instead of geth's once client.go is deprecated.
+func (c *chainClient) BlockByNumber(ctx context.Context, number *big.Int) (b *types.Block, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return b, err
+ }
+ return rpc.BlockByNumberGeth(ctx, number)
+}
+
+func (c *chainClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
+ return c.multiNode.CallContext(ctx, result, method)
+}
+
+func (c *chainClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
+ return c.multiNode.CallContract(ctx, msg, blockNumber)
+}
+
+// TODO-1663: change this to actual ChainID() call once client.go is deprecated.
+func (c *chainClient) ChainID() (*big.Int, error) {
+ //return c.multiNode.ChainID(ctx), nil
+ return c.multiNode.ConfiguredChainID(), nil
+}
+
+func (c *chainClient) Close() {
+ c.multiNode.Close()
+}
+
+func (c *chainClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
+ return c.multiNode.CodeAt(ctx, account, blockNumber)
+}
+
+func (c *chainClient) ConfiguredChainID() *big.Int {
+ return c.multiNode.ConfiguredChainID()
+}
+
+func (c *chainClient) Dial(ctx context.Context) error {
+ return c.multiNode.Dial(ctx)
+}
+
+func (c *chainClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
+ return c.multiNode.EstimateGas(ctx, call)
+}
+func (c *chainClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
+ return c.multiNode.FilterEvents(ctx, q)
+}
+
+func (c *chainClient) HeaderByHash(ctx context.Context, h common.Hash) (head *types.Header, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return head, err
+ }
+ return rpc.HeaderByHash(ctx, h)
+}
+
+func (c *chainClient) HeaderByNumber(ctx context.Context, n *big.Int) (head *types.Header, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return head, err
+ }
+ return rpc.HeaderByNumber(ctx, n)
+}
+
+func (c *chainClient) HeadByHash(ctx context.Context, h common.Hash) (*evmtypes.Head, error) {
+ return c.multiNode.BlockByHash(ctx, h)
+}
+
+func (c *chainClient) HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) {
+ return c.multiNode.BlockByNumber(ctx, n)
+}
+
+func (c *chainClient) IsL2() bool {
+ return c.multiNode.IsL2()
+}
+
+func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*assets.Link, error) {
+ return c.multiNode.LINKBalance(ctx, address, linkAddress)
+}
+
+func (c *chainClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) {
+ return c.multiNode.LatestBlockHeight(ctx)
+}
+
+func (c *chainClient) NodeStates() map[string]string {
+ return c.multiNode.NodeStates()
+}
+
+func (c *chainClient) PendingCodeAt(ctx context.Context, account common.Address) (b []byte, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return b, err
+ }
+ return rpc.PendingCodeAt(ctx, account)
+}
+
+// TODO-1663: change this to evmtypes.Nonce(int64) once client.go is deprecated.
+func (c *chainClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
+ n, err := c.multiNode.PendingSequenceAt(ctx, account)
+ return uint64(n), err
+}
+
+func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction) error {
+ return c.multiNode.SendTransaction(ctx, tx)
+}
+
+func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commontypes.SendTxReturnCode, error) {
+ err := c.SendTransaction(ctx, tx)
+ return ClassifySendError(err, c.logger, tx, fromAddress, c.IsL2())
+}
+
+func (c *chainClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) {
+ return c.multiNode.SequenceAt(ctx, account, blockNumber)
+}
+
+func (c *chainClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (s ethereum.Subscription, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return s, err
+ }
+ return rpc.SubscribeFilterLogs(ctx, q, ch)
+}
+
+func (c *chainClient) SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) {
+ csf := newChainIDSubForwarder(c.ConfiguredChainID(), ch)
+ err := csf.start(c.multiNode.Subscribe(ctx, csf.srcCh, "newHeads"))
+ if err != nil {
+ return nil, err
+ }
+ return csf, nil
+}
+
+func (c *chainClient) SuggestGasPrice(ctx context.Context) (p *big.Int, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return p, err
+ }
+ return rpc.SuggestGasPrice(ctx)
+}
+
+func (c *chainClient) SuggestGasTipCap(ctx context.Context) (t *big.Int, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return t, err
+ }
+ return rpc.SuggestGasTipCap(ctx)
+}
+
+func (c *chainClient) TokenBalance(ctx context.Context, address common.Address, contractAddress common.Address) (*big.Int, error) {
+ return c.multiNode.TokenBalance(ctx, address, contractAddress)
+}
+
+func (c *chainClient) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, error) {
+ return c.multiNode.TransactionByHash(ctx, txHash)
+}
+
+// TODO-1663: return custom Receipt type instead of geth's once client.go is deprecated.
+func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (r *types.Receipt, err error) {
+ rpc, err := c.multiNode.SelectNodeRPC()
+ if err != nil {
+ return r, err
+ }
+ //return rpc.TransactionReceipt(ctx, txHash)
+ return rpc.TransactionReceiptGeth(ctx, txHash)
+}
diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go
index 3a3b8b23a9..af03720ced 100644
--- a/core/chains/evm/client/client.go
+++ b/core/chains/evm/client/client.go
@@ -213,7 +213,7 @@ func (client *client) HeaderByHash(ctx context.Context, h common.Hash) (*types.H
func (client *client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (clienttypes.SendTxReturnCode, error) {
err := client.SendTransaction(ctx, tx)
- return NewSendErrorReturnCode(err, client.logger, tx, fromAddress, client.pool.ChainType().IsL2())
+ return ClassifySendError(err, client.logger, tx, fromAddress, client.pool.ChainType().IsL2())
}
// SendTransaction also uses the sendonly HTTP RPC URLs if set
diff --git a/core/chains/evm/client/client_test.go b/core/chains/evm/client/client_test.go
index 88bc37411c..81a82d20fa 100644
--- a/core/chains/evm/client/client_test.go
+++ b/core/chains/evm/client/client_test.go
@@ -22,7 +22,9 @@ import (
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+
+ commontypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
@@ -43,6 +45,33 @@ func mustNewClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, send
return c
}
+func mustNewChainClient(t *testing.T, wsURL string, sendonlys ...url.URL) evmclient.Client {
+ return mustNewChainClientWithChainID(t, wsURL, testutils.FixtureChainID, sendonlys...)
+}
+
+func mustNewChainClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) evmclient.Client {
+ cfg := evmclient.TestNodePoolConfig{
+ NodeSelectionMode: evmclient.NodeSelectionMode_RoundRobin,
+ }
+ c, err := evmclient.NewChainClientWithTestNode(t, cfg, time.Second*0, cfg.NodeLeaseDuration, wsURL, nil, sendonlys, 42, chainID)
+ require.NoError(t, err)
+ return c
+}
+
+func mustNewClients(t *testing.T, wsURL string, sendonlys ...url.URL) []evmclient.Client {
+ var clients []evmclient.Client
+ clients = append(clients, mustNewClient(t, wsURL, sendonlys...))
+ clients = append(clients, mustNewChainClient(t, wsURL, sendonlys...))
+ return clients
+}
+
+func mustNewClientsWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) []evmclient.Client {
+ var clients []evmclient.Client
+ clients = append(clients, mustNewClientWithChainID(t, wsURL, chainID, sendonlys...))
+ clients = append(clients, mustNewChainClientWithChainID(t, wsURL, chainID, sendonlys...))
+ return clients
+}
+
func TestEthClient_TransactionReceipt(t *testing.T) {
t.Parallel()
@@ -78,15 +107,17 @@ func TestEthClient_TransactionReceipt(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- hash := common.HexToHash(txHash)
- receipt, err := ethClient.TransactionReceipt(testutils.Context(t), hash)
- require.NoError(t, err)
- assert.Equal(t, hash, receipt.TxHash)
- assert.Equal(t, big.NewInt(11), receipt.BlockNumber)
+ hash := common.HexToHash(txHash)
+ receipt, err := ethClient.TransactionReceipt(testutils.Context(t), hash)
+ require.NoError(t, err)
+ assert.Equal(t, hash, receipt.TxHash)
+ assert.Equal(t, big.NewInt(11), receipt.BlockNumber)
+ }
})
t.Run("no tx hash, returns ethereum.NotFound", func(t *testing.T) {
@@ -108,13 +139,15 @@ func TestEthClient_TransactionReceipt(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- hash := common.HexToHash(txHash)
- _, err = ethClient.TransactionReceipt(testutils.Context(t), hash)
- require.Equal(t, ethereum.NotFound, errors.Cause(err))
+ hash := common.HexToHash(txHash)
+ _, err = ethClient.TransactionReceipt(testutils.Context(t), hash)
+ require.Equal(t, ethereum.NotFound, errors.Cause(err))
+ }
})
}
@@ -144,15 +177,17 @@ func TestEthClient_PendingNonceAt(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- result, err := ethClient.PendingNonceAt(testutils.Context(t), address)
- require.NoError(t, err)
+ result, err := ethClient.PendingNonceAt(testutils.Context(t), address)
+ require.NoError(t, err)
- var expected uint64 = 256
- require.Equal(t, result, expected)
+ var expected uint64 = 256
+ require.Equal(t, result, expected)
+ }
}
func TestEthClient_BalanceAt(t *testing.T) {
@@ -189,13 +224,15 @@ func TestEthClient_BalanceAt(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- result, err := ethClient.BalanceAt(testutils.Context(t), address, nil)
- require.NoError(t, err)
- assert.Equal(t, test.balance, result)
+ result, err := ethClient.BalanceAt(testutils.Context(t), address, nil)
+ require.NoError(t, err)
+ assert.Equal(t, test.balance, result)
+ }
})
}
}
@@ -220,13 +257,15 @@ func TestEthClient_LatestBlockHeight(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- result, err := ethClient.LatestBlockHeight(testutils.Context(t))
- require.NoError(t, err)
- require.Equal(t, big.NewInt(256), result)
+ result, err := ethClient.LatestBlockHeight(testutils.Context(t))
+ require.NoError(t, err)
+ require.Equal(t, big.NewInt(256), result)
+ }
}
func TestEthClient_GetERC20Balance(t *testing.T) {
@@ -277,13 +316,15 @@ func TestEthClient_GetERC20Balance(t *testing.T) {
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- result, err := ethClient.TokenBalance(ctx, userAddress, contractAddress)
- require.NoError(t, err)
- assert.Equal(t, test.balance, result)
+ result, err := ethClient.TokenBalance(ctx, userAddress, contractAddress)
+ require.NoError(t, err)
+ assert.Equal(t, test.balance, result)
+ }
})
}
}
@@ -354,20 +395,22 @@ func TestEthClient_HeaderByNumber(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
-
- ctx, cancel := context.WithTimeout(testutils.Context(t), 5*time.Second)
- defer cancel()
- result, err := ethClient.HeadByNumber(ctx, expectedBlockNum)
- if test.error != nil {
- require.Error(t, err, test.error)
- } else {
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
require.NoError(t, err)
- require.Equal(t, expectedBlockHash, result.Hash.Hex())
- require.Equal(t, test.expectedResponseBlock, result.Number)
- require.Zero(t, cltest.FixtureChainID.Cmp(result.EVMChainID.ToInt()))
+
+ ctx, cancel := context.WithTimeout(testutils.Context(t), 5*time.Second)
+ result, err := ethClient.HeadByNumber(ctx, expectedBlockNum)
+ if test.error != nil {
+ require.Error(t, err, test.error)
+ } else {
+ require.NoError(t, err)
+ require.Equal(t, expectedBlockHash, result.Hash.Hex())
+ require.Equal(t, test.expectedResponseBlock, result.Number)
+ require.Zero(t, cltest.FixtureChainID.Cmp(result.EVMChainID.ToInt()))
+ }
+ cancel()
}
})
}
@@ -395,12 +438,14 @@ func TestEthClient_SendTransaction_NoSecondaryURL(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- err = ethClient.SendTransaction(testutils.Context(t), tx)
- assert.NoError(t, err)
+ err = ethClient.SendTransaction(testutils.Context(t), tx)
+ assert.NoError(t, err)
+ }
}
func TestEthClient_SendTransaction_WithSecondaryURLs(t *testing.T) {
@@ -432,16 +477,19 @@ func TestEthClient_SendTransaction_WithSecondaryURLs(t *testing.T) {
t.Cleanup(ts.Close)
sendonlyURL := *cltest.MustParseURL(t, ts.URL)
- ethClient := mustNewClient(t, wsURL, sendonlyURL, sendonlyURL)
- err = ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
- err = ethClient.SendTransaction(testutils.Context(t), tx)
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL, sendonlyURL, sendonlyURL)
+ for _, ethClient := range clients {
+ err = ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
+
+ err = ethClient.SendTransaction(testutils.Context(t), tx)
+ require.NoError(t, err)
+ }
// Unfortunately it's a bit tricky to test this, since there is no
// synchronization. We have to rely on timing instead.
- require.Eventually(t, func() bool { return service.sentCount.Load() == int32(2) }, testutils.WaitTimeout(t), 500*time.Millisecond)
+ require.Eventually(t, func() bool { return service.sentCount.Load() == int32(len(clients)*2) }, testutils.WaitTimeout(t), 500*time.Millisecond)
}
func TestEthClient_SendTransactionReturnCode(t *testing.T) {
@@ -467,13 +515,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.Fatal)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.Fatal)
+ }
})
t.Run("returns TransactionAlreadyKnown error type when error message is nonce too low", func(t *testing.T) {
@@ -493,13 +543,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.TransactionAlreadyKnown)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.TransactionAlreadyKnown)
+ }
})
t.Run("returns Successful error type when there is no error message", func(t *testing.T) {
@@ -518,13 +570,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.NoError(t, err)
- assert.Equal(t, errType, clienttypes.Successful)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.NoError(t, err)
+ assert.Equal(t, errType, commontypes.Successful)
+ }
})
t.Run("returns Underpriced error type when transaction is terminally underpriced", func(t *testing.T) {
@@ -544,13 +598,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.Underpriced)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.Underpriced)
+ }
})
t.Run("returns Unsupported error type when error message is queue full", func(t *testing.T) {
@@ -570,13 +626,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.Unsupported)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.Unsupported)
+ }
})
t.Run("returns Retryable error type when there is a transaction gap", func(t *testing.T) {
@@ -596,13 +654,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.Retryable)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.Retryable)
+ }
})
t.Run("returns InsufficientFunds error type when the sender address doesn't have enough funds", func(t *testing.T) {
@@ -622,13 +682,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.InsufficientFunds)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.InsufficientFunds)
+ }
})
t.Run("returns ExceedsFeeCap error type when gas price is too high for the node", func(t *testing.T) {
@@ -648,13 +710,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.ExceedsMaxFee)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.ExceedsMaxFee)
+ }
})
t.Run("returns Unknown error type when the error can't be categorized", func(t *testing.T) {
@@ -674,13 +738,15 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
return
})
- ethClient := mustNewClient(t, wsURL)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClients(t, wsURL)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
- assert.Error(t, err)
- assert.Equal(t, errType, clienttypes.Unknown)
+ errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
+ assert.Error(t, err)
+ assert.Equal(t, errType, commontypes.Unknown)
+ }
})
}
@@ -718,24 +784,132 @@ func TestEthClient_SubscribeNewHead(t *testing.T) {
return
})
- ethClient := mustNewClientWithChainID(t, wsURL, chainId)
- err := ethClient.Dial(testutils.Context(t))
- require.NoError(t, err)
+ clients := mustNewClientsWithChainID(t, wsURL, chainId)
+ for _, ethClient := range clients {
+ err := ethClient.Dial(testutils.Context(t))
+ require.NoError(t, err)
- headCh := make(chan *evmtypes.Head)
- sub, err := ethClient.SubscribeNewHead(ctx, headCh)
- require.NoError(t, err)
- defer sub.Unsubscribe()
-
- select {
- case err := <-sub.Err():
- t.Fatal(err)
- case <-ctx.Done():
- t.Fatal(ctx.Err())
- case h := <-headCh:
- require.NotNil(t, h.EVMChainID)
- require.Zero(t, chainId.Cmp(h.EVMChainID.ToInt()))
+ headCh := make(chan *evmtypes.Head)
+ sub, err := ethClient.SubscribeNewHead(ctx, headCh)
+ require.NoError(t, err)
+
+ select {
+ case err := <-sub.Err():
+ t.Fatal(err)
+ case <-ctx.Done():
+ t.Fatal(ctx.Err())
+ case h := <-headCh:
+ require.NotNil(t, h.EVMChainID)
+ require.Zero(t, chainId.Cmp(h.EVMChainID.ToInt()))
+ }
+ sub.Unsubscribe()
}
}
+func TestEthClient_ErroringClient(t *testing.T) {
+ t.Parallel()
+ ctx := testutils.Context(t)
+
+ // Empty node means there are no active nodes to select from, causing client to always return error.
+ erroringClient := evmclient.NewChainClientWithEmptyNode(t, commonclient.NodeSelectionModeRoundRobin, time.Second*0, time.Second*0, testutils.FixtureChainID)
+
+ _, err := erroringClient.BalanceAt(ctx, common.Address{}, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ err = erroringClient.BatchCallContext(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ err = erroringClient.BatchCallContextAll(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.BlockByHash(ctx, common.Hash{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.BlockByNumber(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ err = erroringClient.CallContext(ctx, nil, "")
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.CallContract(ctx, ethereum.CallMsg{}, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ // TODO-1663: test actual ChainID() call once client.go is deprecated.
+ id, err := erroringClient.ChainID()
+ require.Equal(t, id, testutils.FixtureChainID)
+ //require.Equal(t, err, commonclient.ErroringNodeError)
+ require.Equal(t, err, nil)
+
+ _, err = erroringClient.CodeAt(ctx, common.Address{}, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ id = erroringClient.ConfiguredChainID()
+ require.Equal(t, id, testutils.FixtureChainID)
+
+ err = erroringClient.Dial(ctx)
+ require.ErrorContains(t, err, "no available nodes for chain")
+
+ _, err = erroringClient.EstimateGas(ctx, ethereum.CallMsg{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.FilterLogs(ctx, ethereum.FilterQuery{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.HeaderByHash(ctx, common.Hash{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.HeaderByNumber(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.HeadByHash(ctx, common.Hash{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.HeadByNumber(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.LINKBalance(ctx, common.Address{}, common.Address{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.LatestBlockHeight(ctx)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.PendingCodeAt(ctx, common.Address{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.PendingNonceAt(ctx, common.Address{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ err = erroringClient.SendTransaction(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ code, err := erroringClient.SendTransactionReturnCode(ctx, nil, common.Address{})
+ require.Equal(t, code, commontypes.Unknown)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.SequenceAt(ctx, common.Address{}, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.SubscribeNewHead(ctx, nil)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.SuggestGasPrice(ctx)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.SuggestGasTipCap(ctx)
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.TokenBalance(ctx, common.Address{}, common.Address{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.TransactionByHash(ctx, common.Hash{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+ _, err = erroringClient.TransactionReceipt(ctx, common.Hash{})
+ require.Equal(t, err, commonclient.ErroringNodeError)
+
+}
+
const headResult = evmclient.HeadResult
diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go
index 7b89e7b92d..7197d77b3d 100644
--- a/core/chains/evm/client/errors.go
+++ b/core/chains/evm/client/errors.go
@@ -397,7 +397,7 @@ func ExtractRPCError(baseErr error) (*JsonError, error) {
return &jErr, nil
}
-func NewSendErrorReturnCode(err error, lggr logger.Logger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (clienttypes.SendTxReturnCode, error) {
+func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (clienttypes.SendTxReturnCode, error) {
sendError := NewSendError(err)
if sendError == nil {
return clienttypes.Successful, err
@@ -465,3 +465,15 @@ func NewSendErrorReturnCode(err error, lggr logger.Logger, tx *types.Transaction
}
return clienttypes.Unknown, err
}
+
+// ClassifySendOnlyError handles SendOnly nodes error codes. In that case, we don't assume there is another transaction that will be correctly
+// priced.
+func ClassifySendOnlyError(err error) clienttypes.SendTxReturnCode {
+ sendError := NewSendError(err)
+ if sendError == nil || sendError.IsNonceTooLowError() || sendError.IsTransactionAlreadyMined() || sendError.IsTransactionAlreadyInMempool() {
+ // Nonce too low or transaction known errors are expected since
+ // the primary SendTransaction may well have succeeded already
+ return clienttypes.Successful
+ }
+ return clienttypes.Fatal
+}
diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go
index 342a914343..8552b2c0a0 100644
--- a/core/chains/evm/client/helpers_test.go
+++ b/core/chains/evm/client/helpers_test.go
@@ -9,7 +9,11 @@ import (
"github.com/pkg/errors"
+ clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
+ evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -64,6 +68,67 @@ func Wrap(err error, s string) error {
return wrap(err, s)
}
+func NewChainClientWithTestNode(
+ t *testing.T,
+ nodeCfg commonclient.NodeConfig,
+ noNewHeadsThreshold time.Duration,
+ leaseDuration time.Duration,
+ rpcUrl string,
+ rpcHTTPURL *url.URL,
+ sendonlyRPCURLs []url.URL,
+ id int32,
+ chainID *big.Int,
+) (Client, error) {
+ parsed, err := url.ParseRequestURI(rpcUrl)
+ if err != nil {
+ return nil, err
+ }
+
+ if parsed.Scheme != "ws" && parsed.Scheme != "wss" {
+ return nil, errors.Errorf("ethereum url scheme must be websocket: %s", parsed.String())
+ }
+
+ lggr := logger.TestLogger(t)
+ rpc := NewRPCClient(lggr, *parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, clienttypes.Primary)
+
+ n := commonclient.NewNode[*big.Int, *evmtypes.Head, RPCCLient](
+ nodeCfg, noNewHeadsThreshold, lggr, *parsed, rpcHTTPURL, "eth-primary-node-0", id, chainID, 1, rpc, "EVM")
+ primaries := []commonclient.Node[*big.Int, *evmtypes.Head, RPCCLient]{n}
+
+ var sendonlys []commonclient.SendOnlyNode[*big.Int, RPCCLient]
+ for i, u := range sendonlyRPCURLs {
+ if u.Scheme != "http" && u.Scheme != "https" {
+ return nil, errors.Errorf("sendonly ethereum rpc url scheme must be http(s): %s", u.String())
+ }
+ var empty url.URL
+ rpc := NewRPCClient(lggr, empty, &sendonlyRPCURLs[i], fmt.Sprintf("eth-sendonly-rpc-%d", i), id, chainID, clienttypes.Secondary)
+ s := commonclient.NewSendOnlyNode[*big.Int, RPCCLient](
+ lggr, u, fmt.Sprintf("eth-sendonly-%d", i), chainID, rpc)
+ sendonlys = append(sendonlys, s)
+ }
+
+ var chainType commonconfig.ChainType
+ c := NewChainClient(lggr, nodeCfg.SelectionMode(), leaseDuration, noNewHeadsThreshold, primaries, sendonlys, chainID, chainType)
+ t.Cleanup(c.Close)
+ return c, nil
+}
+
+func NewChainClientWithEmptyNode(
+ t *testing.T,
+ selectionMode string,
+ leaseDuration time.Duration,
+ noNewHeadsThreshold time.Duration,
+ chainID *big.Int,
+) Client {
+
+ lggr := logger.TestLogger(t)
+
+ var chainType commonconfig.ChainType
+ c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, nil, nil, chainID, chainType)
+ t.Cleanup(c.Close)
+ return c
+}
+
type TestableSendOnlyNode interface {
SendOnlyNode
SetEthClient(newBatchSender BatchSender, newSender TxSender)
diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go
new file mode 100644
index 0000000000..b6ed84eee4
--- /dev/null
+++ b/core/chains/evm/client/rpc_client.go
@@ -0,0 +1,1046 @@
+package client
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+ "net/url"
+ "strconv"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/ethereum/go-ethereum/rpc"
+ "github.com/google/uuid"
+ "github.com/pkg/errors"
+
+ clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+ commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/assets"
+ evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+// RPCCLient includes all the necessary generalized RPC methods along with any additional chain-specific methods.
+type RPCCLient interface {
+ commonclient.RPC[
+ *big.Int,
+ evmtypes.Nonce,
+ common.Address,
+ common.Hash,
+ *types.Transaction,
+ common.Hash,
+ types.Log,
+ ethereum.FilterQuery,
+ *evmtypes.Receipt,
+ *assets.Wei,
+ *evmtypes.Head,
+ ]
+ BlockByHashGeth(ctx context.Context, hash common.Hash) (b *types.Block, err error)
+ BlockByNumberGeth(ctx context.Context, number *big.Int) (b *types.Block, err error)
+ HeaderByHash(ctx context.Context, h common.Hash) (head *types.Header, err error)
+ HeaderByNumber(ctx context.Context, n *big.Int) (head *types.Header, err error)
+ PendingCodeAt(ctx context.Context, account common.Address) (b []byte, err error)
+ SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (s ethereum.Subscription, err error)
+ SuggestGasPrice(ctx context.Context) (p *big.Int, err error)
+ SuggestGasTipCap(ctx context.Context) (t *big.Int, err error)
+ TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (r *types.Receipt, err error)
+}
+
+type rpcClient struct {
+ rpcLog logger.Logger
+ name string
+ id int32
+ chainID *big.Int
+ tier clienttypes.NodeTier
+
+ ws rawclient
+ http *rawclient
+
+ stateMu sync.RWMutex // protects state* fields
+
+ // Need to track subscriptions because closing the RPC does not (always?)
+ // close the underlying subscription
+ subs []ethereum.Subscription
+
+ // Need to track the aliveLoop subscription, so we do not cancel it when checking lease on the MultiNode
+ aliveLoopSub ethereum.Subscription
+
+ // chStopInFlight can be closed to immediately cancel all in-flight requests on
+ // this rpcClient. Closing and replacing should be serialized through
+ // stateMu since it can happen on state transitions as well as rpcClient Close.
+ chStopInFlight chan struct{}
+}
+
+// NewRPCCLient returns a new *rpcClient as commonclient.RPC
+func NewRPCClient(
+ lggr logger.Logger,
+ wsuri url.URL,
+ httpuri *url.URL,
+ name string,
+ id int32,
+ chainID *big.Int,
+ tier clienttypes.NodeTier,
+) RPCCLient {
+ r := new(rpcClient)
+ r.name = name
+ r.id = id
+ r.chainID = chainID
+ r.tier = tier
+ r.ws.uri = wsuri
+ if httpuri != nil {
+ r.http = &rawclient{uri: *httpuri}
+ }
+ r.chStopInFlight = make(chan struct{})
+ lggr = lggr.Named("Client").With(
+ "clientTier", tier.String(),
+ "clientName", name,
+ "client", r.String(),
+ "evmChainID", chainID,
+ )
+ r.rpcLog = lggr.Named("RPC")
+
+ return r
+}
+
+// Not thread-safe, pure dial.
+func (r *rpcClient) Dial(callerCtx context.Context) error {
+ ctx, cancel := r.makeQueryCtx(callerCtx)
+ defer cancel()
+
+ promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc()
+ lggr := r.rpcLog.With("wsuri", r.ws.uri.Redacted())
+ if r.http != nil {
+ lggr = lggr.With("httpuri", r.http.uri.Redacted())
+ }
+ lggr.Debugw("RPC dial: evmclient.Client#dial")
+
+ wsrpc, err := rpc.DialWebsocket(ctx, r.ws.uri.String(), "")
+ if err != nil {
+ promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc()
+ return errors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted())
+ }
+
+ r.ws.rpc = wsrpc
+ r.ws.geth = ethclient.NewClient(wsrpc)
+
+ if r.http != nil {
+ if err := r.DialHTTP(); err != nil {
+ return err
+ }
+ }
+
+ promEVMPoolRPCNodeDialsSuccess.WithLabelValues(r.chainID.String(), r.name).Inc()
+
+ return nil
+}
+
+// Not thread-safe, pure dial.
+// DialHTTP doesn't actually make any external HTTP calls
+// It can only return error if the URL is malformed.
+func (r *rpcClient) DialHTTP() error {
+ promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc()
+ lggr := r.rpcLog.With("httpuri", r.ws.uri.Redacted())
+ lggr.Debugw("RPC dial: evmclient.Client#dial")
+
+ var httprpc *rpc.Client
+ httprpc, err := rpc.DialHTTP(r.http.uri.String())
+ if err != nil {
+ promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc()
+ return errors.Wrapf(err, "error while dialing HTTP: %v", r.http.uri.Redacted())
+ }
+
+ r.http.rpc = httprpc
+ r.http.geth = ethclient.NewClient(httprpc)
+
+ promEVMPoolRPCNodeDialsSuccess.WithLabelValues(r.chainID.String(), r.name).Inc()
+
+ return nil
+}
+
+func (r *rpcClient) Close() {
+ defer func() {
+ if r.ws.rpc != nil {
+ r.ws.rpc.Close()
+ }
+ }()
+
+ r.stateMu.Lock()
+ defer r.stateMu.Unlock()
+ r.cancelInflightRequests()
+}
+
+// cancelInflightRequests closes and replaces the chStopInFlight
+// WARNING: NOT THREAD-SAFE
+// This must be called from within the r.stateMu lock
+func (r *rpcClient) cancelInflightRequests() {
+ close(r.chStopInFlight)
+ r.chStopInFlight = make(chan struct{})
+}
+
+func (r *rpcClient) String() string {
+ s := fmt.Sprintf("(%s)%s:%s", r.tier.String(), r.name, r.ws.uri.Redacted())
+ if r.http != nil {
+ s = s + fmt.Sprintf(":%s", r.http.uri.Redacted())
+ }
+ return s
+}
+
+func (r *rpcClient) logResult(
+ lggr logger.Logger,
+ err error,
+ callDuration time.Duration,
+ rpcDomain,
+ callName string,
+ results ...interface{},
+) {
+ lggr = lggr.With("duration", callDuration, "rpcDomain", rpcDomain, "callName", callName)
+ promEVMPoolRPCNodeCalls.WithLabelValues(r.chainID.String(), r.name).Inc()
+ if err == nil {
+ promEVMPoolRPCNodeCallsSuccess.WithLabelValues(r.chainID.String(), r.name).Inc()
+ lggr.Tracew(
+ fmt.Sprintf("evmclient.Client#%s RPC call success", callName),
+ results...,
+ )
+ } else {
+ promEVMPoolRPCNodeCallsFailed.WithLabelValues(r.chainID.String(), r.name).Inc()
+ lggr.Debugw(
+ fmt.Sprintf("evmclient.Client#%s RPC call failure", callName),
+ append(results, "err", err)...,
+ )
+ }
+ promEVMPoolRPCCallTiming.
+ WithLabelValues(
+ r.chainID.String(), // chain id
+ r.name, // rpcClient name
+ rpcDomain, // rpc domain
+ "false", // is send only
+ strconv.FormatBool(err == nil), // is successful
+ callName, // rpc call name
+ ).
+ Observe(float64(callDuration))
+}
+
+func (r *rpcClient) getRPCDomain() string {
+ if r.http != nil {
+ return r.http.uri.Host
+ }
+ return r.ws.uri.Host
+}
+
+// registerSub adds the sub to the rpcClient list
+func (r *rpcClient) registerSub(sub ethereum.Subscription) {
+ r.stateMu.Lock()
+ defer r.stateMu.Unlock()
+ r.subs = append(r.subs, sub)
+}
+
+// disconnectAll disconnects all clients connected to the rpcClient
+// WARNING: NOT THREAD-SAFE
+// This must be called from within the r.stateMu lock
+func (r *rpcClient) DisconnectAll() {
+ if r.ws.rpc != nil {
+ r.ws.rpc.Close()
+ }
+ r.cancelInflightRequests()
+ r.unsubscribeAll()
+}
+
+// unsubscribeAll unsubscribes all subscriptions
+// WARNING: NOT THREAD-SAFE
+// This must be called from within the r.stateMu lock
+func (r *rpcClient) unsubscribeAll() {
+ for _, sub := range r.subs {
+ sub.Unsubscribe()
+ }
+ r.subs = nil
+}
+func (r *rpcClient) SetAliveLoopSub(sub commontypes.Subscription) {
+ r.stateMu.Lock()
+ defer r.stateMu.Unlock()
+
+ r.aliveLoopSub = sub
+}
+
+// SubscribersCount returns the number of client subscribed to the node
+func (r *rpcClient) SubscribersCount() int32 {
+ r.stateMu.RLock()
+ defer r.stateMu.RUnlock()
+ return int32(len(r.subs))
+}
+
+// UnsubscribeAllExceptAliveLoop disconnects all subscriptions to the node except the alive loop subscription
+// while holding the n.stateMu lock
+func (r *rpcClient) UnsubscribeAllExceptAliveLoop() {
+ r.stateMu.Lock()
+ defer r.stateMu.Unlock()
+
+ for _, s := range r.subs {
+ if s != r.aliveLoopSub {
+ s.Unsubscribe()
+ }
+ }
+}
+
+// RPC wrappers
+
+// 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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With(
+ "method", method,
+ "args", args,
+ )
+
+ lggr.Debug("RPC call: evmclient.Client#CallContext")
+ start := time.Now()
+ if http != nil {
+ err = r.wrapHTTP(http.rpc.CallContext(ctx, result, method, args...))
+ } else {
+ err = r.wrapWS(ws.rpc.CallContext(ctx, result, method, args...))
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "CallContext")
+
+ return err
+}
+
+func (r *rpcClient) BatchCallContext(ctx context.Context, b []any) error {
+ ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx)
+ if err != nil {
+ return err
+ }
+ batch := make([]rpc.BatchElem, len(b))
+ for i, arg := range b {
+ batch[i] = arg.(rpc.BatchElem)
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("nBatchElems", len(b), "batchElems", b)
+
+ lggr.Trace("RPC call: evmclient.Client#BatchCallContext")
+ start := time.Now()
+ if http != nil {
+ err = r.wrapHTTP(http.rpc.BatchCallContext(ctx, batch))
+ } else {
+ err = r.wrapWS(ws.rpc.BatchCallContext(ctx, batch))
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "BatchCallContext")
+
+ return 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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("args", args)
+
+ lggr.Debug("RPC call: evmclient.Client#EthSubscribe")
+ start := time.Now()
+ sub, err := ws.rpc.EthSubscribe(ctx, channel, args...)
+ if err == nil {
+ r.registerSub(sub)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe")
+
+ return sub, err
+}
+
+// GethClient wrappers
+
+func (r *rpcClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (receipt *evmtypes.Receipt, err error) {
+ err = r.CallContext(ctx, &receipt, "eth_getTransactionReceipt", txHash, false)
+ if err != nil {
+ return nil, err
+ }
+ if receipt == nil {
+ err = 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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("txHash", txHash)
+
+ lggr.Debug("RPC call: evmclient.Client#TransactionReceipt")
+
+ start := time.Now()
+ if http != nil {
+ receipt, err = http.geth.TransactionReceipt(ctx, txHash)
+ err = r.wrapHTTP(err)
+ } else {
+ receipt, err = ws.geth.TransactionReceipt(ctx, txHash)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "TransactionReceipt",
+ "receipt", receipt,
+ )
+
+ 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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("txHash", txHash)
+
+ lggr.Debug("RPC call: evmclient.Client#TransactionByHash")
+
+ start := time.Now()
+ if http != nil {
+ tx, _, err = http.geth.TransactionByHash(ctx, txHash)
+ err = r.wrapHTTP(err)
+ } else {
+ tx, _, err = ws.geth.TransactionByHash(ctx, txHash)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "TransactionByHash",
+ "receipt", tx,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("number", number)
+
+ lggr.Debug("RPC call: evmclient.Client#HeaderByNumber")
+ start := time.Now()
+ if http != nil {
+ header, err = http.geth.HeaderByNumber(ctx, number)
+ err = r.wrapHTTP(err)
+ } else {
+ header, err = ws.geth.HeaderByNumber(ctx, number)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "HeaderByNumber", "header", header)
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("hash", hash)
+
+ lggr.Debug("RPC call: evmclient.Client#HeaderByHash")
+ start := time.Now()
+ if http != nil {
+ header, err = http.geth.HeaderByHash(ctx, hash)
+ err = r.wrapHTTP(err)
+ } else {
+ header, err = ws.geth.HeaderByHash(ctx, hash)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "HeaderByHash",
+ "header", header,
+ )
+
+ return
+}
+
+func (r *rpcClient) BlockByNumber(ctx context.Context, number *big.Int) (head *evmtypes.Head, err error) {
+ hex := ToBlockNumArg(number)
+ err = r.CallContext(ctx, &head, "eth_getBlockByNumber", hex, false)
+ if err != nil {
+ return nil, err
+ }
+ if head == nil {
+ err = ethereum.NotFound
+ return
+ }
+ head.EVMChainID = utils.NewBig(r.chainID)
+ return
+}
+
+func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *evmtypes.Head, err error) {
+ err = r.CallContext(ctx, &head, "eth_getBlockByHash", hash.Hex(), false)
+ if err != nil {
+ return nil, err
+ }
+ if head == nil {
+ err = ethereum.NotFound
+ return
+ }
+ head.EVMChainID = utils.NewBig(r.chainID)
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("hash", hash)
+
+ lggr.Debug("RPC call: evmclient.Client#BlockByHash")
+ start := time.Now()
+ if http != nil {
+ block, err = http.geth.BlockByHash(ctx, hash)
+ err = r.wrapHTTP(err)
+ } else {
+ block, err = ws.geth.BlockByHash(ctx, hash)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "BlockByHash",
+ "block", block,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("number", number)
+
+ lggr.Debug("RPC call: evmclient.Client#BlockByNumber")
+ start := time.Now()
+ if http != nil {
+ block, err = http.geth.BlockByNumber(ctx, number)
+ err = r.wrapHTTP(err)
+ } else {
+ block, err = ws.geth.BlockByNumber(ctx, number)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "BlockByNumber",
+ "block", block,
+ )
+
+ return
+}
+
+func (r *rpcClient) SendTransaction(ctx context.Context, tx *types.Transaction) error {
+ ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx)
+ if err != nil {
+ return err
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("tx", tx)
+
+ lggr.Debug("RPC call: evmclient.Client#SendTransaction")
+ start := time.Now()
+ if http != nil {
+ err = r.wrapHTTP(http.geth.SendTransaction(ctx, tx))
+ } else {
+ err = r.wrapWS(ws.geth.SendTransaction(ctx, tx))
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "SendTransaction")
+
+ return err
+}
+
+func (r *rpcClient) SimulateTransaction(ctx context.Context, tx *types.Transaction) error {
+ // Not Implemented
+ return errors.New("SimulateTransaction not implemented")
+}
+
+func (r *rpcClient) SendEmptyTransaction(
+ ctx context.Context,
+ newTxAttempt func(nonce evmtypes.Nonce, feeLimit uint32, fee *assets.Wei, fromAddress common.Address) (attempt any, err error),
+ nonce evmtypes.Nonce,
+ gasLimit uint32,
+ fee *assets.Wei,
+ fromAddress common.Address,
+) (txhash string, err error) {
+ // Not Implemented
+ return "", errors.New("SendEmptyTransaction not implemented")
+}
+
+// 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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("account", account)
+
+ lggr.Debug("RPC call: evmclient.Client#PendingNonceAt")
+ start := time.Now()
+ var n uint64
+ if http != nil {
+ n, err = http.geth.PendingNonceAt(ctx, account)
+ nonce = evmtypes.Nonce(int64(n))
+ err = r.wrapHTTP(err)
+ } else {
+ n, err = ws.geth.PendingNonceAt(ctx, account)
+ nonce = evmtypes.Nonce(int64(n))
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "PendingNonceAt",
+ "nonce", nonce,
+ )
+
+ return
+}
+
+// SequenceAt is a bit of a misnomer. You might expect it to return the highest
+// 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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber)
+
+ lggr.Debug("RPC call: evmclient.Client#NonceAt")
+ start := time.Now()
+ var n uint64
+ if http != nil {
+ n, err = http.geth.NonceAt(ctx, account, blockNumber)
+ nonce = evmtypes.Nonce(int64(n))
+ err = r.wrapHTTP(err)
+ } else {
+ n, err = ws.geth.NonceAt(ctx, account, blockNumber)
+ nonce = evmtypes.Nonce(int64(n))
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "NonceAt",
+ "nonce", nonce,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("account", account)
+
+ lggr.Debug("RPC call: evmclient.Client#PendingCodeAt")
+ start := time.Now()
+ if http != nil {
+ code, err = http.geth.PendingCodeAt(ctx, account)
+ err = r.wrapHTTP(err)
+ } else {
+ code, err = ws.geth.PendingCodeAt(ctx, account)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "PendingCodeAt",
+ "code", code,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber)
+
+ lggr.Debug("RPC call: evmclient.Client#CodeAt")
+ start := time.Now()
+ if http != nil {
+ code, err = http.geth.CodeAt(ctx, account, blockNumber)
+ err = r.wrapHTTP(err)
+ } else {
+ code, err = ws.geth.CodeAt(ctx, account, blockNumber)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "CodeAt",
+ "code", code,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ call := c.(ethereum.CallMsg)
+ lggr := r.newRqLggr().With("call", call)
+
+ lggr.Debug("RPC call: evmclient.Client#EstimateGas")
+ start := time.Now()
+ if http != nil {
+ gas, err = http.geth.EstimateGas(ctx, call)
+ err = r.wrapHTTP(err)
+ } else {
+ gas, err = ws.geth.EstimateGas(ctx, call)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "EstimateGas",
+ "gas", gas,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr()
+
+ lggr.Debug("RPC call: evmclient.Client#SuggestGasPrice")
+ start := time.Now()
+ if http != nil {
+ price, err = http.geth.SuggestGasPrice(ctx)
+ err = r.wrapHTTP(err)
+ } else {
+ price, err = ws.geth.SuggestGasPrice(ctx)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "SuggestGasPrice",
+ "price", price,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("callMsg", msg, "blockNumber", blockNumber)
+ message := msg.(ethereum.CallMsg)
+
+ lggr.Debug("RPC call: evmclient.Client#CallContract")
+ start := time.Now()
+ if http != nil {
+ val, err = http.geth.CallContract(ctx, message, blockNumber)
+ err = r.wrapHTTP(err)
+ } else {
+ val, err = ws.geth.CallContract(ctx, message, blockNumber)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "CallContract",
+ "val", val,
+ )
+
+ return
+
+}
+
+func (r *rpcClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) {
+ var height big.Int
+ h, err := r.BlockNumber(ctx)
+ return height.SetUint64(h), err
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr()
+
+ lggr.Debug("RPC call: evmclient.Client#BlockNumber")
+ start := time.Now()
+ if http != nil {
+ height, err = http.geth.BlockNumber(ctx)
+ err = r.wrapHTTP(err)
+ } else {
+ height, err = ws.geth.BlockNumber(ctx)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "BlockNumber",
+ "height", height,
+ )
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("account", account.Hex(), "blockNumber", blockNumber)
+
+ lggr.Debug("RPC call: evmclient.Client#BalanceAt")
+ start := time.Now()
+ if http != nil {
+ balance, err = http.geth.BalanceAt(ctx, account, blockNumber)
+ err = r.wrapHTTP(err)
+ } else {
+ balance, err = ws.geth.BalanceAt(ctx, account, blockNumber)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "BalanceAt",
+ "balance", balance,
+ )
+
+ return
+}
+
+// TokenBalance returns the balance of the given address for the token contract address.
+func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, contractAddress common.Address) (*big.Int, error) {
+ result := ""
+ numLinkBigInt := new(big.Int)
+ functionSelector := evmtypes.HexToFunctionSelector(BALANCE_OF_ADDRESS_FUNCTION_SELECTOR) // balanceOf(address)
+ data := utils.ConcatBytes(functionSelector.Bytes(), common.LeftPadBytes(address.Bytes(), utils.EVMWordByteLen))
+ args := CallArgs{
+ To: contractAddress,
+ Data: data,
+ }
+ err := r.CallContext(ctx, &result, "eth_call", args, "latest")
+ if err != nil {
+ return numLinkBigInt, err
+ }
+ numLinkBigInt.SetString(result, 0)
+ return numLinkBigInt, nil
+}
+
+// LINKBalance returns the balance of LINK at the given address
+func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*assets.Link, error) {
+ balance, err := r.TokenBalance(ctx, address, linkAddress)
+ if err != nil {
+ return assets.NewLinkFromJuels(0), err
+ }
+ return (*assets.Link)(balance), nil
+}
+
+func (r *rpcClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
+ return r.FilterLogs(ctx, q)
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("q", q)
+
+ lggr.Debug("RPC call: evmclient.Client#FilterLogs")
+ start := time.Now()
+ if http != nil {
+ l, err = http.geth.FilterLogs(ctx, q)
+ err = r.wrapHTTP(err)
+ } else {
+ l, err = ws.geth.FilterLogs(ctx, q)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "FilterLogs",
+ "log", l,
+ )
+
+ return
+}
+
+func (r *rpcClient) ClientVersion(ctx context.Context) (version string, err error) {
+ err = r.CallContext(ctx, &version, "web3_clientVersion")
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr().With("q", q)
+
+ lggr.Debug("RPC call: evmclient.Client#SubscribeFilterLogs")
+ start := time.Now()
+ sub, err = ws.geth.SubscribeFilterLogs(ctx, q, ch)
+ if err == nil {
+ r.registerSub(sub)
+ }
+ err = r.wrapWS(err)
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "SubscribeFilterLogs")
+
+ return
+}
+
+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
+ }
+ defer cancel()
+ lggr := r.newRqLggr()
+
+ lggr.Debug("RPC call: evmclient.Client#SuggestGasTipCap")
+ start := time.Now()
+ if http != nil {
+ tipCap, err = http.geth.SuggestGasTipCap(ctx)
+ err = r.wrapHTTP(err)
+ } else {
+ tipCap, err = ws.geth.SuggestGasTipCap(ctx)
+ err = r.wrapWS(err)
+ }
+ duration := time.Since(start)
+
+ r.logResult(lggr, err, duration, r.getRPCDomain(), "SuggestGasTipCap",
+ "tipCap", tipCap,
+ )
+
+ return
+}
+
+// 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)
+
+ defer cancel()
+
+ if http != nil {
+ chainID, err = http.geth.ChainID(ctx)
+ err = r.wrapHTTP(err)
+ } else {
+ chainID, err = ws.geth.ChainID(ctx)
+ err = r.wrapWS(err)
+ }
+ return
+}
+
+// newRqLggr generates a new logger with a unique request ID
+func (r *rpcClient) newRqLggr() logger.Logger {
+ return r.rpcLog.With(
+ "requestID", uuid.New(),
+ )
+}
+
+func wrapCallError(err error, tp string) error {
+ if err == nil {
+ return nil
+ }
+ if errors.Cause(err).Error() == "context deadline exceeded" {
+ err = errors.Wrap(err, "remote node timed out")
+ }
+ return errors.Wrapf(err, "%s call failed", tp)
+}
+
+func (r *rpcClient) wrapWS(err error) error {
+ err = wrapCallError(err, fmt.Sprintf("%s websocket (%s)", r.tier.String(), r.ws.uri.Redacted()))
+ return err
+}
+
+func (r *rpcClient) wrapHTTP(err error) error {
+ err = wrapCallError(err, fmt.Sprintf("%s http (%s)", r.tier.String(), r.http.uri.Redacted()))
+ if err != nil {
+ r.rpcLog.Debugw("Call failed", "err", err)
+ } else {
+ r.rpcLog.Trace("Call succeeded")
+ }
+ return err
+}
+
+// makeLiveQueryCtxAndSafeGetClients wraps makeQueryCtx
+func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient, err error) {
+ // Need to wrap in mutex because state transition can cancel and replace the
+ // context
+ r.stateMu.RLock()
+ cancelCh := r.chStopInFlight
+ ws = r.ws
+ if r.http != nil {
+ cp := *r.http
+ http = &cp
+ }
+ r.stateMu.RUnlock()
+ ctx, cancel = makeQueryCtx(parentCtx, cancelCh)
+ return
+}
+
+func (r *rpcClient) makeQueryCtx(ctx context.Context) (context.Context, context.CancelFunc) {
+ return makeQueryCtx(ctx, r.getChStopInflight())
+}
+
+// getChStopInflight provides a convenience helper that mutex wraps a
+// read to the chStopInFlight
+func (r *rpcClient) getChStopInflight() chan struct{} {
+ r.stateMu.RLock()
+ defer r.stateMu.RUnlock()
+ return r.chStopInFlight
+}
+
+func (r *rpcClient) Name() string {
+ return r.name
+}
+
+func Name(r *rpcClient) string {
+ return r.name
+}
diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go
index 150ee27757..e1b1257774 100644
--- a/core/chains/evm/txmgr/client.go
+++ b/core/chains/evm/txmgr/client.go
@@ -80,7 +80,7 @@ func (c *evmTxmClient) BatchSendTransactions(
processingErr[i] = fmt.Errorf("failed to process tx (index %d): %w", i, signedErr)
return
}
- codes[i], txErrs[i] = evmclient.NewSendErrorReturnCode(reqs[i].Error, lggr, tx, attempts[i].Tx.FromAddress, c.client.IsL2())
+ codes[i], txErrs[i] = evmclient.ClassifySendError(reqs[i].Error, lggr, tx, attempts[i].Tx.FromAddress, c.client.IsL2())
}(index)
}
wg.Wait()
diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go
index 6210226120..a71c9e8716 100644
--- a/core/chains/evm/types/models.go
+++ b/core/chains/evm/types/models.go
@@ -76,6 +76,10 @@ func (h *Head) GetParent() commontypes.Head[common.Hash] {
return h.Parent
}
+func (h *Head) BlockDifficulty() *utils.Big {
+ return h.Difficulty
+}
+
// EarliestInChain recurses through parents until it finds the earliest one
func (h *Head) EarliestInChain() *Head {
for h.Parent != nil {
From 1a69590dc766a1e7b405fe03cf2e2c6e1ddee64b Mon Sep 17 00:00:00 2001
From: Dylan Tinianov
Date: Wed, 1 Nov 2023 17:12:11 -0400
Subject: [PATCH 049/327] [BCI-2313] Rename L2Suggested to SuggestedPrice
(#11093)
* Rename L2Suggested to SuggestedPrice
* Rename L2Suggested to SuggestedPrice
* update test error string
* update comment
* update docs
* generate docs
* L2Suggested backwards compatibility
* L2Suggested backwards compatibility
* Update CHANGELOG
* Update comments
* Update docs/CHANGELOG.md
Co-authored-by: amit-momin <108959691+amit-momin@users.noreply.github.com>
* Fix error message
* Move import
* deprecate L2Suggested
* Update CONFIG.md
---------
Co-authored-by: amit-momin <108959691+amit-momin@users.noreply.github.com>
Co-authored-by: Prashant Yadav <34992934+prashantkumar1982@users.noreply.github.com>
---
core/chains/evm/config/config_test.go | 2 +-
.../config/toml/defaults/Fantom_Mainnet.toml | 5 +-
.../config/toml/defaults/Fantom_Testnet.toml | 2 +-
.../config/toml/defaults/Klaytn_Mainnet.toml | 2 +-
.../config/toml/defaults/Klaytn_Testnet.toml | 2 +-
.../config/toml/defaults/Metis_Mainnet.toml | 4 +-
.../config/toml/defaults/Metis_Rinkeby.toml | 2 +-
.../config/toml/defaults/Scroll_Mainnet.toml | 4 +-
.../config/toml/defaults/Scroll_Sepolia.toml | 4 +-
core/chains/evm/gas/arbitrum_estimator.go | 8 +--
.../chains/evm/gas/arbitrum_estimator_test.go | 4 +-
core/chains/evm/gas/models.go | 4 +-
...imator.go => suggested_price_estimator.go} | 58 +++++++++----------
...t.go => suggested_price_estimator_test.go} | 18 +++---
core/config/docs/chains-evm.toml | 3 +-
core/services/chainlink/config_test.go | 4 +-
.../chainlink/testdata/config-full.toml | 2 +-
core/web/resolver/testdata/config-full.toml | 2 +-
docs/CHANGELOG.md | 8 +++
docs/CONFIG.md | 19 +++---
20 files changed, 83 insertions(+), 74 deletions(-)
rename core/chains/evm/gas/{l2_suggested_estimator.go => suggested_price_estimator.go} (60%)
rename core/chains/evm/gas/{l2_suggested_estimator_test.go => suggested_price_estimator_test.go} (87%)
diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go
index d0f9e846e3..0a3fc5f41e 100644
--- a/core/chains/evm/config/config_test.go
+++ b/core/chains/evm/config/config_test.go
@@ -423,7 +423,7 @@ func Test_chainScopedConfig_Validate(t *testing.T) {
t.Run("testnet", func(t *testing.T) {
cfg := configWithChains(t, 421611, &toml.Chain{
GasEstimator: toml.GasEstimator{
- Mode: ptr("L2Suggested"),
+ Mode: ptr("SuggestedPrice"),
},
})
assert.NoError(t, cfg.Validate())
diff --git a/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml b/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml
index 7046642bb9..c7fb6ba473 100644
--- a/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml
+++ b/core/chains/evm/config/toml/defaults/Fantom_Mainnet.toml
@@ -9,9 +9,8 @@ RPCBlockQueryDelay = 2
Enabled = true
[GasEstimator]
-# Fantom network has been slow to include txs at times when using the BlockHistory estimator, and the recommendation is to use L2Suggested mode.
-# There is work under way to improve L2Suggested mode's name so that its use on non-L2 chains will be less confusing in the future.
-Mode = 'L2Suggested'
+# Fantom network has been slow to include txs at times when using the BlockHistory estimator, and the recommendation is to use SuggestedPrice mode.
+Mode = 'SuggestedPrice'
[OCR2.Automation]
GasLimit = 3800000
\ No newline at end of file
diff --git a/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml b/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml
index 0292ed5b74..1e1aab1468 100644
--- a/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml
+++ b/core/chains/evm/config/toml/defaults/Fantom_Testnet.toml
@@ -7,7 +7,7 @@ NoNewHeadsThreshold = '0'
RPCBlockQueryDelay = 2
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
[OCR2.Automation]
GasLimit = 3800000
\ No newline at end of file
diff --git a/core/chains/evm/config/toml/defaults/Klaytn_Mainnet.toml b/core/chains/evm/config/toml/defaults/Klaytn_Mainnet.toml
index 36dc04ae96..c68f03b044 100644
--- a/core/chains/evm/config/toml/defaults/Klaytn_Mainnet.toml
+++ b/core/chains/evm/config/toml/defaults/Klaytn_Mainnet.toml
@@ -5,6 +5,6 @@ NoNewHeadsThreshold = '30s'
OCR.ContractConfirmations = 1
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '750 gwei' # gwei = ston
BumpThreshold = 0
diff --git a/core/chains/evm/config/toml/defaults/Klaytn_Testnet.toml b/core/chains/evm/config/toml/defaults/Klaytn_Testnet.toml
index 34b15ca74b..864aa0fa72 100644
--- a/core/chains/evm/config/toml/defaults/Klaytn_Testnet.toml
+++ b/core/chains/evm/config/toml/defaults/Klaytn_Testnet.toml
@@ -5,6 +5,6 @@ NoNewHeadsThreshold = '30s'
OCR.ContractConfirmations = 1
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '750 gwei' # gwei = ston
BumpThreshold = 0
diff --git a/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml b/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml
index 855fef55a7..3e8efa531c 100644
--- a/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml
+++ b/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml
@@ -8,8 +8,8 @@ NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
[GasEstimator]
-Mode = 'L2Suggested'
-# Metis uses the L2Suggested estimator; we don't want to place any limits on the minimum gas price
+Mode = 'SuggestedPrice'
+# Metis uses the SuggestedPrice estimator; we don't want to place any limits on the minimum gas price
PriceMin = '0'
# Never bump gas on metis
BumpThreshold = 0
diff --git a/core/chains/evm/config/toml/defaults/Metis_Rinkeby.toml b/core/chains/evm/config/toml/defaults/Metis_Rinkeby.toml
index 487cc22485..7d9fec9076 100644
--- a/core/chains/evm/config/toml/defaults/Metis_Rinkeby.toml
+++ b/core/chains/evm/config/toml/defaults/Metis_Rinkeby.toml
@@ -9,7 +9,7 @@ OCR.ContractConfirmations = 1
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceMin = '0'
BumpThreshold = 0
diff --git a/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml b/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml
index 63c0855901..56ed84c7f3 100644
--- a/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml
+++ b/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml
@@ -7,8 +7,8 @@ NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
[GasEstimator]
-Mode = 'L2Suggested'
-# Scroll uses the L2Suggested estimator; we don't want to place any limits on the minimum gas price
+Mode = 'SuggestedPrice'
+# Scroll uses the SuggestedPrice estimator; we don't want to place any limits on the minimum gas price
PriceMin = '0'
# Never bump gas on Scroll
BumpThreshold = 0
diff --git a/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml b/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml
index 5a1a0f9ba7..af17c4d485 100644
--- a/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml
+++ b/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml
@@ -7,8 +7,8 @@ NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
[GasEstimator]
-Mode = 'L2Suggested'
-# Scroll uses the L2Suggested estimator; we don't want to place any limits on the minimum gas price
+Mode = 'SuggestedPrice'
+# Scroll uses the SuggestedPrice estimator; we don't want to place any limits on the minimum gas price
PriceMin = '0'
# Never bump gas on Scroll
BumpThreshold = 0
diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go
index 17934bfa07..78d93243bb 100644
--- a/core/chains/evm/gas/arbitrum_estimator.go
+++ b/core/chains/evm/gas/arbitrum_estimator.go
@@ -31,12 +31,12 @@ type ethClient interface {
CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
}
-// arbitrumEstimator is an Estimator which extends l2SuggestedPriceEstimator to use getPricesInArbGas() for gas limit estimation.
+// arbitrumEstimator is an Estimator which extends SuggestedPriceEstimator to use getPricesInArbGas() for gas limit estimation.
type arbitrumEstimator struct {
services.StateMachine
cfg ArbConfig
- EvmEstimator // *l2SuggestedPriceEstimator
+ EvmEstimator // *SuggestedPriceEstimator
client ethClient
pollPeriod time.Duration
@@ -56,7 +56,7 @@ func NewArbitrumEstimator(lggr logger.Logger, cfg ArbConfig, rpcClient rpcClient
lggr = lggr.Named("ArbitrumEstimator")
return &arbitrumEstimator{
cfg: cfg,
- EvmEstimator: NewL2SuggestedPriceEstimator(lggr, rpcClient),
+ EvmEstimator: NewSuggestedPriceEstimator(lggr, rpcClient),
client: ethClient,
pollPeriod: 10 * time.Second,
logger: lggr,
@@ -99,7 +99,7 @@ func (a *arbitrumEstimator) HealthReport() map[string]error {
}
// GetLegacyGas estimates both the gas price and the gas limit.
-// - Price is delegated to the embedded l2SuggestedPriceEstimator.
+// - Price is delegated to the embedded SuggestedPriceEstimator.
// - Limit is computed from the dynamic values perL2Tx and perL1CalldataUnit, provided by the getPricesInArbGas() method
// of the precompilie contract at ArbGasInfoAddress. perL2Tx is a constant amount of gas, and perL1CalldataUnit is
// multiplied by the length of the tx calldata. The sum of these two values plus the original l2GasLimit is returned.
diff --git a/core/chains/evm/gas/arbitrum_estimator_test.go b/core/chains/evm/gas/arbitrum_estimator_test.go
index b6e299190c..a226368edf 100644
--- a/core/chains/evm/gas/arbitrum_estimator_test.go
+++ b/core/chains/evm/gas/arbitrum_estimator_test.go
@@ -131,7 +131,7 @@ func TestArbitrumEstimator(t *testing.T) {
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.TestLogger(t), &arbConfig{}, rpcClient, ethClient)
_, _, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), gasLimit, assets.NewWeiI(10), nil)
- assert.EqualError(t, err, "bump gas is not supported for this l2")
+ assert.EqualError(t, err, "bump gas is not supported for this chain")
})
t.Run("calling GetLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) {
@@ -152,7 +152,7 @@ func TestArbitrumEstimator(t *testing.T) {
t.Cleanup(func() { assert.NoError(t, o.Close()) })
_, _, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
- assert.EqualError(t, err, "failed to estimate l2 gas; gas price not set")
+ assert.EqualError(t, err, "failed to estimate gas; gas price not set")
})
t.Run("limit computes", func(t *testing.T) {
diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go
index 7bd88d7543..299d7d5473 100644
--- a/core/chains/evm/gas/models.go
+++ b/core/chains/evm/gas/models.go
@@ -78,8 +78,8 @@ func NewEstimator(lggr logger.Logger, ethClient evmclient.Client, cfg Config, ge
return NewWrappedEvmEstimator(NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bh, *ethClient.ConfiguredChainID()), df, l1Oracle)
case "FixedPrice":
return NewWrappedEvmEstimator(NewFixedPriceEstimator(geCfg, bh, lggr), df, l1Oracle)
- case "Optimism2", "L2Suggested":
- return NewWrappedEvmEstimator(NewL2SuggestedPriceEstimator(lggr, ethClient), df, l1Oracle)
+ case "L2Suggested", "SuggestedPrice":
+ return NewWrappedEvmEstimator(NewSuggestedPriceEstimator(lggr, ethClient), df, l1Oracle)
default:
lggr.Warnf("GasEstimator: unrecognised mode '%s', falling back to FixedPriceEstimator", s)
return NewWrappedEvmEstimator(NewFixedPriceEstimator(geCfg, bh, lggr), df, l1Oracle)
diff --git a/core/chains/evm/gas/l2_suggested_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go
similarity index 60%
rename from core/chains/evm/gas/l2_suggested_estimator.go
rename to core/chains/evm/gas/suggested_price_estimator.go
index 8e6c06a128..a4ffb80997 100644
--- a/core/chains/evm/gas/l2_suggested_estimator.go
+++ b/core/chains/evm/gas/suggested_price_estimator.go
@@ -19,7 +19,7 @@ import (
)
var (
- _ EvmEstimator = &l2SuggestedPriceEstimator{}
+ _ EvmEstimator = &SuggestedPriceEstimator{}
)
//go:generate mockery --quiet --name rpcClient --output ./mocks/ --case=underscore --structname RPCClient
@@ -27,8 +27,8 @@ type rpcClient interface {
CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error
}
-// l2SuggestedPriceEstimator is an Estimator which uses the L2 suggested gas price from eth_gasPrice.
-type l2SuggestedPriceEstimator struct {
+// SuggestedPriceEstimator is an Estimator which uses the suggested gas price from eth_gasPrice.
+type SuggestedPriceEstimator struct {
services.StateMachine
client rpcClient
@@ -36,7 +36,7 @@ type l2SuggestedPriceEstimator struct {
logger logger.Logger
gasPriceMu sync.RWMutex
- l2GasPrice *assets.Wei
+ GasPrice *assets.Wei
chForceRefetch chan (chan struct{})
chInitialised chan struct{}
@@ -44,12 +44,12 @@ type l2SuggestedPriceEstimator struct {
chDone chan struct{}
}
-// NewL2SuggestedPriceEstimator returns a new Estimator which uses the L2 suggested gas price.
-func NewL2SuggestedPriceEstimator(lggr logger.Logger, client rpcClient) EvmEstimator {
- return &l2SuggestedPriceEstimator{
+// NewSuggestedPriceEstimator returns a new Estimator which uses the suggested gas price.
+func NewSuggestedPriceEstimator(lggr logger.Logger, client rpcClient) EvmEstimator {
+ return &SuggestedPriceEstimator{
client: client,
pollPeriod: 10 * time.Second,
- logger: lggr.Named("L2SuggestedEstimator"),
+ logger: lggr.Named("SuggestedPriceEstimator"),
chForceRefetch: make(chan (chan struct{})),
chInitialised: make(chan struct{}),
chStop: make(chan struct{}),
@@ -57,30 +57,30 @@ func NewL2SuggestedPriceEstimator(lggr logger.Logger, client rpcClient) EvmEstim
}
}
-func (o *l2SuggestedPriceEstimator) Name() string {
+func (o *SuggestedPriceEstimator) Name() string {
return o.logger.Name()
}
-func (o *l2SuggestedPriceEstimator) Start(context.Context) error {
- return o.StartOnce("L2SuggestedEstimator", func() error {
+func (o *SuggestedPriceEstimator) Start(context.Context) error {
+ return o.StartOnce("SuggestedPriceEstimator", func() error {
go o.run()
<-o.chInitialised
return nil
})
}
-func (o *l2SuggestedPriceEstimator) Close() error {
- return o.StopOnce("L2SuggestedEstimator", func() error {
+func (o *SuggestedPriceEstimator) Close() error {
+ return o.StopOnce("SuggestedPriceEstimator", func() error {
close(o.chStop)
<-o.chDone
return nil
})
}
-func (o *l2SuggestedPriceEstimator) HealthReport() map[string]error {
+func (o *SuggestedPriceEstimator) HealthReport() map[string]error {
return map[string]error{o.Name(): o.Healthy()}
}
-func (o *l2SuggestedPriceEstimator) run() {
+func (o *SuggestedPriceEstimator) run() {
defer close(o.chDone)
t := o.refreshPrice()
@@ -100,7 +100,7 @@ func (o *l2SuggestedPriceEstimator) run() {
}
}
-func (o *l2SuggestedPriceEstimator) refreshPrice() (t *time.Timer) {
+func (o *SuggestedPriceEstimator) refreshPrice() (t *time.Timer) {
t = time.NewTimer(utils.WithJitter(o.pollPeriod))
var res hexutil.Big
@@ -113,28 +113,28 @@ func (o *l2SuggestedPriceEstimator) refreshPrice() (t *time.Timer) {
}
bi := (*assets.Wei)(&res)
- o.logger.Debugw("refreshPrice", "l2GasPrice", bi)
+ o.logger.Debugw("refreshPrice", "GasPrice", bi)
o.gasPriceMu.Lock()
defer o.gasPriceMu.Unlock()
- o.l2GasPrice = bi
+ o.GasPrice = bi
return
}
-func (o *l2SuggestedPriceEstimator) OnNewLongestChain(context.Context, *evmtypes.Head) {}
+func (o *SuggestedPriceEstimator) OnNewLongestChain(context.Context, *evmtypes.Head) {}
-func (*l2SuggestedPriceEstimator) GetDynamicFee(_ context.Context, _ uint32, _ *assets.Wei) (fee DynamicFee, chainSpecificGasLimit uint32, err error) {
+func (*SuggestedPriceEstimator) GetDynamicFee(_ context.Context, _ uint32, _ *assets.Wei) (fee DynamicFee, chainSpecificGasLimit uint32, err error) {
err = errors.New("dynamic fees are not implemented for this layer 2")
return
}
-func (*l2SuggestedPriceEstimator) BumpDynamicFee(_ context.Context, _ DynamicFee, _ uint32, _ *assets.Wei, _ []EvmPriorAttempt) (bumped DynamicFee, chainSpecificGasLimit uint32, err error) {
+func (*SuggestedPriceEstimator) BumpDynamicFee(_ context.Context, _ DynamicFee, _ uint32, _ *assets.Wei, _ []EvmPriorAttempt) (bumped DynamicFee, chainSpecificGasLimit uint32, err error) {
err = errors.New("dynamic fees are not implemented for this layer 2")
return
}
-func (o *l2SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte, l2GasLimit uint32, maxGasPriceWei *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint32, err error) {
- chainSpecificGasLimit = l2GasLimit
+func (o *SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte, GasLimit uint32, maxGasPriceWei *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint32, err error) {
+ chainSpecificGasLimit = GasLimit
ok := o.IfStarted(func() {
if slices.Contains(opts, feetypes.OptForceRefetch) {
@@ -159,10 +159,10 @@ func (o *l2SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte,
}
}
if gasPrice = o.getGasPrice(); gasPrice == nil {
- err = errors.New("failed to estimate l2 gas; gas price not set")
+ err = errors.New("failed to estimate gas; gas price not set")
return
}
- o.logger.Debugw("GetLegacyGas", "l2GasPrice", gasPrice, "l2GasLimit", l2GasLimit)
+ o.logger.Debugw("GetLegacyGas", "GasPrice", gasPrice, "GasLimit", GasLimit)
})
if !ok {
return nil, 0, errors.New("estimator is not started")
@@ -176,12 +176,12 @@ func (o *l2SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte,
return
}
-func (o *l2SuggestedPriceEstimator) BumpLegacyGas(_ context.Context, _ *assets.Wei, _ uint32, _ *assets.Wei, _ []EvmPriorAttempt) (bumpedGasPrice *assets.Wei, chainSpecificGasLimit uint32, err error) {
- return nil, 0, errors.New("bump gas is not supported for this l2")
+func (o *SuggestedPriceEstimator) BumpLegacyGas(_ context.Context, _ *assets.Wei, _ uint32, _ *assets.Wei, _ []EvmPriorAttempt) (bumpedGasPrice *assets.Wei, chainSpecificGasLimit uint32, err error) {
+ return nil, 0, errors.New("bump gas is not supported for this chain")
}
-func (o *l2SuggestedPriceEstimator) getGasPrice() (l2GasPrice *assets.Wei) {
+func (o *SuggestedPriceEstimator) getGasPrice() (GasPrice *assets.Wei) {
o.gasPriceMu.RLock()
defer o.gasPriceMu.RUnlock()
- return o.l2GasPrice
+ return o.GasPrice
}
diff --git a/core/chains/evm/gas/l2_suggested_estimator_test.go b/core/chains/evm/gas/suggested_price_estimator_test.go
similarity index 87%
rename from core/chains/evm/gas/l2_suggested_estimator_test.go
rename to core/chains/evm/gas/suggested_price_estimator_test.go
index 69b3603302..808b28a3a6 100644
--- a/core/chains/evm/gas/l2_suggested_estimator_test.go
+++ b/core/chains/evm/gas/suggested_price_estimator_test.go
@@ -17,7 +17,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
-func TestL2SuggestedEstimator(t *testing.T) {
+func TestSuggestedPriceEstimator(t *testing.T) {
t.Parallel()
maxGasPrice := assets.NewWeiI(100)
@@ -27,7 +27,7 @@ func TestL2SuggestedEstimator(t *testing.T) {
t.Run("calling GetLegacyGas on unstarted estimator returns error", func(t *testing.T) {
client := mocks.NewRPCClient(t)
- o := gas.NewL2SuggestedPriceEstimator(logger.TestLogger(t), client)
+ o := gas.NewSuggestedPriceEstimator(logger.TestLogger(t), client)
_, _, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
assert.EqualError(t, err, "estimator is not started")
})
@@ -39,7 +39,7 @@ func TestL2SuggestedEstimator(t *testing.T) {
(*big.Int)(res).SetInt64(42)
})
- o := gas.NewL2SuggestedPriceEstimator(logger.TestLogger(t), client)
+ o := gas.NewSuggestedPriceEstimator(logger.TestLogger(t), client)
require.NoError(t, o.Start(testutils.Context(t)))
t.Cleanup(func() { assert.NoError(t, o.Close()) })
gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
@@ -50,7 +50,7 @@ func TestL2SuggestedEstimator(t *testing.T) {
t.Run("gas price is lower than user specified max gas price", func(t *testing.T) {
client := mocks.NewRPCClient(t)
- o := gas.NewL2SuggestedPriceEstimator(logger.TestLogger(t), client)
+ o := gas.NewSuggestedPriceEstimator(logger.TestLogger(t), client)
client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
@@ -68,7 +68,7 @@ func TestL2SuggestedEstimator(t *testing.T) {
t.Run("gas price is lower than global max gas price", func(t *testing.T) {
client := mocks.NewRPCClient(t)
- o := gas.NewL2SuggestedPriceEstimator(logger.TestLogger(t), client)
+ o := gas.NewSuggestedPriceEstimator(logger.TestLogger(t), client)
client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
@@ -85,14 +85,14 @@ func TestL2SuggestedEstimator(t *testing.T) {
t.Run("calling BumpLegacyGas always returns error", func(t *testing.T) {
client := mocks.NewRPCClient(t)
- o := gas.NewL2SuggestedPriceEstimator(logger.TestLogger(t), client)
+ o := gas.NewSuggestedPriceEstimator(logger.TestLogger(t), client)
_, _, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), gasLimit, assets.NewWeiI(10), nil)
- assert.EqualError(t, err, "bump gas is not supported for this l2")
+ assert.EqualError(t, err, "bump gas is not supported for this chain")
})
t.Run("calling GetLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) {
client := mocks.NewRPCClient(t)
- o := gas.NewL2SuggestedPriceEstimator(logger.TestLogger(t), client)
+ o := gas.NewSuggestedPriceEstimator(logger.TestLogger(t), client)
client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(errors.New("kaboom"))
@@ -100,6 +100,6 @@ func TestL2SuggestedEstimator(t *testing.T) {
t.Cleanup(func() { assert.NoError(t, o.Close()) })
_, _, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
- assert.EqualError(t, err, "failed to estimate l2 gas; gas price not set")
+ assert.EqualError(t, err, "failed to estimate gas; gas price not set")
})
}
diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml
index c8b5395d6d..0e0d0d0bd8 100644
--- a/core/config/docs/chains-evm.toml
+++ b/core/config/docs/chains-evm.toml
@@ -112,7 +112,8 @@ Enabled = true # Default
#
# - `FixedPrice` uses static configured values for gas price (can be set via API call).
# - `BlockHistory` dynamically adjusts default gas price based on heuristics from mined blocks.
-# - `L2Suggested` is a special mode only for use with L2 blockchains. This mode will use the gas price suggested by the rpc endpoint via `eth_gasPrice`.
+# - `L2Suggested` mode is deprecated and replaced with `SuggestedPrice`.
+# - `SuggestedPrice` is a mode which uses the gas price suggested by the rpc endpoint via `eth_gasPrice`.
# - `Arbitrum` is a special mode only for use with Arbitrum blockchains. It uses the suggested gas price (up to `ETH_MAX_GAS_PRICE_WEI`, with `1000 gwei` default) as well as an estimated gas limit (up to `ETH_GAS_LIMIT_MAX`, with `1,000,000,000` default).
#
# Chainlink nodes decide what gas price to use using an `Estimator`. It ships with several simple and battle-hardened built-in estimators that should work well for almost all use-cases. Note that estimators will change their behaviour slightly depending on if you are in EIP-1559 mode or not.
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 48fb8272ac..986b98d936 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -468,7 +468,7 @@ func TestConfig_Marshal(t *testing.T) {
FlagsContractAddress: mustAddress("0xae4E781a6218A8031764928E88d457937A954fC3"),
GasEstimator: evmcfg.GasEstimator{
- Mode: ptr("L2Suggested"),
+ Mode: ptr("SuggestedPrice"),
EIP1559DynamicFees: ptr(true),
BumpPercent: ptr[uint16](10),
BumpThreshold: ptr[uint32](6),
@@ -912,7 +912,7 @@ ResendAfterThreshold = '1h0m0s'
Enabled = true
[EVM.GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '9.223372036854775807 ether'
PriceMax = '281.474976710655 micro'
PriceMin = '13 wei'
diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml
index 1534a411dc..7ce0d185b1 100644
--- a/core/services/chainlink/testdata/config-full.toml
+++ b/core/services/chainlink/testdata/config-full.toml
@@ -257,7 +257,7 @@ ResendAfterThreshold = '1h0m0s'
Enabled = true
[EVM.GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '9.223372036854775807 ether'
PriceMax = '281.474976710655 micro'
PriceMin = '13 wei'
diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml
index 4b53396b94..f44f119075 100644
--- a/core/web/resolver/testdata/config-full.toml
+++ b/core/web/resolver/testdata/config-full.toml
@@ -257,7 +257,7 @@ ResendAfterThreshold = '1h0m0s'
Enabled = true
[EVM.GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '9.223372036854775807 ether'
PriceMax = '281.474976710655 micro'
PriceMin = '13 wei'
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index daeddf2ce6..8f3b16c132 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [dev]
+### Changed
+
+- `L2Suggested` mode is now called `SuggestedPrice`
+
+### Removed
+
+- Removed `Optimism2` as a supported gas estimator mode
+
...
## 2.7.0 - UNRELEASED
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index da986e0500..313e7b46aa 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -2726,7 +2726,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
@@ -2885,7 +2885,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '0'
@@ -2963,7 +2963,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '750 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
@@ -3042,7 +3042,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '0'
@@ -3199,7 +3199,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
@@ -3277,7 +3277,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '750 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
@@ -4383,7 +4383,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '0'
@@ -4461,7 +4461,7 @@ ResendAfterThreshold = '1m0s'
Enabled = true
[GasEstimator]
-Mode = 'L2Suggested'
+Mode = 'SuggestedPrice'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '0'
@@ -5004,7 +5004,8 @@ Mode controls what type of gas estimator is used.
- `FixedPrice` uses static configured values for gas price (can be set via API call).
- `BlockHistory` dynamically adjusts default gas price based on heuristics from mined blocks.
-- `L2Suggested` is a special mode only for use with L2 blockchains. This mode will use the gas price suggested by the rpc endpoint via `eth_gasPrice`.
+- `L2Suggested` mode is deprecated and replaced with `SuggestedPrice`.
+- `SuggestedPrice` is a mode which uses the gas price suggested by the rpc endpoint via `eth_gasPrice`.
- `Arbitrum` is a special mode only for use with Arbitrum blockchains. It uses the suggested gas price (up to `ETH_MAX_GAS_PRICE_WEI`, with `1000 gwei` default) as well as an estimated gas limit (up to `ETH_GAS_LIMIT_MAX`, with `1,000,000,000` default).
Chainlink nodes decide what gas price to use using an `Estimator`. It ships with several simple and battle-hardened built-in estimators that should work well for almost all use-cases. Note that estimators will change their behaviour slightly depending on if you are in EIP-1559 mode or not.
From 836ab9048781ef40b1098e9324dddfcd71f3ee5b Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Wed, 1 Nov 2023 17:18:06 -0400
Subject: [PATCH 050/327] Utilizes Lazier Fund Return for Tests (#11144)
---
.gitignore | 1 +
integration-tests/docker/test_env/cl_node_cluster.go | 3 ++-
integration-tests/docker/test_env/test_env.go | 2 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
integration-tests/smoke/ocr_test.go | 2 +-
integration-tests/smoke/vrfv2plus_test.go | 5 ++---
7 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/.gitignore b/.gitignore
index decea4a68a..bfd66e2a39 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,7 @@ tools/clroot/db.sqlite3-wal
.idea
.vscode/
*.iml
+debug.env
# codeship
*.aes
diff --git a/integration-tests/docker/test_env/cl_node_cluster.go b/integration-tests/docker/test_env/cl_node_cluster.go
index a717a19264..5ae90bb982 100644
--- a/integration-tests/docker/test_env/cl_node_cluster.go
+++ b/integration-tests/docker/test_env/cl_node_cluster.go
@@ -3,8 +3,9 @@ package test_env
import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink/integration-tests/client"
"golang.org/x/sync/errgroup"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/client"
)
var (
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index 07b193f102..40ed0d4d53 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -23,11 +23,11 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/logwatch"
+ "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/utils"
- "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
)
var (
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 3affd79919..aa670da1c9 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -20,7 +20,7 @@ require (
github.com/rs/zerolog v1.30.0
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.1
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.2
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.27
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 98685fdf88..f7b55b259f 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2368,8 +2368,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.1 h1:YznR7isiPYbywuUma5eVSyuZYwbUHIGJ2lpcJazOZgo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.1/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.2 h1:Ac/wdRDF4L479wpFT3yqn6ujb6kFTn7aq8gj9giyFHM=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.2/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go
index 8d71c5d08f..8952f00d76 100644
--- a/integration-tests/smoke/ocr_test.go
+++ b/integration-tests/smoke/ocr_test.go
@@ -22,7 +22,7 @@ func TestOCRBasic(t *testing.T) {
WithGeth().
WithMockAdapter().
WithCLNodes(6).
- WithFunding(big.NewFloat(.1)).
+ WithFunding(big.NewFloat(.01)).
WithStandardCleanup().
Build()
require.NoError(t, err)
diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go
index 408e5a95ed..d7381c9cd3 100644
--- a/integration-tests/smoke/vrfv2plus_test.go
+++ b/integration-tests/smoke/vrfv2plus_test.go
@@ -6,14 +6,13 @@ import (
"testing"
"time"
- "github.com/kelseyhightower/envconfig"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version"
-
"github.com/ethereum/go-ethereum/common"
+ "github.com/kelseyhightower/envconfig"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus"
From ac9e6185c1008a8702d525829d8e0ed3047aff86 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Thu, 2 Nov 2023 04:35:47 -0500
Subject: [PATCH 051/327] core/chains/cosmos: remove; import from
chainlink-comsos (#11136)
---
core/chains/cosmos/chain.go | 317 ----------
core/chains/cosmos/cosmostxm/helpers_test.go | 15 -
core/chains/cosmos/cosmostxm/key_wrapper.go | 62 --
.../cosmos/cosmostxm/keystore_adapter.go | 129 -----
core/chains/cosmos/cosmostxm/main_test.go | 17 -
core/chains/cosmos/cosmostxm/orm.go | 104 ----
core/chains/cosmos/cosmostxm/orm_test.go | 76 ---
core/chains/cosmos/cosmostxm/txm.go | 542 ------------------
.../cosmos/cosmostxm/txm_internal_test.go | 426 --------------
core/chains/cosmos/cosmostxm/txm_test.go | 121 ----
core/chains/cosmos/relayer_adapter.go | 50 --
core/cmd/shell.go | 5 +-
core/cmd/shell_local_test.go | 9 +-
core/internal/cltest/cltest.go | 9 +-
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
.../mocks/relayer_chain_interoperators.go | 251 ++------
.../chainlink/relayer_chain_interoperators.go | 54 +-
.../relayer_chain_interoperators_test.go | 18 +-
core/services/chainlink/relayer_factory.go | 22 +-
core/services/pg/channels.go | 5 +-
.../0207_drop_insert_on_terra_msg.sql | 20 +
core/web/loader/loader_test.go | 10 +-
core/web/resolver/eth_key_test.go | 10 +-
core/web/resolver/node_test.go | 11 +-
core/web/resolver/resolver_test.go | 4 +-
go.mod | 6 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
30 files changed, 148 insertions(+), 2161 deletions(-)
delete mode 100644 core/chains/cosmos/chain.go
delete mode 100644 core/chains/cosmos/cosmostxm/helpers_test.go
delete mode 100644 core/chains/cosmos/cosmostxm/key_wrapper.go
delete mode 100644 core/chains/cosmos/cosmostxm/keystore_adapter.go
delete mode 100644 core/chains/cosmos/cosmostxm/main_test.go
delete mode 100644 core/chains/cosmos/cosmostxm/orm.go
delete mode 100644 core/chains/cosmos/cosmostxm/orm_test.go
delete mode 100644 core/chains/cosmos/cosmostxm/txm.go
delete mode 100644 core/chains/cosmos/cosmostxm/txm_internal_test.go
delete mode 100644 core/chains/cosmos/cosmostxm/txm_test.go
delete mode 100644 core/chains/cosmos/relayer_adapter.go
create mode 100644 core/store/migrate/migrations/0207_drop_insert_on_terra_msg.sql
diff --git a/core/chains/cosmos/chain.go b/core/chains/cosmos/chain.go
deleted file mode 100644
index e11f95d356..0000000000
--- a/core/chains/cosmos/chain.go
+++ /dev/null
@@ -1,317 +0,0 @@
-package cosmos
-
-import (
- "context"
- "crypto/rand"
- "fmt"
- "math/big"
- "time"
-
- "github.com/pelletier/go-toml/v2"
- "github.com/pkg/errors"
- "go.uber.org/multierr"
-
- sdk "github.com/cosmos/cosmos-sdk/types"
- bank "github.com/cosmos/cosmos-sdk/x/bank/types"
-
- "github.com/smartcontractkit/sqlx"
-
- relaychains "github.com/smartcontractkit/chainlink-relay/pkg/chains"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
-
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
-
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos/cosmostxm"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay"
-)
-
-// defaultRequestTimeout is the default Cosmos client timeout.
-// Note that while the cosmos node is processing a heavy block,
-// requests can be delayed significantly (https://github.com/tendermint/tendermint/issues/6899),
-// however there's nothing we can do but wait until the block is processed.
-// So we set a fairly high timeout here.
-// TODO(BCI-979): Remove this, or make this configurable with the updated client.
-const defaultRequestTimeout = 30 * time.Second
-
-var (
- // ErrChainIDEmpty is returned when chain is required but was empty.
- ErrChainIDEmpty = errors.New("chain id empty")
- // ErrChainIDInvalid is returned when a chain id does not match any configured chains.
- ErrChainIDInvalid = errors.New("chain id does not match any local chains")
-)
-
-// Chain is a wrap for easy use in other places in the core node
-type Chain = adapters.Chain
-
-// ChainOpts holds options for configuring a Chain.
-type ChainOpts struct {
- QueryConfig pg.QConfig
- Logger logger.Logger
- DB *sqlx.DB
- KeyStore loop.Keystore
- EventBroadcaster pg.EventBroadcaster
-}
-
-func (o *ChainOpts) Validate() (err error) {
- required := func(s string) error {
- return fmt.Errorf("%s is required", s)
- }
- if o.QueryConfig == nil {
- err = multierr.Append(err, required("Config"))
- }
- if o.Logger == nil {
- err = multierr.Append(err, required("Logger'"))
- }
- if o.DB == nil {
- err = multierr.Append(err, required("DB"))
- }
- if o.KeyStore == nil {
- err = multierr.Append(err, required("KeyStore"))
- }
- if o.EventBroadcaster == nil {
- err = multierr.Append(err, required("EventBroadcaster"))
- }
- return
-}
-
-func NewChain(cfg *coscfg.TOMLConfig, opts ChainOpts) (adapters.Chain, error) {
- if !cfg.IsEnabled() {
- return nil, fmt.Errorf("cannot create new chain with ID %s, the chain is disabled", *cfg.ChainID)
- }
- c, err := newChain(*cfg.ChainID, cfg, opts.DB, opts.KeyStore, opts.QueryConfig, opts.EventBroadcaster, opts.Logger)
- if err != nil {
- return nil, err
- }
- return c, nil
-}
-
-var _ adapters.Chain = (*chain)(nil)
-
-type chain struct {
- services.StateMachine
- id string
- cfg *coscfg.TOMLConfig
- txm *cosmostxm.Txm
- lggr logger.Logger
-}
-
-func newChain(id string, cfg *coscfg.TOMLConfig, db *sqlx.DB, ks loop.Keystore, logCfg pg.QConfig, eb pg.EventBroadcaster, lggr logger.Logger) (*chain, error) {
- lggr = logger.With(lggr, "cosmosChainID", id)
- var ch = chain{
- id: id,
- cfg: cfg,
- lggr: logger.Named(lggr, "Chain"),
- }
- tc := func() (client.ReaderWriter, error) {
- return ch.getClient("")
- }
- gpe := client.NewMustGasPriceEstimator([]client.GasPricesEstimator{
- client.NewClosureGasPriceEstimator(func() (map[string]sdk.DecCoin, error) {
- return map[string]sdk.DecCoin{
- cfg.GasToken(): sdk.NewDecCoinFromDec(cfg.GasToken(), cfg.FallbackGasPrice()),
- }, nil
- }),
- }, lggr)
- ch.txm = cosmostxm.NewTxm(db, tc, *gpe, ch.id, cfg, ks, lggr, logCfg, eb)
-
- return &ch, nil
-}
-
-func (c *chain) Name() string {
- return c.lggr.Name()
-}
-
-func (c *chain) ID() string {
- return c.id
-}
-
-func (c *chain) ChainID() string {
- return c.id
-}
-
-func (c *chain) Config() coscfg.Config {
- return c.cfg
-}
-
-func (c *chain) TxManager() adapters.TxManager {
- return c.txm
-}
-
-func (c *chain) Reader(name string) (client.Reader, error) {
- return c.getClient(name)
-}
-
-// getClient returns a client, optionally requiring a specific node by name.
-func (c *chain) getClient(name string) (client.ReaderWriter, error) {
- var node db.Node
- if name == "" { // Any node
- nodes, err := c.cfg.ListNodes()
- if err != nil {
- return nil, fmt.Errorf("failed to list nodes: %w", err)
- }
- if len(nodes) == 0 {
- return nil, errors.New("no nodes available")
- }
- nodeIndex, err := rand.Int(rand.Reader, big.NewInt(int64(len(nodes))))
- if err != nil {
- return nil, fmt.Errorf("could not generate a random node index: %w", err)
- }
- node = nodes[nodeIndex.Int64()]
- } else { // Named node
- var err error
- node, err = c.cfg.GetNode(name)
- if err != nil {
- return nil, fmt.Errorf("failed to get node named %s: %w", name, err)
- }
- if node.CosmosChainID != c.id {
- return nil, fmt.Errorf("failed to create client for chain %s with node %s: wrong chain id %s", c.id, name, node.CosmosChainID)
- }
- }
- client, err := client.NewClient(c.id, node.TendermintURL, defaultRequestTimeout, logger.Named(c.lggr, "Client."+name))
- if err != nil {
- return nil, fmt.Errorf("failed to create client: %w", err)
- }
- c.lggr.Debugw("Created client", "name", node.Name, "tendermint-url", node.TendermintURL)
- return client, nil
-}
-
-// Start starts cosmos chain.
-func (c *chain) Start(ctx context.Context) error {
- return c.StartOnce("Chain", func() error {
- c.lggr.Debug("Starting")
- return c.txm.Start(ctx)
- })
-}
-
-func (c *chain) Close() error {
- return c.StopOnce("Chain", func() error {
- c.lggr.Debug("Stopping")
- return c.txm.Close()
- })
-}
-
-func (c *chain) Ready() error {
- return multierr.Combine(
- c.StateMachine.Ready(),
- c.txm.Ready(),
- )
-}
-
-func (c *chain) HealthReport() map[string]error {
- m := map[string]error{c.Name(): c.Healthy()}
- services.CopyHealth(m, c.txm.HealthReport())
- return m
-}
-
-// ChainService interface
-func (c *chain) GetChainStatus(ctx context.Context) (relaytypes.ChainStatus, error) {
- toml, err := c.cfg.TOMLString()
- if err != nil {
- return relaytypes.ChainStatus{}, err
- }
- return relaytypes.ChainStatus{
- ID: c.id,
- Enabled: *c.cfg.Enabled,
- Config: toml,
- }, nil
-}
-func (c *chain) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []relaytypes.NodeStatus, nextPageToken string, total int, err error) {
- return relaychains.ListNodeStatuses(int(pageSize), pageToken, c.listNodeStatuses)
-}
-
-func (c *chain) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error {
- fromAcc, err := sdk.AccAddressFromBech32(from)
- if err != nil {
- return fmt.Errorf("failed to parse from account: %s", fromAcc)
- }
- toAcc, err := sdk.AccAddressFromBech32(to)
- if err != nil {
- return fmt.Errorf("failed to parse from account: %s", toAcc)
- }
- coin := sdk.Coin{Amount: sdk.NewIntFromBigInt(amount), Denom: c.Config().GasToken()}
-
- txm := c.TxManager()
-
- if balanceCheck {
- var reader client.Reader
- reader, err = c.Reader("")
- if err != nil {
- return fmt.Errorf("chain unreachable: %v", err)
- }
- gasPrice, err2 := txm.GasPrice()
- if err2 != nil {
- return fmt.Errorf("gas price unavailable: %v", err2)
- }
-
- err = validateBalance(reader, gasPrice, fromAcc, coin)
- if err != nil {
- return fmt.Errorf("failed to validate balance: %v", err)
- }
- }
-
- sendMsg := bank.NewMsgSend(fromAcc, toAcc, sdk.Coins{coin})
- _, err = txm.Enqueue("", sendMsg)
- if err != nil {
- return fmt.Errorf("failed to enqueue tx: %w", err)
- }
- return nil
-}
-
-// TODO BCF-2602 statuses are static for non-evm chain and should be dynamic
-func (c *chain) listNodeStatuses(start, end int) ([]relaytypes.NodeStatus, int, error) {
- stats := make([]relaytypes.NodeStatus, 0)
- total := len(c.cfg.Nodes)
- if start >= total {
- return stats, total, relaychains.ErrOutOfRange
- }
- if end > total {
- end = total
- }
- nodes := c.cfg.Nodes[start:end]
- for _, node := range nodes {
- stat, err := nodeStatus(node, c.ChainID())
- if err != nil {
- return stats, total, err
- }
- stats = append(stats, stat)
- }
- return stats, total, nil
-}
-
-func nodeStatus(n *coscfg.Node, id relay.ChainID) (relaytypes.NodeStatus, error) {
- var s relaytypes.NodeStatus
- s.ChainID = id
- s.Name = *n.Name
- b, err := toml.Marshal(n)
- if err != nil {
- return relaytypes.NodeStatus{}, err
- }
- s.Config = string(b)
- return s, nil
-}
-
-// maxGasUsedTransfer is an upper bound on how much gas we expect a MsgSend for a single coin to use.
-const maxGasUsedTransfer = 100_000
-
-// validateBalance validates that fromAddr's balance can cover coin, including fees at gasPrice.
-func validateBalance(reader client.Reader, gasPrice sdk.DecCoin, fromAddr sdk.AccAddress, coin sdk.Coin) error {
- balance, err := reader.Balance(fromAddr, coin.GetDenom())
- if err != nil {
- return err
- }
-
- fee := gasPrice.Amount.MulInt64(maxGasUsedTransfer).RoundInt()
- need := coin.Amount.Add(fee)
-
- if balance.Amount.LT(need) {
- return errors.Errorf("balance %q is too low for this transaction to be executed: need %s total, including %s fee", balance, need, fee)
- }
- return nil
-}
diff --git a/core/chains/cosmos/cosmostxm/helpers_test.go b/core/chains/cosmos/cosmostxm/helpers_test.go
deleted file mode 100644
index a2dfbbeed8..0000000000
--- a/core/chains/cosmos/cosmostxm/helpers_test.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package cosmostxm
-
-import "golang.org/x/exp/maps"
-
-func (ka *keystoreAdapter) Accounts() ([]string, error) {
- ka.mutex.Lock()
- defer ka.mutex.Unlock()
- err := ka.updateMappingLocked()
- if err != nil {
- return nil, err
- }
- addresses := maps.Keys(ka.addressToPubKey)
-
- return addresses, nil
-}
diff --git a/core/chains/cosmos/cosmostxm/key_wrapper.go b/core/chains/cosmos/cosmostxm/key_wrapper.go
deleted file mode 100644
index e03dfd89b8..0000000000
--- a/core/chains/cosmos/cosmostxm/key_wrapper.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package cosmostxm
-
-import (
- "bytes"
- "context"
-
- "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
- cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
-)
-
-// KeyWrapper uses a keystoreAdapter to implement the cosmos-sdk PrivKey interface for a specific key.
-type KeyWrapper struct {
- adapter *keystoreAdapter
- account string
-}
-
-var _ cryptotypes.PrivKey = &KeyWrapper{}
-
-func NewKeyWrapper(adapter *keystoreAdapter, account string) *KeyWrapper {
- return &KeyWrapper{
- adapter: adapter,
- account: account,
- }
-}
-
-func (a *KeyWrapper) Bytes() []byte {
- // don't expose the private key.
- return nil
-}
-
-func (a *KeyWrapper) Sign(msg []byte) ([]byte, error) {
- return a.adapter.Sign(context.Background(), a.account, msg)
-}
-
-func (a *KeyWrapper) PubKey() cryptotypes.PubKey {
- pubKey, err := a.adapter.PubKey(a.account)
- if err != nil {
- // return an empty pubkey if it's not found.
- return &secp256k1.PubKey{Key: []byte{}}
- }
- return pubKey
-}
-
-func (a *KeyWrapper) Equals(other cryptotypes.LedgerPrivKey) bool {
- return bytes.Equal(a.PubKey().Bytes(), other.PubKey().Bytes())
-}
-
-func (a *KeyWrapper) Type() string {
- return "secp256k1"
-}
-
-func (a *KeyWrapper) Reset() {
- // no-op
-}
-
-func (a *KeyWrapper) String() string {
- return ""
-}
-
-func (a *KeyWrapper) ProtoMessage() {
- // no-op
-}
diff --git a/core/chains/cosmos/cosmostxm/keystore_adapter.go b/core/chains/cosmos/cosmostxm/keystore_adapter.go
deleted file mode 100644
index 6b360dde98..0000000000
--- a/core/chains/cosmos/cosmostxm/keystore_adapter.go
+++ /dev/null
@@ -1,129 +0,0 @@
-package cosmostxm
-
-import (
- "context"
- "crypto/sha256"
- "encoding/hex"
- "sync"
-
- "github.com/cometbft/cometbft/crypto"
- "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
- cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
- "github.com/cosmos/cosmos-sdk/types/bech32"
- "github.com/pkg/errors"
- "golang.org/x/crypto/ripemd160" //nolint: staticcheck
-
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
-)
-
-type accountInfo struct {
- Account string
- PubKey *secp256k1.PubKey
-}
-
-// keystoreAdapter adapts a Cosmos loop.Keystore to translate public keys into bech32-prefixed account addresses.
-type keystoreAdapter struct {
- keystore loop.Keystore
- accountPrefix string
- mutex sync.RWMutex
- addressToPubKey map[string]*accountInfo
-}
-
-func newKeystoreAdapter(keystore loop.Keystore, accountPrefix string) *keystoreAdapter {
- return &keystoreAdapter{
- keystore: keystore,
- accountPrefix: accountPrefix,
- addressToPubKey: make(map[string]*accountInfo),
- }
-}
-
-func (ka *keystoreAdapter) updateMappingLocked() error {
- accounts, err := ka.keystore.Accounts(context.Background())
- if err != nil {
- return err
- }
-
- // similar to cosmos-sdk, cache and re-use calculated bech32 addresses to prevent duplicated work.
- // ref: https://github.com/cosmos/cosmos-sdk/blob/3b509c187e1643757f5ef8a0b5ae3decca0c7719/types/address.go#L705
-
- type cacheEntry struct {
- bech32Addr string
- accountInfo *accountInfo
- }
- accountCache := make(map[string]cacheEntry, len(ka.addressToPubKey))
- for bech32Addr, accountInfo := range ka.addressToPubKey {
- accountCache[accountInfo.Account] = cacheEntry{bech32Addr: bech32Addr, accountInfo: accountInfo}
- }
-
- addressToPubKey := make(map[string]*accountInfo, len(accounts))
- for _, account := range accounts {
- if prevEntry, ok := accountCache[account]; ok {
- addressToPubKey[prevEntry.bech32Addr] = prevEntry.accountInfo
- continue
- }
- pubKeyBytes, err := hex.DecodeString(account)
- if err != nil {
- return err
- }
-
- if len(pubKeyBytes) != secp256k1.PubKeySize {
- return errors.New("length of pubkey is incorrect")
- }
-
- sha := sha256.Sum256(pubKeyBytes)
- hasherRIPEMD160 := ripemd160.New()
- _, _ = hasherRIPEMD160.Write(sha[:])
- address := crypto.Address(hasherRIPEMD160.Sum(nil))
-
- bech32Addr, err := bech32.ConvertAndEncode(ka.accountPrefix, address)
- if err != nil {
- return err
- }
-
- addressToPubKey[bech32Addr] = &accountInfo{
- Account: account,
- PubKey: &secp256k1.PubKey{Key: pubKeyBytes},
- }
- }
-
- ka.addressToPubKey = addressToPubKey
- return nil
-}
-
-func (ka *keystoreAdapter) lookup(id string) (*accountInfo, error) {
- ka.mutex.RLock()
- ai, ok := ka.addressToPubKey[id]
- ka.mutex.RUnlock()
- if !ok {
- // try updating the mapping once, incase there was an update on the keystore.
- ka.mutex.Lock()
- err := ka.updateMappingLocked()
- if err != nil {
- ka.mutex.Unlock()
- return nil, err
- }
- ai, ok = ka.addressToPubKey[id]
- ka.mutex.Unlock()
- if !ok {
- return nil, errors.New("No such id")
- }
- }
- return ai, nil
-}
-
-func (ka *keystoreAdapter) Sign(ctx context.Context, id string, hash []byte) ([]byte, error) {
- accountInfo, err := ka.lookup(id)
- if err != nil {
- return nil, err
- }
- return ka.keystore.Sign(ctx, accountInfo.Account, hash)
-}
-
-// Returns the cosmos PubKey associated with the prefixed address.
-func (ka *keystoreAdapter) PubKey(address string) (cryptotypes.PubKey, error) {
- accountInfo, err := ka.lookup(address)
- if err != nil {
- return nil, err
- }
- return accountInfo.PubKey, nil
-}
diff --git a/core/chains/cosmos/cosmostxm/main_test.go b/core/chains/cosmos/cosmostxm/main_test.go
deleted file mode 100644
index bc340afa43..0000000000
--- a/core/chains/cosmos/cosmostxm/main_test.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package cosmostxm
-
-import (
- "os"
- "testing"
-
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
-)
-
-func TestMain(m *testing.M) {
- params.InitCosmosSdk(
- /* bech32Prefix= */ "wasm",
- /* token= */ "cosm",
- )
- code := m.Run()
- os.Exit(code)
-}
diff --git a/core/chains/cosmos/cosmostxm/orm.go b/core/chains/cosmos/cosmostxm/orm.go
deleted file mode 100644
index cc9b179cce..0000000000
--- a/core/chains/cosmos/cosmostxm/orm.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package cosmostxm
-
-import (
- "database/sql"
-
- "github.com/pkg/errors"
-
- "github.com/smartcontractkit/sqlx"
-
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
-
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
-
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
-)
-
-// ORM manages the data model for cosmos tx management.
-type ORM struct {
- chainID string
- q pg.Q
-}
-
-// NewORM creates an ORM scoped to chainID.
-func NewORM(chainID string, db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *ORM {
- namedLogger := logger.Named(lggr, "Configs")
- q := pg.NewQ(db, namedLogger, cfg)
- return &ORM{
- chainID: chainID,
- q: q,
- }
-}
-
-// InsertMsg inserts a cosmos msg, assumed to be a serialized cosmos ExecuteContractMsg.
-func (o *ORM) InsertMsg(contractID, typeURL string, msg []byte, qopts ...pg.QOpt) (int64, error) {
- var tm adapters.Msg
- q := o.q.WithOpts(qopts...)
- err := q.Get(&tm, `INSERT INTO cosmos_msgs (contract_id, type, raw, state, cosmos_chain_id, created_at, updated_at)
- VALUES ($1, $2, $3, $4, $5, NOW(), NOW()) RETURNING *`, contractID, typeURL, msg, db.Unstarted, o.chainID)
- if err != nil {
- return 0, err
- }
- return tm.ID, nil
-}
-
-// UpdateMsgsContract updates messages for the given contract.
-func (o *ORM) UpdateMsgsContract(contractID string, from, to db.State, qopts ...pg.QOpt) error {
- q := o.q.WithOpts(qopts...)
- _, err := q.Exec(`UPDATE cosmos_msgs SET state = $1, updated_at = NOW()
- WHERE cosmos_chain_id = $2 AND contract_id = $3 AND state = $4`, to, o.chainID, contractID, from)
- if err != nil {
- return err
- }
- return nil
-}
-
-// GetMsgsState returns the oldest messages with a given state up to limit.
-func (o *ORM) GetMsgsState(state db.State, limit int64, qopts ...pg.QOpt) (adapters.Msgs, error) {
- if limit < 1 {
- return adapters.Msgs{}, errors.New("limit must be greater than 0")
- }
- q := o.q.WithOpts(qopts...)
- var msgs adapters.Msgs
- if err := q.Select(&msgs, `SELECT * FROM cosmos_msgs WHERE state = $1 AND cosmos_chain_id = $2 ORDER BY id ASC LIMIT $3`, state, o.chainID, limit); err != nil {
- return nil, err
- }
- return msgs, nil
-}
-
-// GetMsgs returns any messages matching ids.
-func (o *ORM) GetMsgs(ids ...int64) (adapters.Msgs, error) {
- var msgs adapters.Msgs
- if err := o.q.Select(&msgs, `SELECT * FROM cosmos_msgs WHERE id = ANY($1)`, ids); err != nil {
- return nil, err
- }
- return msgs, nil
-}
-
-// UpdateMsgs updates msgs with the given ids.
-// Note state transitions are validated at the db level.
-func (o *ORM) UpdateMsgs(ids []int64, state db.State, txHash *string, qopts ...pg.QOpt) error {
- if state == db.Broadcasted && txHash == nil {
- return errors.New("txHash is required when updating to broadcasted")
- }
- q := o.q.WithOpts(qopts...)
- var res sql.Result
- var err error
- if state == db.Broadcasted {
- res, err = q.Exec(`UPDATE cosmos_msgs SET state = $1, updated_at = NOW(), tx_hash = $2 WHERE id = ANY($3)`, state, *txHash, ids)
- } else {
- res, err = q.Exec(`UPDATE cosmos_msgs SET state = $1, updated_at = NOW() WHERE id = ANY($2)`, state, ids)
- }
- if err != nil {
- return err
- }
- count, err := res.RowsAffected()
- if err != nil {
- return err
- }
- if int(count) != len(ids) {
- return errors.Errorf("expected %d records updated, got %d", len(ids), count)
- }
- return nil
-}
diff --git a/core/chains/cosmos/cosmostxm/orm_test.go b/core/chains/cosmos/cosmostxm/orm_test.go
deleted file mode 100644
index 3cee25bac1..0000000000
--- a/core/chains/cosmos/cosmostxm/orm_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package cosmostxm
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- cosmosdb "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
-
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
-)
-
-func TestORM(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
- lggr := logger.TestLogger(t)
- logCfg := pgtest.NewQConfig(true)
- chainID := cosmostest.RandomChainID()
- o := NewORM(chainID, db, lggr, logCfg)
-
- // Create
- mid, err := o.InsertMsg("0x123", "", []byte("hello"))
- require.NoError(t, err)
- assert.NotEqual(t, 0, int(mid))
-
- // Read
- unstarted, err := o.GetMsgsState(cosmosdb.Unstarted, 5)
- require.NoError(t, err)
- require.Equal(t, 1, len(unstarted))
- assert.Equal(t, "hello", string(unstarted[0].Raw))
- assert.Equal(t, chainID, unstarted[0].ChainID)
- t.Log(unstarted[0].UpdatedAt, unstarted[0].CreatedAt)
-
- // Limit
- unstarted, err = o.GetMsgsState(cosmosdb.Unstarted, 0)
- assert.Error(t, err)
- assert.Empty(t, unstarted)
- unstarted, err = o.GetMsgsState(cosmosdb.Unstarted, -1)
- assert.Error(t, err)
- assert.Empty(t, unstarted)
- mid2, err := o.InsertMsg("0xabc", "", []byte("test"))
- require.NoError(t, err)
- assert.NotEqual(t, 0, int(mid2))
- unstarted, err = o.GetMsgsState(cosmosdb.Unstarted, 1)
- require.NoError(t, err)
- require.Equal(t, 1, len(unstarted))
- assert.Equal(t, "hello", string(unstarted[0].Raw))
- assert.Equal(t, chainID, unstarted[0].ChainID)
- unstarted, err = o.GetMsgsState(cosmosdb.Unstarted, 2)
- require.NoError(t, err)
- require.Equal(t, 2, len(unstarted))
- assert.Equal(t, "test", string(unstarted[1].Raw))
- assert.Equal(t, chainID, unstarted[1].ChainID)
-
- // Update
- txHash := "123"
- err = o.UpdateMsgs([]int64{mid}, cosmosdb.Started, &txHash)
- require.NoError(t, err)
- err = o.UpdateMsgs([]int64{mid}, cosmosdb.Broadcasted, &txHash)
- require.NoError(t, err)
- broadcasted, err := o.GetMsgsState(cosmosdb.Broadcasted, 5)
- require.NoError(t, err)
- require.Equal(t, 1, len(broadcasted))
- assert.Equal(t, broadcasted[0].Raw, unstarted[0].Raw)
- require.NotNil(t, broadcasted[0].TxHash)
- assert.Equal(t, *broadcasted[0].TxHash, txHash)
- assert.Equal(t, chainID, broadcasted[0].ChainID)
-
- err = o.UpdateMsgs([]int64{mid}, cosmosdb.Confirmed, nil)
- require.NoError(t, err)
- confirmed, err := o.GetMsgsState(cosmosdb.Confirmed, 5)
- require.NoError(t, err)
- require.Equal(t, 1, len(confirmed))
-}
diff --git a/core/chains/cosmos/cosmostxm/txm.go b/core/chains/cosmos/cosmostxm/txm.go
deleted file mode 100644
index 712e1b8fc7..0000000000
--- a/core/chains/cosmos/cosmostxm/txm.go
+++ /dev/null
@@ -1,542 +0,0 @@
-package cosmostxm
-
-import (
- "cmp"
- "context"
- "encoding/hex"
- "fmt"
- "slices"
- "strings"
- "time"
-
- "github.com/gogo/protobuf/proto"
- "github.com/pkg/errors"
-
- "github.com/smartcontractkit/sqlx"
-
- wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
- "github.com/cometbft/cometbft/crypto/tmhash"
- sdk "github.com/cosmos/cosmos-sdk/types"
- txtypes "github.com/cosmos/cosmos-sdk/types/tx"
- "github.com/cosmos/cosmos-sdk/x/bank/types"
-
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
- cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
-
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
-
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-)
-
-var (
- _ services.Service = (*Txm)(nil)
- _ adapters.TxManager = (*Txm)(nil)
-)
-
-// Txm manages transactions for the cosmos blockchain.
-type Txm struct {
- services.StateMachine
- eb pg.EventBroadcaster
- sub pg.Subscription
- orm *ORM
- lggr logger.Logger
- tc func() (cosmosclient.ReaderWriter, error)
- keystoreAdapter *keystoreAdapter
- stop, done chan struct{}
- cfg coscfg.Config
- gpe cosmosclient.ComposedGasPriceEstimator
-}
-
-// NewTxm creates a txm. Uses simulation so should only be used to send txes to trusted contracts i.e. OCR.
-func NewTxm(db *sqlx.DB, tc func() (cosmosclient.ReaderWriter, error), gpe cosmosclient.ComposedGasPriceEstimator, chainID string, cfg coscfg.Config, ks loop.Keystore, lggr logger.Logger, logCfg pg.QConfig, eb pg.EventBroadcaster) *Txm {
- lggr = logger.Named(lggr, "Txm")
- keystoreAdapter := newKeystoreAdapter(ks, cfg.Bech32Prefix())
- return &Txm{
- eb: eb,
- orm: NewORM(chainID, db, lggr, logCfg),
- lggr: lggr,
- tc: tc,
- keystoreAdapter: keystoreAdapter,
- stop: make(chan struct{}),
- done: make(chan struct{}),
- cfg: cfg,
- gpe: gpe,
- }
-}
-
-// Start subscribes to pg notifications about cosmos msg inserts and processes them.
-func (txm *Txm) Start(context.Context) error {
- return txm.StartOnce("Txm", func() error {
- sub, err := txm.eb.Subscribe(pg.ChannelInsertOnCosmosMsg, "")
- if err != nil {
- return err
- }
- txm.sub = sub
- go txm.run()
- return nil
- })
-}
-
-func (txm *Txm) confirmAnyUnconfirmed(ctx context.Context) {
- // Confirm any broadcasted but not confirmed txes.
- // This is an edge case if we crash after having broadcasted but before we confirm.
- for {
- broadcasted, err := txm.orm.GetMsgsState(db.Broadcasted, txm.cfg.MaxMsgsPerBatch())
- if err != nil {
- // Should never happen but if so, theoretically can retry with a reboot
- logger.Criticalw(txm.lggr, "unable to look for broadcasted but unconfirmed txes", "err", err)
- return
- }
- if len(broadcasted) == 0 {
- return
- }
- tc, err := txm.tc()
- if err != nil {
- logger.Criticalw(txm.lggr, "unable to get client for handling broadcasted but unconfirmed txes", "count", len(broadcasted), "err", err)
- return
- }
- msgsByTxHash := make(map[string]adapters.Msgs)
- for _, msg := range broadcasted {
- msgsByTxHash[*msg.TxHash] = append(msgsByTxHash[*msg.TxHash], msg)
- }
- for txHash, msgs := range msgsByTxHash {
- maxPolls, pollPeriod := txm.confirmPollConfig()
- err := txm.confirmTx(ctx, tc, txHash, msgs.GetIDs(), maxPolls, pollPeriod)
- if err != nil {
- txm.lggr.Errorw("unable to confirm broadcasted but unconfirmed txes", "err", err, "txhash", txHash)
- if ctx.Err() != nil {
- return
- }
- }
- }
- }
-}
-
-func (txm *Txm) run() {
- defer close(txm.done)
- ctx, cancel := utils.StopChan(txm.stop).NewCtx()
- defer cancel()
- txm.confirmAnyUnconfirmed(ctx)
- // Jitter in case we have multiple cosmos chains each with their own client.
- tick := time.After(utils.WithJitter(txm.cfg.BlockRate()))
- for {
- select {
- case <-txm.sub.Events():
- txm.sendMsgBatch(ctx)
- case <-tick:
- txm.sendMsgBatch(ctx)
- tick = time.After(utils.WithJitter(txm.cfg.BlockRate()))
- case <-txm.stop:
- return
- }
- }
-}
-
-var (
- typeMsgSend = sdk.MsgTypeURL(&types.MsgSend{})
- typeMsgExecuteContract = sdk.MsgTypeURL(&wasmtypes.MsgExecuteContract{})
-)
-
-func unmarshalMsg(msgType string, raw []byte) (sdk.Msg, string, error) {
- switch msgType {
- case typeMsgSend:
- var ms types.MsgSend
- err := ms.Unmarshal(raw)
- if err != nil {
- return nil, "", err
- }
- return &ms, ms.FromAddress, nil
- case typeMsgExecuteContract:
- var ms wasmtypes.MsgExecuteContract
- err := ms.Unmarshal(raw)
- if err != nil {
- return nil, "", err
- }
- return &ms, ms.Sender, nil
- }
- return nil, "", errors.Errorf("unrecognized message type: %s", msgType)
-}
-
-type msgValidator struct {
- cutoff time.Time
- expired, valid adapters.Msgs
-}
-
-func (e *msgValidator) add(msg adapters.Msg) {
- if msg.CreatedAt.Before(e.cutoff) {
- e.expired = append(e.expired, msg)
- } else {
- e.valid = append(e.valid, msg)
- }
-}
-
-func (e *msgValidator) sortValid() {
- slices.SortFunc(e.valid, func(a, b adapters.Msg) int {
- ac, bc := a.CreatedAt, b.CreatedAt
- if ac.Equal(bc) {
- return cmp.Compare(a.ID, b.ID)
- }
- if ac.After(bc) {
- return 1
- }
- return -1 // ac.Before(bc)
- })
-}
-
-func (txm *Txm) sendMsgBatch(ctx context.Context) {
- msgs := msgValidator{cutoff: time.Now().Add(-txm.cfg.TxMsgTimeout())}
- err := txm.orm.q.Transaction(func(tx pg.Queryer) error {
- // There may be leftover Started messages after a crash or failed send attempt.
- started, err := txm.orm.GetMsgsState(db.Started, txm.cfg.MaxMsgsPerBatch(), pg.WithQueryer(tx))
- if err != nil {
- txm.lggr.Errorw("unable to read unstarted msgs", "err", err)
- return err
- }
- if limit := txm.cfg.MaxMsgsPerBatch() - int64(len(started)); limit > 0 {
- // Use the remaining batch budget for Unstarted
- unstarted, err := txm.orm.GetMsgsState(db.Unstarted, limit, pg.WithQueryer(tx)) //nolint
- if err != nil {
- txm.lggr.Errorw("unable to read unstarted msgs", "err", err)
- return err
- }
- for _, msg := range unstarted {
- msgs.add(msg)
- }
- // Update valid, Unstarted messages to Started
- err = txm.orm.UpdateMsgs(msgs.valid.GetIDs(), db.Started, nil, pg.WithQueryer(tx))
- if err != nil {
- // Assume transient db error retry
- txm.lggr.Errorw("unable to mark unstarted txes as started", "err", err)
- return err
- }
- }
- for _, msg := range started {
- msgs.add(msg)
- }
- // Update expired messages (Unstarted or Started) to Errored
- err = txm.orm.UpdateMsgs(msgs.expired.GetIDs(), db.Errored, nil, pg.WithQueryer(tx))
- if err != nil {
- // Assume transient db error retry
- txm.lggr.Errorw("unable to mark expired txes as errored", "err", err)
- return err
- }
- return nil
- })
- if err != nil {
- return
- }
- if len(msgs.valid) == 0 {
- return
- }
- msgs.sortValid()
- txm.lggr.Debugw("building a batch", "not expired", msgs.valid, "marked expired", msgs.expired)
- var msgsByFrom = make(map[string]adapters.Msgs)
- for _, m := range msgs.valid {
- msg, sender, err2 := unmarshalMsg(m.Type, m.Raw)
- if err2 != nil {
- // Should be impossible given the check in Enqueue
- logger.Criticalw(txm.lggr, "Failed to unmarshal msg, skipping", "err", err2, "msg", m)
- continue
- }
- m.DecodedMsg = msg
- _, err2 = sdk.AccAddressFromBech32(sender)
- if err2 != nil {
- // Should never happen, we parse sender on Enqueue
- logger.Criticalw(txm.lggr, "Unable to parse sender", "err", err2, "sender", sender)
- continue
- }
- msgsByFrom[sender] = append(msgsByFrom[sender], m)
- }
-
- txm.lggr.Debugw("msgsByFrom", "msgsByFrom", msgsByFrom)
- gasPrice, err := txm.GasPrice()
- if err != nil {
- // Should be impossible
- logger.Criticalw(txm.lggr, "Failed to get gas price", "err", err)
- return
- }
- for s, msgs := range msgsByFrom {
- sender, _ := sdk.AccAddressFromBech32(s) // Already checked validity above
- err := txm.sendMsgBatchFromAddress(ctx, gasPrice, sender, msgs)
- if err != nil {
- txm.lggr.Errorw("Could not send message batch", "err", err, "from", sender.String())
- continue
- }
- if ctx.Err() != nil {
- return
- }
- }
-
-}
-
-func (txm *Txm) sendMsgBatchFromAddress(ctx context.Context, gasPrice sdk.DecCoin, sender sdk.AccAddress, msgs adapters.Msgs) error {
- tc, err := txm.tc()
- if err != nil {
- logger.Criticalw(txm.lggr, "unable to get client", "err", err)
- return err
- }
- an, sn, err := tc.Account(sender)
- if err != nil {
- txm.lggr.Warnw("unable to read account", "err", err, "from", sender.String())
- // If we can't read the account, assume transient api issues and leave msgs unstarted
- // to retry on next poll.
- return err
- }
-
- txm.lggr.Debugw("simulating batch", "from", sender, "msgs", msgs, "seqnum", sn)
- simResults, err := tc.BatchSimulateUnsigned(msgs.GetSimMsgs(), sn)
- if err != nil {
- txm.lggr.Warnw("unable to simulate", "err", err, "from", sender.String())
- // If we can't simulate assume transient api issue and retry on next poll.
- // Note one rare scenario in which this can happen: the cosmos node misbehaves
- // in that it confirms a txhash is present but still gives an old seq num.
- // This is benign as the next retry will succeeds.
- return err
- }
- txm.lggr.Debugw("simulation results", "from", sender, "succeeded", simResults.Succeeded, "failed", simResults.Failed)
- err = txm.orm.UpdateMsgs(simResults.Failed.GetSimMsgsIDs(), db.Errored, nil)
- if err != nil {
- txm.lggr.Errorw("unable to mark failed sim txes as errored", "err", err, "from", sender.String())
- // If we can't mark them as failed retry on next poll. Presumably same ones will fail.
- return err
- }
-
- // Continue if there are no successful txes
- if len(simResults.Succeeded) == 0 {
- txm.lggr.Warnw("all sim msgs errored, not sending tx", "from", sender.String())
- return errors.New("all sim msgs errored")
- }
- // Get the gas limit for the successful batch
- s, err := tc.SimulateUnsigned(simResults.Succeeded.GetMsgs(), sn)
- if err != nil {
- // In the OCR context this should only happen upon stale report
- txm.lggr.Warnw("unexpected failure after successful simulation", "err", err)
- return err
- }
- gasLimit := s.GasInfo.GasUsed
-
- lb, err := tc.LatestBlock()
- if err != nil {
- txm.lggr.Warnw("unable to get latest block", "err", err, "from", sender.String())
- // Assume transient api issue and retry.
- return err
- }
- header, timeout := lb.SdkBlock.Header.Height, txm.cfg.BlocksUntilTxTimeout()
- if header < 0 {
- return fmt.Errorf("invalid negative header height: %d", header)
- } else if timeout < 0 {
- return fmt.Errorf("invalid negative blocks until tx timeout: %d", timeout)
- }
- timeoutHeight := uint64(header) + uint64(timeout)
- signedTx, err := tc.CreateAndSign(simResults.Succeeded.GetMsgs(), an, sn, gasLimit, txm.cfg.GasLimitMultiplier(),
- gasPrice, NewKeyWrapper(txm.keystoreAdapter, sender.String()), timeoutHeight)
- if err != nil {
- txm.lggr.Errorw("unable to sign tx", "err", err, "from", sender.String())
- return err
- }
-
- // We need to ensure that we either broadcast successfully and mark the tx as
- // broadcasted OR we do not broadcast successfully and we do not mark it as broadcasted.
- // We do this by first marking it broadcasted then rolling back if the broadcast api call fails.
- // There is still a small chance of network failure or node/db crash after broadcasting but before committing the tx,
- // in which case the msgs would be picked up again and re-broadcast, ensuring at-least once delivery.
- var resp *txtypes.BroadcastTxResponse
- err = txm.orm.q.Transaction(func(tx pg.Queryer) error {
- txHash := strings.ToUpper(hex.EncodeToString(tmhash.Sum(signedTx)))
- err = txm.orm.UpdateMsgs(simResults.Succeeded.GetSimMsgsIDs(), db.Broadcasted, &txHash, pg.WithQueryer(tx))
- if err != nil {
- return err
- }
-
- txm.lggr.Infow("broadcasting tx", "from", sender, "msgs", simResults.Succeeded, "gasLimit", gasLimit, "gasPrice", gasPrice.String(), "timeoutHeight", timeoutHeight, "hash", txHash)
- resp, err = tc.Broadcast(signedTx, txtypes.BroadcastMode_BROADCAST_MODE_SYNC)
- if err != nil {
- // Rollback marking as broadcasted
- // Note can happen if the node's mempool is full, where we expect errCode 20.
- return err
- }
- if resp.TxResponse == nil {
- // Rollback marking as broadcasted
- return errors.New("unexpected nil tx response")
- }
- if resp.TxResponse.TxHash != txHash {
- // Should never happen
- logger.Criticalw(txm.lggr, "txhash mismatch", "got", resp.TxResponse.TxHash, "want", txHash)
- }
- return nil
- })
- if err != nil {
- txm.lggr.Errorw("error broadcasting tx", "err", err, "from", sender.String())
- // Was unable to broadcast, retry on next poll
- return err
- }
-
- maxPolls, pollPeriod := txm.confirmPollConfig()
- if err := txm.confirmTx(ctx, tc, resp.TxResponse.TxHash, simResults.Succeeded.GetSimMsgsIDs(), maxPolls, pollPeriod); err != nil {
- txm.lggr.Errorw("error confirming tx", "err", err, "hash", resp.TxResponse.TxHash)
- return err
- }
-
- return nil
-}
-
-func (txm *Txm) confirmPollConfig() (maxPolls int, pollPeriod time.Duration) {
- blocks := txm.cfg.BlocksUntilTxTimeout()
- blockPeriod := txm.cfg.BlockRate()
- pollPeriod = txm.cfg.ConfirmPollPeriod()
- if pollPeriod == 0 {
- // don't divide by zero
- maxPolls = 1
- } else {
- maxPolls = int((time.Duration(blocks) * blockPeriod) / pollPeriod)
- }
- return
-}
-
-func (txm *Txm) confirmTx(ctx context.Context, tc cosmosclient.Reader, txHash string, broadcasted []int64, maxPolls int, pollPeriod time.Duration) error {
- // We either mark these broadcasted txes as confirmed or errored.
- // Confirmed: we see the txhash onchain. There are no reorgs in cosmos chains.
- // Errored: we do not see the txhash onchain after waiting for N blocks worth
- // of time (plus a small buffer to account for block time variance) where N
- // is TimeoutHeight - HeightAtBroadcast. In other words, if we wait for that long
- // and the tx is not confirmed, we know it has timed out.
- for tries := 0; tries < maxPolls; tries++ {
- // Jitter in-case we're confirming multiple txes in parallel for different keys
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-time.After(utils.WithJitter(pollPeriod)):
- }
- // Confirm that this tx is onchain, ensuring the sequence number has incremented
- // so we can build a new batch
- tx, err := tc.Tx(txHash)
- if err != nil {
- if strings.Contains(err.Error(), "not found") {
- txm.lggr.Infow("txhash not found yet, still confirming", "hash", txHash)
- } else {
- txm.lggr.Errorw("error looking for hash of tx", "err", err, "hash", txHash)
- }
- continue
- }
- // Sanity check
- if tx.TxResponse == nil || tx.TxResponse.TxHash != txHash {
- txm.lggr.Errorw("error looking for hash of tx, unexpected response", "tx", tx, "hash", txHash)
- continue
- }
-
- txm.lggr.Infow("successfully sent batch", "hash", txHash, "msgs", broadcasted)
- // If confirmed mark these as completed.
- err = txm.orm.UpdateMsgs(broadcasted, db.Confirmed, nil)
- if err != nil {
- return err
- }
- return nil
- }
- txm.lggr.Errorw("unable to confirm tx after timeout period, marking errored", "hash", txHash)
- // If we are unable to confirm the tx after the timeout period
- // mark these msgs as errored
- err := txm.orm.UpdateMsgs(broadcasted, db.Errored, nil)
- if err != nil {
- txm.lggr.Errorw("unable to mark timed out txes as errored", "err", err, "txes", broadcasted, "num", len(broadcasted))
- return err
- }
- return nil
-}
-
-// Enqueue enqueue a msg destined for the cosmos chain.
-func (txm *Txm) Enqueue(contractID string, msg sdk.Msg) (int64, error) {
- typeURL, raw, err := txm.marshalMsg(msg)
- if err != nil {
- return 0, err
- }
-
- // We could consider simulating here too, but that would
- // introduce another network call and essentially double
- // the enqueue time. Enqueue is used in the context of OCRs Transmit
- // and must be fast, so we do the minimum.
-
- var id int64
- err = txm.orm.q.Transaction(func(tx pg.Queryer) (err error) {
- // cancel any unstarted msgs (normally just one)
- err = txm.orm.UpdateMsgsContract(contractID, db.Unstarted, db.Errored, pg.WithQueryer(tx))
- if err != nil {
- return err
- }
- id, err = txm.orm.InsertMsg(contractID, typeURL, raw, pg.WithQueryer(tx))
- return err
- })
- return id, err
-}
-
-func (txm *Txm) marshalMsg(msg sdk.Msg) (string, []byte, error) {
- switch ms := msg.(type) {
- case *wasmtypes.MsgExecuteContract:
- _, err := sdk.AccAddressFromBech32(ms.Sender)
- if err != nil {
- txm.lggr.Errorw("failed to parse sender, skipping", "err", err, "sender", ms.Sender)
- return "", nil, err
- }
-
- case *types.MsgSend:
- _, err := sdk.AccAddressFromBech32(ms.FromAddress)
- if err != nil {
- txm.lggr.Errorw("failed to parse sender, skipping", "err", err, "sender", ms.FromAddress)
- return "", nil, err
- }
-
- default:
- return "", nil, &cosmos.ErrMsgUnsupported{Msg: msg}
- }
- typeURL := sdk.MsgTypeURL(msg)
- raw, err := proto.Marshal(msg)
- if err != nil {
- txm.lggr.Errorw("failed to marshal msg, skipping", "err", err, "msg", msg)
- return "", nil, err
- }
- return typeURL, raw, nil
-}
-
-// GetMsgs returns any messages matching ids.
-func (txm *Txm) GetMsgs(ids ...int64) (adapters.Msgs, error) {
- return txm.orm.GetMsgs(ids...)
-}
-
-// GasPrice returns the gas price from the estimator in the configured fee token.
-func (txm *Txm) GasPrice() (sdk.DecCoin, error) {
- prices := txm.gpe.GasPrices()
- gasPrice, ok := prices[txm.cfg.GasToken()]
- if !ok {
- return sdk.DecCoin{}, errors.New("unexpected empty gas price")
- }
- return gasPrice, nil
-}
-
-// Close close service
-func (txm *Txm) Close() error {
- return txm.StopOnce("Txm", func() error {
- txm.sub.Close()
- close(txm.stop)
- <-txm.done
- return nil
- })
-}
-
-func (txm *Txm) Name() string { return txm.lggr.Name() }
-
-// Healthy service is healthy
-func (txm *Txm) Healthy() error {
- return nil
-}
-
-// Ready service is ready
-func (txm *Txm) Ready() error {
- return nil
-}
-
-func (txm *Txm) HealthReport() map[string]error { return map[string]error{txm.Name(): txm.Healthy()} }
diff --git a/core/chains/cosmos/cosmostxm/txm_internal_test.go b/core/chains/cosmos/cosmostxm/txm_internal_test.go
deleted file mode 100644
index f29f130cae..0000000000
--- a/core/chains/cosmos/cosmostxm/txm_internal_test.go
+++ /dev/null
@@ -1,426 +0,0 @@
-package cosmostxm
-
-import (
- "fmt"
- "testing"
- "time"
-
- wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
- tmservicetypes "github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
- cosmostypes "github.com/cosmos/cosmos-sdk/types"
- txtypes "github.com/cosmos/cosmos-sdk/types/tx"
- "github.com/pkg/errors"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
- "go.uber.org/zap/zapcore"
-
- cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
- tcmocks "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client/mocks"
- coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- cosmosdb "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
- relayutils "github.com/smartcontractkit/chainlink-relay/pkg/utils"
-
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/keystore"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-)
-
-func generateExecuteMsg(msg []byte, from, to cosmostypes.AccAddress) cosmostypes.Msg {
- return &wasmtypes.MsgExecuteContract{
- Sender: from.String(),
- Contract: to.String(),
- Msg: msg,
- Funds: cosmostypes.Coins{},
- }
-}
-
-func newReaderWriterMock(t *testing.T) *tcmocks.ReaderWriter {
- tc := new(tcmocks.ReaderWriter)
- tc.Test(t)
- t.Cleanup(func() { tc.AssertExpectations(t) })
- return tc
-}
-
-func TestTxm(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
- lggr := testutils.LoggerAssertMaxLevel(t, zapcore.ErrorLevel)
- ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, pgtest.NewQConfig(true))
- require.NoError(t, ks.Unlock("blah"))
-
- for i := 0; i < 4; i++ {
- _, err := ks.Cosmos().Create()
- require.NoError(t, err)
- }
-
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- adapter := newKeystoreAdapter(loopKs, "wasm")
- accounts, err := adapter.Accounts()
- require.NoError(t, err)
- require.Equal(t, len(accounts), 4)
-
- sender1, err := cosmostypes.AccAddressFromBech32(accounts[0])
- require.NoError(t, err)
- sender2, err := cosmostypes.AccAddressFromBech32(accounts[1])
- require.NoError(t, err)
- contract, err := cosmostypes.AccAddressFromBech32(accounts[2])
- require.NoError(t, err)
- contract2, err := cosmostypes.AccAddressFromBech32(accounts[3])
- require.NoError(t, err)
-
- logCfg := pgtest.NewQConfig(true)
- chainID := cosmostest.RandomChainID()
- two := int64(2)
- gasToken := "ucosm"
- cfg := &coscfg.TOMLConfig{Chain: coscfg.Chain{
- MaxMsgsPerBatch: &two,
- GasToken: &gasToken,
- }}
- cfg.SetDefaults()
- gpe := cosmosclient.NewMustGasPriceEstimator([]cosmosclient.GasPricesEstimator{
- cosmosclient.NewFixedGasPriceEstimator(map[string]cosmostypes.DecCoin{
- cfg.GasToken(): cosmostypes.NewDecCoinFromDec(cfg.GasToken(), cosmostypes.MustNewDecFromStr("0.01")),
- },
- lggr.(logger.SugaredLogger),
- ),
- }, lggr)
-
- t.Run("single msg", func(t *testing.T) {
- tc := newReaderWriterMock(t)
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, logCfg, nil)
-
- // Enqueue a single msg, then send it in a batch
- id1, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`1`), sender1, contract))
- require.NoError(t, err)
- tc.On("Account", mock.Anything).Return(uint64(0), uint64(0), nil)
- tc.On("BatchSimulateUnsigned", mock.Anything, mock.Anything).Return(&cosmosclient.BatchSimResults{
- Failed: nil,
- Succeeded: cosmosclient.SimMsgs{{ID: id1, Msg: &wasmtypes.MsgExecuteContract{
- Sender: sender1.String(),
- Msg: []byte(`1`),
- }}},
- }, nil)
- tc.On("SimulateUnsigned", mock.Anything, mock.Anything).Return(&txtypes.SimulateResponse{GasInfo: &cosmostypes.GasInfo{
- GasUsed: 1_000_000,
- }}, nil)
- tc.On("LatestBlock").Return(&tmservicetypes.GetLatestBlockResponse{SdkBlock: &tmservicetypes.Block{
- Header: tmservicetypes.Header{Height: 1},
- }}, nil)
- tc.On("CreateAndSign", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{0x01}, nil)
-
- txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
- tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil)
- tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil)
- txm.sendMsgBatch(testutils.Context(t))
-
- // Should be in completed state
- completed, err := txm.orm.GetMsgs(id1)
- require.NoError(t, err)
- require.Equal(t, 1, len(completed))
- assert.Equal(t, completed[0].State, cosmosdb.Confirmed)
- })
-
- t.Run("two msgs different accounts", func(t *testing.T) {
- tc := newReaderWriterMock(t)
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
-
- id1, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`0`), sender1, contract))
- require.NoError(t, err)
- id2, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`1`), sender2, contract))
- require.NoError(t, err)
-
- tc.On("Account", mock.Anything).Return(uint64(0), uint64(0), nil).Once()
- // Note this must be arg dependent, we don't know which order
- // the procesing will happen in (map iteration by from address).
- tc.On("BatchSimulateUnsigned", cosmosclient.SimMsgs{
- {
- ID: id2,
- Msg: &wasmtypes.MsgExecuteContract{
- Sender: sender2.String(),
- Msg: []byte(`1`),
- Contract: contract.String(),
- },
- },
- }, mock.Anything).Return(&cosmosclient.BatchSimResults{
- Failed: nil,
- Succeeded: cosmosclient.SimMsgs{
- {
- ID: id2,
- Msg: &wasmtypes.MsgExecuteContract{
- Sender: sender2.String(),
- Msg: []byte(`1`),
- Contract: contract.String(),
- },
- },
- },
- }, nil).Once()
- tc.On("SimulateUnsigned", mock.Anything, mock.Anything).Return(&txtypes.SimulateResponse{GasInfo: &cosmostypes.GasInfo{
- GasUsed: 1_000_000,
- }}, nil).Once()
- tc.On("LatestBlock").Return(&tmservicetypes.GetLatestBlockResponse{SdkBlock: &tmservicetypes.Block{
- Header: tmservicetypes.Header{Height: 1},
- }}, nil).Once()
- tc.On("CreateAndSign", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{0x01}, nil).Once()
- txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
- tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil).Once()
- tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil).Once()
- txm.sendMsgBatch(testutils.Context(t))
-
- // Should be in completed state
- completed, err := txm.orm.GetMsgs(id1, id2)
- require.NoError(t, err)
- require.Equal(t, 2, len(completed))
- assert.Equal(t, cosmosdb.Errored, completed[0].State) // cancelled
- assert.Equal(t, cosmosdb.Confirmed, completed[1].State)
- })
-
- t.Run("two msgs different contracts", func(t *testing.T) {
- tc := newReaderWriterMock(t)
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
-
- id1, err := txm.Enqueue(contract.String(), generateExecuteMsg([]byte(`0`), sender1, contract))
- require.NoError(t, err)
- id2, err := txm.Enqueue(contract2.String(), generateExecuteMsg([]byte(`1`), sender2, contract2))
- require.NoError(t, err)
- ids := []int64{id1, id2}
- senders := []string{sender1.String(), sender2.String()}
- contracts := []string{contract.String(), contract2.String()}
- for i := 0; i < 2; i++ {
- tc.On("Account", mock.Anything).Return(uint64(0), uint64(0), nil).Once()
- // Note this must be arg dependent, we don't know which order
- // the procesing will happen in (map iteration by from address).
- tc.On("BatchSimulateUnsigned", cosmosclient.SimMsgs{
- {
- ID: ids[i],
- Msg: &wasmtypes.MsgExecuteContract{
- Sender: senders[i],
- Msg: []byte(fmt.Sprintf(`%d`, i)),
- Contract: contracts[i],
- },
- },
- }, mock.Anything).Return(&cosmosclient.BatchSimResults{
- Failed: nil,
- Succeeded: cosmosclient.SimMsgs{
- {
- ID: ids[i],
- Msg: &wasmtypes.MsgExecuteContract{
- Sender: senders[i],
- Msg: []byte(fmt.Sprintf(`%d`, i)),
- Contract: contracts[i],
- },
- },
- },
- }, nil).Once()
- tc.On("SimulateUnsigned", mock.Anything, mock.Anything).Return(&txtypes.SimulateResponse{GasInfo: &cosmostypes.GasInfo{
- GasUsed: 1_000_000,
- }}, nil).Once()
- tc.On("LatestBlock").Return(&tmservicetypes.GetLatestBlockResponse{SdkBlock: &tmservicetypes.Block{
- Header: tmservicetypes.Header{Height: 1},
- }}, nil).Once()
- tc.On("CreateAndSign", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{0x01}, nil).Once()
- }
- txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
- tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil).Twice()
- tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil).Twice()
- txm.sendMsgBatch(testutils.Context(t))
-
- // Should be in completed state
- completed, err := txm.orm.GetMsgs(id1, id2)
- require.NoError(t, err)
- require.Equal(t, 2, len(completed))
- assert.Equal(t, cosmosdb.Confirmed, completed[0].State)
- assert.Equal(t, cosmosdb.Confirmed, completed[1].State)
- })
-
- t.Run("failed to confirm", func(t *testing.T) {
- tc := newReaderWriterMock(t)
- tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{
- Tx: &txtypes.Tx{},
- TxResponse: &cosmostypes.TxResponse{TxHash: "0x123"},
- }, errors.New("not found")).Twice()
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
- i, err := txm.orm.InsertMsg("blah", "", []byte{0x01})
- require.NoError(t, err)
- txh := "0x123"
- require.NoError(t, txm.orm.UpdateMsgs([]int64{i}, cosmosdb.Started, &txh))
- require.NoError(t, txm.orm.UpdateMsgs([]int64{i}, cosmosdb.Broadcasted, &txh))
- err = txm.confirmTx(testutils.Context(t), tc, txh, []int64{i}, 2, 1*time.Millisecond)
- require.NoError(t, err)
- m, err := txm.orm.GetMsgs(i)
- require.NoError(t, err)
- require.Equal(t, 1, len(m))
- assert.Equal(t, cosmosdb.Errored, m[0].State)
- })
-
- t.Run("confirm any unconfirmed", func(t *testing.T) {
- require.Equal(t, int64(2), cfg.MaxMsgsPerBatch())
- txHash1 := "0x1234"
- txHash2 := "0x1235"
- txHash3 := "0xabcd"
- tc := newReaderWriterMock(t)
- tc.On("Tx", txHash1).Return(&txtypes.GetTxResponse{
- TxResponse: &cosmostypes.TxResponse{TxHash: txHash1},
- }, nil).Once()
- tc.On("Tx", txHash2).Return(&txtypes.GetTxResponse{
- TxResponse: &cosmostypes.TxResponse{TxHash: txHash2},
- }, nil).Once()
- tc.On("Tx", txHash3).Return(&txtypes.GetTxResponse{
- TxResponse: &cosmostypes.TxResponse{TxHash: txHash3},
- }, nil).Once()
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfg, loopKs, lggr, pgtest.NewQConfig(true), nil)
-
- // Insert and broadcast 3 msgs with different txhashes.
- id1, err := txm.orm.InsertMsg("blah", "", []byte{0x01})
- require.NoError(t, err)
- id2, err := txm.orm.InsertMsg("blah", "", []byte{0x02})
- require.NoError(t, err)
- id3, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
- require.NoError(t, err)
- err = txm.orm.UpdateMsgs([]int64{id1}, cosmosdb.Started, &txHash1)
- require.NoError(t, err)
- err = txm.orm.UpdateMsgs([]int64{id2}, cosmosdb.Started, &txHash2)
- require.NoError(t, err)
- err = txm.orm.UpdateMsgs([]int64{id3}, cosmosdb.Started, &txHash3)
- require.NoError(t, err)
- err = txm.orm.UpdateMsgs([]int64{id1}, cosmosdb.Broadcasted, &txHash1)
- require.NoError(t, err)
- err = txm.orm.UpdateMsgs([]int64{id2}, cosmosdb.Broadcasted, &txHash2)
- require.NoError(t, err)
- err = txm.orm.UpdateMsgs([]int64{id3}, cosmosdb.Broadcasted, &txHash3)
- require.NoError(t, err)
-
- // Confirm them as in a restart while confirming scenario
- txm.confirmAnyUnconfirmed(testutils.Context(t))
- msgs, err := txm.orm.GetMsgs(id1, id2, id3)
- require.NoError(t, err)
- require.Equal(t, 3, len(msgs))
- assert.Equal(t, cosmosdb.Confirmed, msgs[0].State)
- assert.Equal(t, cosmosdb.Confirmed, msgs[1].State)
- assert.Equal(t, cosmosdb.Confirmed, msgs[2].State)
- })
-
- t.Run("expired msgs", func(t *testing.T) {
- tc := new(tcmocks.ReaderWriter)
- timeout, err := relayutils.NewDuration(1 * time.Millisecond)
- require.NoError(t, err)
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- two := int64(2)
- cfgShortExpiry := &coscfg.TOMLConfig{Chain: coscfg.Chain{
- MaxMsgsPerBatch: &two,
- TxMsgTimeout: &timeout,
- }}
- cfgShortExpiry.SetDefaults()
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfgShortExpiry, loopKs, lggr, pgtest.NewQConfig(true), nil)
-
- // Send a single one expired
- id1, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
- require.NoError(t, err)
- time.Sleep(1 * time.Millisecond)
- txm.sendMsgBatch(testutils.Context(t))
- // Should be marked errored
- m, err := txm.orm.GetMsgs(id1)
- require.NoError(t, err)
- assert.Equal(t, cosmosdb.Errored, m[0].State)
-
- // Send a batch which is all expired
- id2, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
- require.NoError(t, err)
- id3, err := txm.orm.InsertMsg("blah", "", []byte{0x03})
- require.NoError(t, err)
- time.Sleep(1 * time.Millisecond)
- txm.sendMsgBatch(testutils.Context(t))
- require.NoError(t, err)
- ms, err := txm.orm.GetMsgs(id2, id3)
- require.NoError(t, err)
- assert.Equal(t, cosmosdb.Errored, ms[0].State)
- assert.Equal(t, cosmosdb.Errored, ms[1].State)
- })
-
- t.Run("started msgs", func(t *testing.T) {
- tc := new(tcmocks.ReaderWriter)
- tc.On("Account", mock.Anything).Return(uint64(0), uint64(0), nil)
- tc.On("SimulateUnsigned", mock.Anything, mock.Anything).Return(&txtypes.SimulateResponse{GasInfo: &cosmostypes.GasInfo{
- GasUsed: 1_000_000,
- }}, nil)
- tc.On("LatestBlock").Return(&tmservicetypes.GetLatestBlockResponse{SdkBlock: &tmservicetypes.Block{
- Header: tmservicetypes.Header{Height: 1},
- }}, nil)
- tc.On("CreateAndSign", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{0x01}, nil)
- txResp := &cosmostypes.TxResponse{TxHash: "4BF5122F344554C53BDE2EBB8CD2B7E3D1600AD631C385A5D7CCE23C7785459A"}
- tc.On("Broadcast", mock.Anything, mock.Anything).Return(&txtypes.BroadcastTxResponse{TxResponse: txResp}, nil)
- tc.On("Tx", mock.Anything).Return(&txtypes.GetTxResponse{Tx: &txtypes.Tx{}, TxResponse: txResp}, nil)
- tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
- two := int64(2)
- cfgMaxMsgs := &coscfg.TOMLConfig{Chain: coscfg.Chain{
- MaxMsgsPerBatch: &two,
- }}
- cfgMaxMsgs.SetDefaults()
- loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
- txm := NewTxm(db, tcFn, *gpe, chainID, cfgMaxMsgs, loopKs, lggr, pgtest.NewQConfig(true), nil)
-
- // Leftover started is processed
- msg1 := generateExecuteMsg([]byte{0x03}, sender1, contract)
- id1 := mustInsertMsg(t, txm, contract.String(), msg1)
- require.NoError(t, txm.orm.UpdateMsgs([]int64{id1}, cosmosdb.Started, nil))
- msgs := cosmosclient.SimMsgs{{ID: id1, Msg: &wasmtypes.MsgExecuteContract{
- Sender: sender1.String(),
- Msg: []byte{0x03},
- Contract: contract.String(),
- }}}
- tc.On("BatchSimulateUnsigned", msgs, mock.Anything).
- Return(&cosmosclient.BatchSimResults{Failed: nil, Succeeded: msgs}, nil).Once()
- time.Sleep(1 * time.Millisecond)
- txm.sendMsgBatch(testutils.Context(t))
- m, err := txm.orm.GetMsgs(id1)
- require.NoError(t, err)
- assert.Equal(t, cosmosdb.Confirmed, m[0].State)
-
- // Leftover started is not cancelled
- msg2 := generateExecuteMsg([]byte{0x04}, sender1, contract)
- msg3 := generateExecuteMsg([]byte{0x05}, sender1, contract)
- id2 := mustInsertMsg(t, txm, contract.String(), msg2)
- require.NoError(t, txm.orm.UpdateMsgs([]int64{id2}, cosmosdb.Started, nil))
- time.Sleep(time.Millisecond) // ensure != CreatedAt
- id3 := mustInsertMsg(t, txm, contract.String(), msg3)
- msgs = cosmosclient.SimMsgs{{ID: id2, Msg: &wasmtypes.MsgExecuteContract{
- Sender: sender1.String(),
- Msg: []byte{0x04},
- Contract: contract.String(),
- }}, {ID: id3, Msg: &wasmtypes.MsgExecuteContract{
- Sender: sender1.String(),
- Msg: []byte{0x05},
- Contract: contract.String(),
- }}}
- tc.On("BatchSimulateUnsigned", msgs, mock.Anything).
- Return(&cosmosclient.BatchSimResults{Failed: nil, Succeeded: msgs}, nil).Once()
- time.Sleep(1 * time.Millisecond)
- txm.sendMsgBatch(testutils.Context(t))
- require.NoError(t, err)
- ms, err := txm.orm.GetMsgs(id2, id3)
- require.NoError(t, err)
- assert.Equal(t, cosmosdb.Confirmed, ms[0].State)
- assert.Equal(t, cosmosdb.Confirmed, ms[1].State)
- })
-}
-
-func mustInsertMsg(t *testing.T, txm *Txm, contractID string, msg cosmostypes.Msg) int64 {
- typeURL, raw, err := txm.marshalMsg(msg)
- require.NoError(t, err)
- id, err := txm.orm.InsertMsg(contractID, typeURL, raw)
- require.NoError(t, err)
- return id
-}
diff --git a/core/chains/cosmos/cosmostxm/txm_test.go b/core/chains/cosmos/cosmostxm/txm_test.go
deleted file mode 100644
index 25ac9e8d9e..0000000000
--- a/core/chains/cosmos/cosmostxm/txm_test.go
+++ /dev/null
@@ -1,121 +0,0 @@
-//go:build integration
-
-package cosmostxm_test
-
-// TestTxm_Integration is disabled in order to be moved to chainlink-cosmos before DB testing is available
-//func TestTxm_Integration(t *testing.T) {
-// chainID := cosmostest.RandomChainID()
-// cosmosChain := coscfg.Chain{}
-// cosmosChain.SetDefaults()
-// fallbackGasPrice := sdk.NewDecCoinFromDec(*cosmosChain.GasToken, sdk.MustNewDecFromStr("0.01"))
-// chainConfig := cosmos.CosmosConfig{ChainID: &chainID, Enabled: ptr(true), Chain: cosmosChain}
-// cfg, db := heavyweight.FullTestDBNoFixturesV2(t, "cosmos_txm", func(c *chainlink.Config, s *chainlink.Secrets) {
-// c.Cosmos = cosmos.CosmosConfigs{&chainConfig}
-// })
-// lggr := logger.TestLogger(t)
-// logCfg := pgtest.NewQConfig(true)
-// gpe := cosmosclient.NewMustGasPriceEstimator([]cosmosclient.GasPricesEstimator{
-// cosmosclient.NewFixedGasPriceEstimator(map[string]sdk.DecCoin{
-// *cosmosChain.GasToken: fallbackGasPrice,
-// },
-// lggr.(logger.SugaredLogger),
-// ),
-// }, lggr)
-// orm := cosmostxm.NewORM(chainID, db, lggr, logCfg)
-// eb := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, lggr, uuid.New())
-// require.NoError(t, eb.Start(testutils.Context(t)))
-// t.Cleanup(func() { require.NoError(t, eb.Close()) })
-// ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, pgtest.NewQConfig(true))
-// zeConfig := sdk.GetConfig()
-// fmt.Println(zeConfig)
-// accounts, testdir, tendermintURL := cosmosclient.SetupLocalCosmosNode(t, chainID, *cosmosChain.GasToken)
-// tc, err := cosmosclient.NewClient(chainID, tendermintURL, 0, lggr)
-// require.NoError(t, err)
-//
-// loopKs := &keystore.CosmosLoopKeystore{Cosmos: ks.Cosmos()}
-// keystoreAdapter := cosmostxm.NewKeystoreAdapter(loopKs, *cosmosChain.Bech32Prefix)
-//
-// // First create a transmitter key and fund it with 1k native tokens
-// require.NoError(t, ks.Unlock("blah"))
-// err = ks.Cosmos().EnsureKey()
-// require.NoError(t, err)
-// ksAccounts, err := keystoreAdapter.Accounts()
-// require.NoError(t, err)
-// transmitterAddress := ksAccounts[0]
-// transmitterID, err := sdk.AccAddressFromBech32(transmitterAddress)
-// require.NoError(t, err)
-// an, sn, err := tc.Account(accounts[0].Address)
-// require.NoError(t, err)
-// resp, err := tc.SignAndBroadcast([]sdk.Msg{banktypes.NewMsgSend(accounts[0].Address, transmitterID, sdk.NewCoins(sdk.NewInt64Coin(*cosmosChain.GasToken, 100000)))},
-// an, sn, gpe.GasPrices()[*cosmosChain.GasToken], accounts[0].PrivateKey, txtypes.BroadcastMode_BROADCAST_MODE_SYNC)
-// tx, success := cosmosclient.AwaitTxCommitted(t, tc, resp.TxResponse.TxHash)
-// require.True(t, success)
-// require.Equal(t, types.CodeTypeOK, tx.TxResponse.Code)
-// require.NoError(t, err)
-//
-// // TODO: find a way to pull this test artifact from
-// // the chainlink-cosmos repo instead of copying it to cores testdata
-// contractID := cosmosclient.DeployTestContract(t, tendermintURL, chainID, *cosmosChain.GasToken, accounts[0], cosmosclient.Account{
-// Name: "transmitter",
-// PrivateKey: cosmostxm.NewKeyWrapper(keystoreAdapter, transmitterAddress),
-// Address: transmitterID,
-// }, tc, testdir, "../../../testdata/cosmos/my_first_contract.wasm")
-//
-// tcFn := func() (cosmosclient.ReaderWriter, error) { return tc, nil }
-// // Start txm
-// txm := cosmostxm.NewTxm(db, tcFn, *gpe, chainID, &chainConfig, loopKs, lggr, pgtest.NewQConfig(true), eb)
-// require.NoError(t, txm.Start(testutils.Context(t)))
-//
-// // Change the contract state
-// setMsg := &wasmtypes.MsgExecuteContract{
-// Sender: transmitterID.String(),
-// Contract: contractID.String(),
-// Msg: []byte(`{"reset":{"count":5}}`),
-// Funds: sdk.Coins{},
-// }
-// _, err = txm.Enqueue(contractID.String(), setMsg)
-// require.NoError(t, err)
-//
-// // Observe the counter gets set eventually
-// gomega.NewWithT(t).Eventually(func() bool {
-// d, err := tc.ContractState(contractID, []byte(`{"get_count":{}}`))
-// require.NoError(t, err)
-// t.Log("contract value", string(d))
-// return string(d) == `{"count":5}`
-// }, 20*time.Second, time.Second).Should(gomega.BeTrue())
-// // Ensure messages are completed
-// gomega.NewWithT(t).Eventually(func() bool {
-// msgs, err := orm.GetMsgsState(Confirmed, 5)
-// require.NoError(t, err)
-// return 1 == len(msgs)
-// }, 5*time.Second, time.Second).Should(gomega.BeTrue())
-//
-// // Ensure invalid msgs are marked as errored
-// invalidMsg := &wasmtypes.MsgExecuteContract{
-// Sender: transmitterID.String(),
-// Contract: contractID.String(),
-// Msg: []byte(`{"blah":{"blah":5}}`),
-// Funds: sdk.Coins{},
-// }
-// _, err = txm.Enqueue(contractID.String(), invalidMsg)
-// require.NoError(t, err)
-// _, err = txm.Enqueue(contractID.String(), invalidMsg)
-// require.NoError(t, err)
-// _, err = txm.Enqueue(contractID.String(), setMsg)
-// require.NoError(t, err)
-//
-// // Ensure messages are completed
-// gomega.NewWithT(t).Eventually(func() bool {
-// succeeded, err := orm.GetMsgsState(Confirmed, 5)
-// require.NoError(t, err)
-// errored, err := orm.GetMsgsState(Errored, 5)
-// require.NoError(t, err)
-// t.Log("errored", len(errored), "succeeded", len(succeeded))
-// return 2 == len(succeeded) && 2 == len(errored)
-// }, 20*time.Second, time.Second).Should(gomega.BeTrue())
-//
-// // Observe the messages have been marked as completed
-// require.NoError(t, txm.Close())
-//}
-//
-//func ptr[T any](t T) *T { return &t }
diff --git a/core/chains/cosmos/relayer_adapter.go b/core/chains/cosmos/relayer_adapter.go
deleted file mode 100644
index ace441c2bb..0000000000
--- a/core/chains/cosmos/relayer_adapter.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package cosmos
-
-import (
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
-
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
-
- pkgcosmos "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
- "github.com/smartcontractkit/chainlink/v2/core/chains"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay"
-)
-
-// LegacyChainContainer is container interface for Cosmos chains
-type LegacyChainContainer interface {
- Get(id string) (adapters.Chain, error)
- Len() int
- List(ids ...string) ([]adapters.Chain, error)
- Slice() []adapters.Chain
-}
-
-type LegacyChains = chains.ChainsKV[adapters.Chain]
-
-var _ LegacyChainContainer = &LegacyChains{}
-
-func NewLegacyChains(m map[string]adapters.Chain) *LegacyChains {
- return chains.NewChainsKV[adapters.Chain](m)
-}
-
-type LoopRelayerChainer interface {
- loop.Relayer
- Chain() adapters.Chain
-}
-
-type LoopRelayerChain struct {
- loop.Relayer
- chain adapters.Chain
-}
-
-func NewLoopRelayerChain(r *pkgcosmos.Relayer, s adapters.Chain) *LoopRelayerChain {
- ra := relay.NewServerAdapter(r, s)
- return &LoopRelayerChain{
- Relayer: ra,
- chain: s,
- }
-}
-func (r *LoopRelayerChain) Chain() adapters.Chain {
- return r.chain
-}
-
-var _ LoopRelayerChainer = &LoopRelayerChain{}
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 1ef99992a6..308ebf8da8 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -173,9 +173,8 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G
if cfg.CosmosEnabled() {
cosmosCfg := chainlink.CosmosFactoryConfig{
- Keystore: keyStore.Cosmos(),
- TOMLConfigs: cfg.CosmosConfigs(),
- EventBroadcaster: eventBroadcaster,
+ Keystore: keyStore.Cosmos(),
+ TOMLConfigs: cfg.CosmosConfigs(),
}
initOps = append(initOps, chainlink.InitCosmos(ctx, relayerFactory, cosmosCfg))
}
diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go
index d70b06f5a9..89b8704f87 100644
--- a/core/cmd/shell_local_test.go
+++ b/core/cmd/shell_local_test.go
@@ -302,8 +302,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
legacy := cltest.NewLegacyChainsWithMockChain(t, ethClient, config)
- mockRelayerChainInteroperators := chainlinkmocks.NewRelayerChainInteroperators(t)
- mockRelayerChainInteroperators.On("LegacyEVMChains").Return(legacy, nil)
+ mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy}
app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe()
ethClient.On("Dial", mock.Anything).Return(nil)
@@ -385,8 +384,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
ethClient.On("Dial", mock.Anything).Return(nil)
legacy := cltest.NewLegacyChainsWithMockChain(t, ethClient, config)
- mockRelayerChainInteroperators := chainlinkmocks.NewRelayerChainInteroperators(t)
- mockRelayerChainInteroperators.On("LegacyEVMChains").Return(legacy, nil)
+ mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy}
app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe()
client := cmd.Shell{
@@ -465,8 +463,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) {
ethClient.On("Dial", mock.Anything).Return(nil)
legacy := cltest.NewLegacyChainsWithMockChain(t, ethClient, config)
- mockRelayerChainInteroperators := chainlinkmocks.NewRelayerChainInteroperators(t)
- mockRelayerChainInteroperators.On("LegacyEVMChains").Return(legacy, nil)
+ mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy}
app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(clienttypes.Successful, nil)
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index d47e6243b8..4cb9808fe2 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -414,11 +414,10 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn
if cfg.CosmosEnabled() {
cosmosCfg := chainlink.CosmosFactoryConfig{
- Keystore: keyStore.Cosmos(),
- TOMLConfigs: cfg.CosmosConfigs(),
- EventBroadcaster: eventBroadcaster,
- DB: db,
- QConfig: cfg.Database(),
+ Keystore: keyStore.Cosmos(),
+ TOMLConfigs: cfg.CosmosConfigs(),
+ DB: db,
+ QConfig: cfg.Database(),
}
initOps = append(initOps, chainlink.InitCosmos(testCtx, relayerFactory, cosmosCfg))
}
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 690a8d189c..f2b1f9a4c9 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -301,7 +301,7 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 5cbdb37427..683cc1ea06 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1456,8 +1456,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
diff --git a/core/services/chainlink/mocks/relayer_chain_interoperators.go b/core/services/chainlink/mocks/relayer_chain_interoperators.go
index 0a8758f6d4..81f112f766 100644
--- a/core/services/chainlink/mocks/relayer_chain_interoperators.go
+++ b/core/services/chainlink/mocks/relayer_chain_interoperators.go
@@ -1,248 +1,61 @@
-// Code generated by mockery v2.28.1. DO NOT EDIT.
-
package mocks
import (
- context "context"
-
- chainlink "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
-
- cosmos "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
+ "context"
+ "slices"
- evm "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ services2 "github.com/smartcontractkit/chainlink/v2/core/services"
+ "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
- // Manually edited. mockery generates the wrong dependency. edited to use `loop` rather than `loop/internal`
- // seems to caused by incorrect alias resolution of the relayer dep
- internal "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
- mock "github.com/stretchr/testify/mock"
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- relay "github.com/smartcontractkit/chainlink/v2/core/services/relay"
+ "github.com/smartcontractkit/chainlink/v2/core/services/relay"
- services "github.com/smartcontractkit/chainlink/v2/core/services"
-
- types "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
)
-// RelayerChainInteroperators is an autogenerated mock type for the RelayerChainInteroperators type
-type RelayerChainInteroperators struct {
- mock.Mock
-}
-
-// ChainStatus provides a mock function with given fields: ctx, id
-func (_m *RelayerChainInteroperators) ChainStatus(ctx context.Context, id relay.ID) (types.ChainStatus, error) {
- ret := _m.Called(ctx, id)
-
- var r0 types.ChainStatus
- var r1 error
- if rf, ok := ret.Get(0).(func(context.Context, relay.ID) (types.ChainStatus, error)); ok {
- return rf(ctx, id)
- }
- if rf, ok := ret.Get(0).(func(context.Context, relay.ID) types.ChainStatus); ok {
- r0 = rf(ctx, id)
- } else {
- r0 = ret.Get(0).(types.ChainStatus)
- }
-
- if rf, ok := ret.Get(1).(func(context.Context, relay.ID) error); ok {
- r1 = rf(ctx, id)
- } else {
- r1 = ret.Error(1)
- }
-
- return r0, r1
-}
-
-// ChainStatuses provides a mock function with given fields: ctx, offset, limit
-func (_m *RelayerChainInteroperators) ChainStatuses(ctx context.Context, offset int, limit int) ([]types.ChainStatus, int, error) {
- ret := _m.Called(ctx, offset, limit)
-
- var r0 []types.ChainStatus
- var r1 int
- var r2 error
- if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]types.ChainStatus, int, error)); ok {
- return rf(ctx, offset, limit)
- }
- if rf, ok := ret.Get(0).(func(context.Context, int, int) []types.ChainStatus); ok {
- r0 = rf(ctx, offset, limit)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]types.ChainStatus)
- }
- }
-
- 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(context.Context, int, int) error); ok {
- r2 = rf(ctx, offset, limit)
- } else {
- r2 = ret.Error(2)
- }
-
- return r0, r1, r2
+// FakeRelayerChainInteroperators is a fake chainlink.RelayerChainInteroperators.
+// This exists because mockery generation doesn't understand how to produce an alias instead of the underlying type (which is not exported in this case).
+type FakeRelayerChainInteroperators struct {
+ EVMChains evm.LegacyChainContainer
+ Nodes []types.NodeStatus
+ NodesErr error
}
-// Get provides a mock function with given fields: id
-func (_m *RelayerChainInteroperators) Get(id relay.ID) (internal.Relayer, error) {
- ret := _m.Called(id)
-
- var r0 internal.Relayer
- var r1 error
- if rf, ok := ret.Get(0).(func(relay.ID) (internal.Relayer, error)); ok {
- return rf(id)
- }
- if rf, ok := ret.Get(0).(func(relay.ID) internal.Relayer); ok {
- r0 = rf(id)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(internal.Relayer)
- }
- }
-
- if rf, ok := ret.Get(1).(func(relay.ID) error); ok {
- r1 = rf(id)
- } else {
- r1 = ret.Error(1)
- }
-
- return r0, r1
+func (f *FakeRelayerChainInteroperators) LegacyEVMChains() evm.LegacyChainContainer {
+ return f.EVMChains
}
-// LegacyCosmosChains provides a mock function with given fields:
-func (_m *RelayerChainInteroperators) LegacyCosmosChains() cosmos.LegacyChainContainer {
- ret := _m.Called()
-
- var r0 cosmos.LegacyChainContainer
- if rf, ok := ret.Get(0).(func() cosmos.LegacyChainContainer); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(cosmos.LegacyChainContainer)
- }
- }
-
- return r0
+func (f *FakeRelayerChainInteroperators) NodeStatuses(ctx context.Context, offset, limit int, relayIDs ...relay.ID) (nodes []types.NodeStatus, count int, err error) {
+ return slices.Clone(f.Nodes), len(f.Nodes), f.NodesErr
}
-// LegacyEVMChains provides a mock function with given fields:
-func (_m *RelayerChainInteroperators) LegacyEVMChains() evm.LegacyChainContainer {
- ret := _m.Called()
-
- var r0 evm.LegacyChainContainer
- if rf, ok := ret.Get(0).(func() evm.LegacyChainContainer); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(evm.LegacyChainContainer)
- }
- }
-
- return r0
+func (f *FakeRelayerChainInteroperators) Services() []services2.ServiceCtx {
+ panic("unimplemented")
}
-// List provides a mock function with given fields: filter
-func (_m *RelayerChainInteroperators) List(filter chainlink.FilterFn) chainlink.RelayerChainInteroperators {
- ret := _m.Called(filter)
-
- var r0 chainlink.RelayerChainInteroperators
- if rf, ok := ret.Get(0).(func(chainlink.FilterFn) chainlink.RelayerChainInteroperators); ok {
- r0 = rf(filter)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(chainlink.RelayerChainInteroperators)
- }
- }
-
- return r0
+func (f *FakeRelayerChainInteroperators) List(filter chainlink.FilterFn) chainlink.RelayerChainInteroperators {
+ panic("unimplemented")
}
-// NodeStatuses provides a mock function with given fields: ctx, offset, limit, relayIDs
-func (_m *RelayerChainInteroperators) NodeStatuses(ctx context.Context, offset int, limit int, relayIDs ...relay.ID) ([]types.NodeStatus, int, error) {
- _va := make([]interface{}, len(relayIDs))
- for _i := range relayIDs {
- _va[_i] = relayIDs[_i]
- }
- var _ca []interface{}
- _ca = append(_ca, ctx, offset, limit)
- _ca = append(_ca, _va...)
- ret := _m.Called(_ca...)
-
- var r0 []types.NodeStatus
- var r1 int
- var r2 error
- if rf, ok := ret.Get(0).(func(context.Context, int, int, ...relay.ID) ([]types.NodeStatus, int, error)); ok {
- return rf(ctx, offset, limit, relayIDs...)
- }
- if rf, ok := ret.Get(0).(func(context.Context, int, int, ...relay.ID) []types.NodeStatus); ok {
- r0 = rf(ctx, offset, limit, relayIDs...)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]types.NodeStatus)
- }
- }
-
- if rf, ok := ret.Get(1).(func(context.Context, int, int, ...relay.ID) int); ok {
- r1 = rf(ctx, offset, limit, relayIDs...)
- } else {
- r1 = ret.Get(1).(int)
- }
-
- if rf, ok := ret.Get(2).(func(context.Context, int, int, ...relay.ID) error); ok {
- r2 = rf(ctx, offset, limit, relayIDs...)
- } else {
- r2 = ret.Error(2)
- }
-
- return r0, r1, r2
+func (f *FakeRelayerChainInteroperators) Get(id relay.ID) (loop.Relayer, error) {
+ panic("unimplemented")
}
-// Services provides a mock function with given fields:
-func (_m *RelayerChainInteroperators) Services() []services.ServiceCtx {
- ret := _m.Called()
-
- var r0 []services.ServiceCtx
- if rf, ok := ret.Get(0).(func() []services.ServiceCtx); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]services.ServiceCtx)
- }
- }
-
- return r0
+func (f *FakeRelayerChainInteroperators) Slice() []loop.Relayer {
+ panic("unimplemented")
}
-// Slice provides a mock function with given fields:
-func (_m *RelayerChainInteroperators) Slice() []internal.Relayer {
- ret := _m.Called()
-
- var r0 []internal.Relayer
- if rf, ok := ret.Get(0).(func() []internal.Relayer); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]internal.Relayer)
- }
- }
-
- return r0
+func (f *FakeRelayerChainInteroperators) LegacyCosmosChains() chainlink.LegacyCosmosContainer {
+ panic("unimplemented")
}
-type mockConstructorTestingTNewRelayerChainInteroperators interface {
- mock.TestingT
- Cleanup(func())
+func (f *FakeRelayerChainInteroperators) ChainStatus(ctx context.Context, id relay.ID) (types.ChainStatus, error) {
+ panic("unimplemented")
}
-// NewRelayerChainInteroperators creates a new instance of RelayerChainInteroperators. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewRelayerChainInteroperators(t mockConstructorTestingTNewRelayerChainInteroperators) *RelayerChainInteroperators {
- mock := &RelayerChainInteroperators{}
- mock.Mock.Test(t)
-
- t.Cleanup(func() { mock.AssertExpectations(t) })
-
- return mock
+func (f *FakeRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]types.ChainStatus, int, error) {
+ panic("unimplemented")
}
diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go
index e039afbfc9..b2ec0822d4 100644
--- a/core/services/chainlink/relayer_chain_interoperators.go
+++ b/core/services/chainlink/relayer_chain_interoperators.go
@@ -7,11 +7,12 @@ import (
"sort"
"sync"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2"
@@ -24,10 +25,6 @@ var ErrNoSuchRelayer = errors.New("relayer does not exist")
// encapsulates relayers and chains and is the primary entry point for
// the node to access relayers, get legacy chains associated to a relayer
// and get status about the chains and nodes
-//
-// note the generated mockery code incorrectly resolves dependencies and needs to be manually edited
-// therefore this interface is not auto-generated. for reference use and edit the result:
-// `go:generate mockery --quiet --name RelayerChainInteroperators --output ./mocks/ --case=underscore“`
type RelayerChainInteroperators interface {
Services() []services.ServiceCtx
@@ -50,7 +47,7 @@ type LoopRelayerStorer interface {
// on the relayer interface.
type LegacyChainer interface {
LegacyEVMChains() evm.LegacyChainContainer
- LegacyCosmosChains() cosmos.LegacyChainContainer
+ LegacyCosmosChains() LegacyCosmosContainer
}
type ChainStatuser interface {
@@ -135,7 +132,7 @@ func InitCosmos(ctx context.Context, factory RelayerFactory, config CosmosFactor
op.loopRelayers[id] = a
legacyMap[id.ChainID] = a.Chain()
}
- op.legacyChains.CosmosChains = cosmos.NewLegacyChains(legacyMap)
+ op.legacyChains.CosmosChains = NewLegacyCosmos(legacyMap)
return nil
}
@@ -196,7 +193,7 @@ func (rs *CoreRelayerChainInteroperators) LegacyEVMChains() evm.LegacyChainConta
// LegacyCosmosChains returns a container with all the cosmos chains
// TODO BCF-2511
-func (rs *CoreRelayerChainInteroperators) LegacyCosmosChains() cosmos.LegacyChainContainer {
+func (rs *CoreRelayerChainInteroperators) LegacyCosmosChains() LegacyCosmosContainer {
rs.mu.Lock()
defer rs.mu.Unlock()
return rs.legacyChains.CosmosChains
@@ -355,5 +352,44 @@ func (rs *CoreRelayerChainInteroperators) Services() (s []services.ServiceCtx) {
// deprecated when chain-specific logic is removed from products.
type legacyChains struct {
EVMChains evm.LegacyChainContainer
- CosmosChains cosmos.LegacyChainContainer
+ CosmosChains LegacyCosmosContainer
}
+
+// LegacyCosmosContainer is container interface for Cosmos chains
+type LegacyCosmosContainer interface {
+ Get(id string) (adapters.Chain, error)
+ Len() int
+ List(ids ...string) ([]adapters.Chain, error)
+ Slice() []adapters.Chain
+}
+
+type LegacyCosmos = chains.ChainsKV[adapters.Chain]
+
+var _ LegacyCosmosContainer = &LegacyCosmos{}
+
+func NewLegacyCosmos(m map[string]adapters.Chain) *LegacyCosmos {
+ return chains.NewChainsKV[adapters.Chain](m)
+}
+
+type CosmosLoopRelayerChainer interface {
+ loop.Relayer
+ Chain() adapters.Chain
+}
+
+type CosmosLoopRelayerChain struct {
+ loop.Relayer
+ chain adapters.Chain
+}
+
+func NewCosmosLoopRelayerChain(r *cosmos.Relayer, s adapters.Chain) *CosmosLoopRelayerChain {
+ ra := relay.NewServerAdapter(r, s)
+ return &CosmosLoopRelayerChain{
+ Relayer: ra,
+ chain: s,
+ }
+}
+func (r *CosmosLoopRelayerChain) Chain() adapters.Chain {
+ return r.chain
+}
+
+var _ CosmosLoopRelayerChainer = &CosmosLoopRelayerChain{}
diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go
index cfc7dbadc1..8729306964 100644
--- a/core/services/chainlink/relayer_chain_interoperators_test.go
+++ b/core/services/chainlink/relayer_chain_interoperators_test.go
@@ -257,11 +257,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
name: "2 cosmos chains with 2 nodes",
initFuncs: []chainlink.CoreRelayerChainInitFunc{
chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{
- Keystore: keyStore.Cosmos(),
- TOMLConfigs: cfg.CosmosConfigs(),
- EventBroadcaster: pg.NewNullEventBroadcaster(),
- DB: db,
- QConfig: cfg.Database()}),
+ Keystore: keyStore.Cosmos(),
+ TOMLConfigs: cfg.CosmosConfigs(),
+ DB: db,
+ QConfig: cfg.Database()}),
},
expectedCosmosChainCnt: 2,
expectedCosmosNodeCnt: 2,
@@ -290,11 +289,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Keystore: keyStore.StarkNet(),
TOMLConfigs: cfg.StarknetConfigs()}),
chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{
- Keystore: keyStore.Cosmos(),
- TOMLConfigs: cfg.CosmosConfigs(),
- EventBroadcaster: pg.NewNullEventBroadcaster(),
- DB: db,
- QConfig: cfg.Database(),
+ Keystore: keyStore.Cosmos(),
+ TOMLConfigs: cfg.CosmosConfigs(),
+ DB: db,
+ QConfig: cfg.Database(),
}),
},
expectedEVMChainCnt: 2,
diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go
index a159ee7cd0..76bfcd1641 100644
--- a/core/services/chainlink/relayer_factory.go
+++ b/core/services/chainlink/relayer_factory.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/sqlx"
- pkgcosmos "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
+ "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
@@ -17,7 +17,7 @@ import (
pkgstarknet "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink"
starkchain "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/chain"
"github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
- "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/config/env"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -225,7 +225,6 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs config.TOML
type CosmosFactoryConfig struct {
Keystore keystore.Cosmos
coscfg.TOMLConfigs
- EventBroadcaster pg.EventBroadcaster
*sqlx.DB
pg.QConfig
}
@@ -238,9 +237,6 @@ func (c CosmosFactoryConfig) Validate() error {
if len(c.TOMLConfigs) == 0 {
err = errors.Join(err, fmt.Errorf("no CosmosConfigs provided"))
}
- if c.EventBroadcaster == nil {
- err = errors.Join(err, fmt.Errorf("nil EventBroadcaster"))
- }
if c.DB == nil {
err = errors.Join(err, fmt.Errorf("nil DB"))
}
@@ -254,12 +250,12 @@ func (c CosmosFactoryConfig) Validate() error {
return err
}
-func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConfig) (map[relay.ID]cosmos.LoopRelayerChainer, error) {
+func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConfig) (map[relay.ID]CosmosLoopRelayerChainer, error) {
err := config.Validate()
if err != nil {
return nil, fmt.Errorf("cannot create Cosmos relayer: %w", err)
}
- relayers := make(map[relay.ID]cosmos.LoopRelayerChainer)
+ relayers := make(map[relay.ID]CosmosLoopRelayerChainer)
var (
cosmosLggr = r.Logger.Named("Cosmos")
@@ -273,11 +269,9 @@ func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConf
lggr := cosmosLggr.Named(relayID.ChainID)
opts := cosmos.ChainOpts{
- QueryConfig: config.QConfig,
- Logger: lggr,
- DB: config.DB,
- KeyStore: loopKs,
- EventBroadcaster: config.EventBroadcaster,
+ Logger: lggr,
+ DB: config.DB,
+ KeyStore: loopKs,
}
chain, err := cosmos.NewChain(chainCfg, opts)
@@ -285,7 +279,7 @@ func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConf
return nil, fmt.Errorf("failed to load Cosmos chain %q: %w", relayID, err)
}
- relayers[relayID] = cosmos.NewLoopRelayerChain(pkgcosmos.NewRelayer(lggr, chain), chain)
+ relayers[relayID] = NewCosmosLoopRelayerChain(cosmos.NewRelayer(lggr, chain), chain)
}
return relayers, nil
diff --git a/core/services/pg/channels.go b/core/services/pg/channels.go
index 1d67dabe52..aed132a7f2 100644
--- a/core/services/pg/channels.go
+++ b/core/services/pg/channels.go
@@ -1,7 +1,4 @@
package pg
// Postgres channel to listen for new evm.txes
-const (
- ChannelInsertOnCosmosMsg = "insert_on_cosmos_msg"
- ChannelInsertOnEVMLogs = "evm.insert_on_logs"
-)
+const ChannelInsertOnEVMLogs = "evm.insert_on_logs"
diff --git a/core/store/migrate/migrations/0207_drop_insert_on_terra_msg.sql b/core/store/migrate/migrations/0207_drop_insert_on_terra_msg.sql
new file mode 100644
index 0000000000..f4ae4b98e2
--- /dev/null
+++ b/core/store/migrate/migrations/0207_drop_insert_on_terra_msg.sql
@@ -0,0 +1,20 @@
+-- +goose Up
+
+-- +goose StatementBegin
+DROP TRIGGER IF EXISTS insert_on_terra_msg ON PUBLIC.cosmos_msgs;
+DROP FUNCTION IF EXISTS PUBLIC.notify_terra_msg_insert;
+-- +goose StatementEnd
+
+-- +goose Down
+
+-- +goose StatementBegin
+CREATE FUNCTION notify_terra_msg_insert() RETURNS trigger
+ LANGUAGE plpgsql
+AS $$
+BEGIN
+ PERFORM pg_notify('insert_on_terra_msg'::text, NOW()::text);
+ RETURN NULL;
+END
+$$;
+CREATE TRIGGER notify_terra_msg_insertion AFTER INSERT ON cosmos_msgs FOR EACH STATEMENT EXECUTE PROCEDURE notify_terra_msg_insert();
+-- +goose StatementEnd
diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go
index 0dd45a1735..984aa9f618 100644
--- a/core/web/loader/loader_test.go
+++ b/core/web/loader/loader_test.go
@@ -26,7 +26,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/job"
jobORMMocks "github.com/smartcontractkit/chainlink/v2/core/services/job/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -69,9 +68,6 @@ func TestLoader_Nodes(t *testing.T) {
ctx := InjectDataloader(testutils.Context(t), app)
chainID1, chainID2, notAnID := big.NewInt(1), big.NewInt(2), big.NewInt(3)
- relayID1 := relay.ID{Network: relay.EVM, ChainID: relay.ChainID(chainID1.String())}
- relayID2 := relay.ID{Network: relay.EVM, ChainID: relay.ChainID(chainID2.String())}
- notARelayID := relay.ID{Network: relay.EVM, ChainID: relay.ChainID(notAnID.String())}
genNodeStat := func(id string) relaytypes.NodeStatus {
return relaytypes.NodeStatus{
@@ -79,11 +75,9 @@ func TestLoader_Nodes(t *testing.T) {
ChainID: id,
}
}
- rcInterops := chainlinkmocks.NewRelayerChainInteroperators(t)
- rcInterops.On("NodeStatuses", mock.Anything, 0, -1,
- relayID2, relayID1, notARelayID).Return([]relaytypes.NodeStatus{
+ rcInterops := &chainlinkmocks.FakeRelayerChainInteroperators{Nodes: []relaytypes.NodeStatus{
genNodeStat(chainID2.String()), genNodeStat(chainID1.String()),
- }, 2, nil)
+ }}
app.On("GetRelayers").Return(rcInterops)
batcher := nodeBatcher{app}
diff --git a/core/web/resolver/eth_key_test.go b/core/web/resolver/eth_key_test.go
index 6cac2f4ac4..a7f8ce56d9 100644
--- a/core/web/resolver/eth_key_test.go
+++ b/core/web/resolver/eth_key_test.go
@@ -100,7 +100,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.balM.On("GetEthBalance", address).Return(assets.NewEth(1))
f.Mocks.chain.On("BalanceMonitor").Return(f.Mocks.balM)
f.Mocks.chain.On("Config").Return(f.Mocks.scfg)
- f.Mocks.relayerChainInterops.On("LegacyEVMChains").Return(legacyEVMChains)
+ f.Mocks.relayerChainInterops.EVMChains = legacyEVMChains
f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID})
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
@@ -149,7 +149,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil)
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
- f.Mocks.relayerChainInterops.On("LegacyEVMChains").Return(f.Mocks.legacyEVMChains)
+ f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains
f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID})
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
@@ -268,7 +268,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, gError)
- f.Mocks.relayerChainInterops.On("LegacyEVMChains").Return(f.Mocks.legacyEVMChains)
+ f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains
f.App.On("GetRelayers").Return(f.Mocks.relayerChainInterops)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
},
@@ -302,7 +302,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(assets.NewLinkFromJuels(12), gError)
f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, nil)
- f.Mocks.relayerChainInterops.On("LegacyEVMChains").Return(f.Mocks.legacyEVMChains)
+ f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
f.Mocks.balM.On("GetEthBalance", address).Return(assets.NewEth(1))
f.Mocks.chain.On("BalanceMonitor").Return(f.Mocks.balM)
@@ -358,7 +358,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.chain.On("BalanceMonitor").Return(nil)
f.Mocks.chain.On("Config").Return(f.Mocks.scfg)
f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, nil)
- f.Mocks.relayerChainInterops.On("LegacyEVMChains").Return(f.Mocks.legacyEVMChains)
+ f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains
f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID})
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
diff --git a/core/web/resolver/node_test.go b/core/web/resolver/node_test.go
index e949a67a85..9f34b27420 100644
--- a/core/web/resolver/node_test.go
+++ b/core/web/resolver/node_test.go
@@ -5,10 +5,10 @@ import (
gqlerrors "github.com/graph-gophers/graphql-go/errors"
"github.com/pkg/errors"
- "github.com/stretchr/testify/mock"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
+ "github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -43,17 +43,16 @@ func TestResolver_Nodes(t *testing.T) {
name: "success",
authenticated: true,
before: func(f *gqlTestFramework) {
- f.App.On("GetRelayers").Return(f.Mocks.relayerChainInterops)
- f.Mocks.relayerChainInterops.On("NodeStatuses", mock.Anything, PageDefaultOffset, PageDefaultLimit).Return([]types.NodeStatus{
+ f.App.On("GetRelayers").Return(chainlink.RelayerChainInteroperators(f.Mocks.relayerChainInterops))
+ f.Mocks.relayerChainInterops.Nodes = []types.NodeStatus{
{
Name: "node-name",
ChainID: chainID.String(),
Config: `Name = 'node-name'`,
},
- }, 1, nil)
+ }
f.App.On("EVMORM").Return(f.Mocks.evmORM)
f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID})
-
},
query: query,
result: `
@@ -76,7 +75,7 @@ func TestResolver_Nodes(t *testing.T) {
name: "generic error",
authenticated: true,
before: func(f *gqlTestFramework) {
- f.Mocks.relayerChainInterops.On("NodeStatuses", mock.Anything, PageDefaultOffset, PageDefaultLimit).Return([]types.NodeStatus{}, 0, gError)
+ f.Mocks.relayerChainInterops.NodesErr = gError
f.App.On("GetRelayers").Return(f.Mocks.relayerChainInterops)
},
query: query,
diff --git a/core/web/resolver/resolver_test.go b/core/web/resolver/resolver_test.go
index d0523d6b96..fa8471c5e2 100644
--- a/core/web/resolver/resolver_test.go
+++ b/core/web/resolver/resolver_test.go
@@ -52,7 +52,7 @@ type mocks struct {
solana *keystoreMocks.Solana
chain *evmORMMocks.Chain
legacyEVMChains *evmORMMocks.LegacyChainContainer
- relayerChainInterops *chainlinkMocks.RelayerChainInteroperators
+ relayerChainInterops *chainlinkMocks.FakeRelayerChainInteroperators
ethClient *evmClientMocks.Client
eIMgr *webhookmocks.ExternalInitiatorManager
balM *evmORMMocks.BalanceMonitor
@@ -111,7 +111,7 @@ func setupFramework(t *testing.T) *gqlTestFramework {
solana: keystoreMocks.NewSolana(t),
chain: evmORMMocks.NewChain(t),
legacyEVMChains: evmORMMocks.NewLegacyChainContainer(t),
- relayerChainInterops: chainlinkMocks.NewRelayerChainInteroperators(t),
+ relayerChainInterops: &chainlinkMocks.FakeRelayerChainInteroperators{},
ethClient: evmClientMocks.NewClient(t),
eIMgr: webhookmocks.NewExternalInitiatorManager(t),
balM: evmORMMocks.NewBalanceMonitor(t),
diff --git a/go.mod b/go.mod
index ad3cb5f78e..2df4b05c74 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,6 @@ module github.com/smartcontractkit/chainlink/v2
go 1.21
require (
- github.com/CosmWasm/wasmd v0.40.1
github.com/Depado/ginprom v1.7.11
github.com/Masterminds/semver/v3 v3.2.1
github.com/Masterminds/sprig/v3 v3.2.3
@@ -24,7 +23,6 @@ require (
github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4
github.com/gin-gonic/gin v1.9.1
github.com/go-webauthn/webauthn v0.8.2
- github.com/gogo/protobuf v1.3.3
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8
github.com/google/uuid v1.3.1
github.com/gorilla/securecookie v1.1.1
@@ -67,7 +65,7 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
@@ -116,6 +114,7 @@ require (
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
+ github.com/CosmWasm/wasmd v0.40.1 // indirect
github.com/CosmWasm/wasmvm v1.2.4 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
@@ -184,6 +183,7 @@ require (
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.3.1+incompatible // indirect
+ github.com/gogo/protobuf v1.3.3 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
diff --git a/go.sum b/go.sum
index f879f16272..f13b00d6db 100644
--- a/go.sum
+++ b/go.sum
@@ -1457,8 +1457,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index aa670da1c9..be9285c6d4 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -383,7 +383,7 @@ require (
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index f7b55b259f..7c5542bfa6 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2360,8 +2360,8 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0 h1:YrJ3moRDu2kgdv4o3Hym/FWVF4MS5cIZ7o7wk+43pvk=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231030134738-81a5a89699a0/go.mod h1:fxtwgVZzTgoU1CpdSxNvFXecIY2r8DhH2JCzPO4e9G0=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
From 463f938e1fb9f4d3782c6f147331d22bc0dc59c4 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Thu, 2 Nov 2023 11:30:54 +0000
Subject: [PATCH 052/327] [chore] Skip Mercury/VRF flakey tests (#11141)
---
core/services/relay/evm/mercury/config_poller_test.go | 1 +
core/services/vrf/v2/integration_v2_plus_test.go | 2 ++
2 files changed, 3 insertions(+)
diff --git a/core/services/relay/evm/mercury/config_poller_test.go b/core/services/relay/evm/mercury/config_poller_test.go
index 6a692b0eac..1b3ba72128 100644
--- a/core/services/relay/evm/mercury/config_poller_test.go
+++ b/core/services/relay/evm/mercury/config_poller_test.go
@@ -115,6 +115,7 @@ func TestMercuryConfigPoller(t *testing.T) {
}
func TestNotify(t *testing.T) {
+ testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCF-2746")
feedIDStr := "8257737fdf4f79639585fd0ed01bea93c248a9ad940e98dd27f41c9b6230fed1"
feedIDBytes, err := hexutil.Decode("0x" + feedIDStr)
require.NoError(t, err)
diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go
index f08c10c200..6d2b77acb7 100644
--- a/core/services/vrf/v2/integration_v2_plus_test.go
+++ b/core/services/vrf/v2/integration_v2_plus_test.go
@@ -304,6 +304,7 @@ func newVRFCoordinatorV2PlusUniverse(t *testing.T, key ethkey.KeyV2, numConsumer
}
func TestVRFV2PlusIntegration_SingleConsumer_HappyPath_BatchFulfillment(t *testing.T) {
+ testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCF-2745")
t.Parallel()
ownerKey := cltest.MustGenerateRandomKey(t)
uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false)
@@ -456,6 +457,7 @@ func TestVRFV2PlusIntegration_SingleConsumer_HappyPath(t *testing.T) {
}
func TestVRFV2PlusIntegration_SingleConsumer_EOA_Request(t *testing.T) {
+ testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCF-2744")
t.Parallel()
ownerKey := cltest.MustGenerateRandomKey(t)
uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false)
From 627d698401b4b19321b7db603d4dbba4d1c8ca4e Mon Sep 17 00:00:00 2001
From: Sam
Date: Thu, 2 Nov 2023 09:52:49 -0400
Subject: [PATCH 053/327] Bump Chainlink-relay to
c686b4d48672d0eb818beafcff90ad4e33ea5db3 (#11145)
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 ++--
go.mod | 2 +-
go.sum | 4 ++--
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index f2b1f9a4c9..65dcec563e 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -302,7 +302,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 683cc1ea06..781eed46ce 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1458,8 +1458,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 h1:59vz5H52EpwWE/64ZQpNCs7Gtnyi7/ytjyoGjlbKhBA=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/go.mod b/go.mod
index 2df4b05c74..569912ed1b 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index f13b00d6db..155e54646d 100644
--- a/go.sum
+++ b/go.sum
@@ -1459,8 +1459,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 h1:59vz5H52EpwWE/64ZQpNCs7Gtnyi7/ytjyoGjlbKhBA=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index be9285c6d4..33beae119a 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -384,7 +384,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 7c5542bfa6..7969e82144 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2362,8 +2362,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111 h1:CElKhWq0WIa9Rmg5Ssajs5Hp3m3u/nYIQdXtpj2gbcc=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231031114820-e9826d481111/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 h1:59vz5H52EpwWE/64ZQpNCs7Gtnyi7/ytjyoGjlbKhBA=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From f7e868e171c0fc2ee656cd575c0912ead5b3fe2d Mon Sep 17 00:00:00 2001
From: Makram
Date: Thu, 2 Nov 2023 16:16:04 +0100
Subject: [PATCH 054/327] fix: v2 superscript (#11146)
* dereference only after parsing args
* fix sending key parsing
* fix public key parsing
---
.../vrfv2/testnet/v2scripts/super_scripts.go | 101 +++++++++++-------
1 file changed, 60 insertions(+), 41 deletions(-)
diff --git a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
index f5e3700569..23ad8e1374 100644
--- a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
+++ b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
@@ -5,10 +5,6 @@ import (
"encoding/hex"
"flag"
"fmt"
- "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/constants"
- "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/jobs"
- "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/model"
- "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/util"
"math/big"
"os"
"strings"
@@ -18,6 +14,11 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/shopspring/decimal"
+ "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/constants"
+ "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/jobs"
+ "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/model"
+ "github.com/smartcontractkit/chainlink/core/scripts/common/vrf/util"
+
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2"
@@ -37,12 +38,12 @@ func DeployUniverseViaCLI(e helpers.Environment) {
deployCmd := flag.NewFlagSet("deploy-universe", flag.ExitOnError)
// required flags
- linkAddress := *deployCmd.String("link-address", "", "address of link token")
- linkEthAddress := *deployCmd.String("link-eth-feed", "", "address of link eth feed")
- bhsContractAddressString := *deployCmd.String("bhs-address", "", "address of BHS contract")
- batchBHSAddressString := *deployCmd.String("batch-bhs-address", "", "address of Batch BHS contract")
- coordinatorAddressString := *deployCmd.String("coordinator-address", "", "address of VRF Coordinator contract")
- batchCoordinatorAddressString := *deployCmd.String("batch-coordinator-address", "", "address Batch VRF Coordinator contract")
+ linkAddress := deployCmd.String("link-address", "", "address of link token")
+ linkEthAddress := deployCmd.String("link-eth-feed", "", "address of link eth feed")
+ bhsContractAddressString := deployCmd.String("bhs-address", "", "address of BHS contract")
+ batchBHSAddressString := deployCmd.String("batch-bhs-address", "", "address of Batch BHS contract")
+ coordinatorAddressString := deployCmd.String("coordinator-address", "", "address of VRF Coordinator contract")
+ batchCoordinatorAddressString := deployCmd.String("batch-coordinator-address", "", "address Batch VRF Coordinator contract")
subscriptionBalanceJuelsString := deployCmd.String("subscription-balance", constants.SubscriptionBalanceJuels, "amount to fund subscription")
nodeSendingKeyFundingAmount := deployCmd.String("sending-key-funding-amount", constants.NodeSendingKeyFundingAmount, "CL node sending key funding amount")
@@ -87,7 +88,10 @@ func DeployUniverseViaCLI(e helpers.Environment) {
ReqsForTier5: big.NewInt(*reqsForTier5),
}
- vrfPrimaryNodeSendingKeys := strings.Split(*vrfPrimaryNodeSendingKeysString, ",")
+ var vrfPrimaryNodeSendingKeys []string
+ if len(*vrfPrimaryNodeSendingKeysString) > 0 {
+ vrfPrimaryNodeSendingKeys = strings.Split(*vrfPrimaryNodeSendingKeysString, ",")
+ }
nodesMap := make(map[string]model.Node)
@@ -100,14 +104,14 @@ func DeployUniverseViaCLI(e helpers.Environment) {
SendingKeyFundingAmount: fundingAmount,
}
- bhsContractAddress := common.HexToAddress(bhsContractAddressString)
- batchBHSAddress := common.HexToAddress(batchBHSAddressString)
- coordinatorAddress := common.HexToAddress(coordinatorAddressString)
- batchCoordinatorAddress := common.HexToAddress(batchCoordinatorAddressString)
+ bhsContractAddress := common.HexToAddress(*bhsContractAddressString)
+ batchBHSAddress := common.HexToAddress(*batchBHSAddressString)
+ coordinatorAddress := common.HexToAddress(*coordinatorAddressString)
+ batchCoordinatorAddress := common.HexToAddress(*batchCoordinatorAddressString)
contractAddresses := model.ContractAddresses{
- LinkAddress: linkAddress,
- LinkEthAddress: linkEthAddress,
+ LinkAddress: *linkAddress,
+ LinkEthAddress: *linkEthAddress,
BhsContractAddress: bhsContractAddress,
BatchBHSAddress: batchBHSAddress,
CoordinatorAddress: coordinatorAddress,
@@ -149,29 +153,32 @@ func VRFV2DeployUniverse(
batchFulfillmentEnabled bool,
nodesMap map[string]model.Node,
) model.JobSpecs {
-
- // Put key in ECDSA format
- if strings.HasPrefix(*registerKeyUncompressedPubKey, "0x") {
- *registerKeyUncompressedPubKey = strings.Replace(*registerKeyUncompressedPubKey, "0x", "04", 1)
- }
-
- // Generate compressed public key and key hash
- pubBytes, err := hex.DecodeString(*registerKeyUncompressedPubKey)
- helpers.PanicErr(err)
- pk, err := crypto.UnmarshalPubkey(pubBytes)
- helpers.PanicErr(err)
- var pkBytes []byte
- if big.NewInt(0).Mod(pk.Y, big.NewInt(2)).Uint64() != 0 {
- pkBytes = append(pk.X.Bytes(), 1)
- } else {
- pkBytes = append(pk.X.Bytes(), 0)
+ var compressedPkHex string
+ var keyHash common.Hash
+ if len(*registerKeyUncompressedPubKey) > 0 {
+ // Put key in ECDSA format
+ if strings.HasPrefix(*registerKeyUncompressedPubKey, "0x") {
+ *registerKeyUncompressedPubKey = strings.Replace(*registerKeyUncompressedPubKey, "0x", "04", 1)
+ }
+
+ // Generate compressed public key and key hash
+ pubBytes, err := hex.DecodeString(*registerKeyUncompressedPubKey)
+ helpers.PanicErr(err)
+ pk, err := crypto.UnmarshalPubkey(pubBytes)
+ helpers.PanicErr(err)
+ var pkBytes []byte
+ if big.NewInt(0).Mod(pk.Y, big.NewInt(2)).Uint64() != 0 {
+ pkBytes = append(pk.X.Bytes(), 1)
+ } else {
+ pkBytes = append(pk.X.Bytes(), 0)
+ }
+ var newPK secp256k1.PublicKey
+ copy(newPK[:], pkBytes)
+
+ compressedPkHex = hexutil.Encode(pkBytes)
+ keyHash, err = newPK.Hash()
+ helpers.PanicErr(err)
}
- var newPK secp256k1.PublicKey
- copy(newPK[:], pkBytes)
-
- compressedPkHex := hexutil.Encode(pkBytes)
- keyHash, err := newPK.Hash()
- helpers.PanicErr(err)
if len(contractAddresses.LinkAddress) == 0 {
fmt.Println("\nDeploying LINK Token...")
@@ -268,7 +275,13 @@ func VRFV2DeployUniverse(
e.ChainID, //evmChainID
strings.Join(util.MapToAddressArr(nodesMap[model.VRFPrimaryNodeName].SendingKeys), "\",\""), //fromAddresses
contractAddresses.CoordinatorAddress,
- nodesMap[model.VRFPrimaryNodeName].SendingKeys[0].Address,
+ func() string {
+ if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 {
+ return keys[0].Address
+ } else {
+ return common.HexToAddress("0x0").String()
+ }
+ }(),
contractAddresses.CoordinatorAddress,
contractAddresses.CoordinatorAddress,
)
@@ -283,7 +296,13 @@ func VRFV2DeployUniverse(
e.ChainID, //evmChainID
strings.Join(util.MapToAddressArr(nodesMap[model.VRFBackupNodeName].SendingKeys), "\",\""), //fromAddresses
contractAddresses.CoordinatorAddress,
- nodesMap[model.VRFPrimaryNodeName].SendingKeys[0],
+ func() string {
+ if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 {
+ return keys[0].Address
+ } else {
+ return common.HexToAddress("0x0").String()
+ }
+ }(),
contractAddresses.CoordinatorAddress,
contractAddresses.CoordinatorAddress,
)
From a08b7054e9384c597112496dbe23683983c84a00 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Thu, 2 Nov 2023 15:57:41 +0000
Subject: [PATCH 055/327] [BCF-2463] Add generic job type for lightweight OCR
plugins (#10665)
* [BCF-2463] Add generic job type for lightweight OCR plugins
* [chore] Refactor ErrJobSpecNoRelayer; add ErrRelayerNotEnabled
* [feedback] Move validation of PluginConfig to ocr2/validate/validate.go
* Add tests for pluginConfig
* Sensible defaults for command
---
core/services/ocr2/delegate.go | 169 ++++++++++++++++--
.../ocr2/plugins/generic/helpers_test.go | 7 +
.../ocr2/plugins/generic/merge_test.go | 32 ++++
.../generic/pipeline_runner_adapter_test.go | 35 +---
.../ocr2/plugins/generic/telemetry_adapter.go | 13 +-
.../plugins/generic/telemetry_adapter_test.go | 15 +-
core/services/ocr2/validate/validate.go | 33 ++++
core/services/ocr2/validate/validate_test.go | 83 +++++++++
go.mod | 2 +-
9 files changed, 334 insertions(+), 55 deletions(-)
create mode 100644 core/services/ocr2/plugins/generic/helpers_test.go
create mode 100644 core/services/ocr2/plugins/generic/merge_test.go
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index efb6f04fd3..e822fd5d8f 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -8,6 +8,7 @@ import (
"log"
"time"
+ "google.golang.org/grpc"
"gopkg.in/guregu/null.v4"
"github.com/ethereum/go-ethereum/common"
@@ -30,6 +31,7 @@ import (
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop/reportingplugins"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
@@ -43,6 +45,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/persistence"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/generic"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper"
@@ -70,7 +73,28 @@ import (
"github.com/smartcontractkit/chainlink/v2/plugins"
)
-var ErrJobSpecNoRelayer = errors.New("OCR2 job spec could not get relayer id")
+type ErrJobSpecNoRelayer struct {
+ PluginName string
+ Err error
+}
+
+func (e ErrJobSpecNoRelayer) Unwrap() error { return e.Err }
+
+func (e ErrJobSpecNoRelayer) Error() string {
+ return fmt.Sprintf("%s services: OCR2 job spec could not get relayer ID: %s", e.PluginName, e.Err)
+}
+
+type ErrRelayNotEnabled struct {
+ PluginName string
+ Relay string
+ Err error
+}
+
+func (e ErrRelayNotEnabled) Unwrap() error { return e.Err }
+
+func (e ErrRelayNotEnabled) Error() string {
+ return fmt.Sprintf("%s services: failed to get relay %s, is it enabled? %s", e.PluginName, e.Relay, e.Err)
+}
type RelayGetter interface {
Get(id relay.ID) (loop.Relayer, error)
@@ -245,7 +269,7 @@ func (d *Delegate) OnDeleteJob(jb job.Job, q pg.Queryer) error {
rid, err := spec.RelayID()
if err != nil {
- d.lggr.Errorw("DeleteJob: "+ErrJobSpecNoRelayer.Error(), "err", err)
+ d.lggr.Errorw("DeleteJob", "err", ErrJobSpecNoRelayer{Err: err, PluginName: string(spec.PluginType)})
return nil
}
// we only have clean to do for the EVM
@@ -337,7 +361,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("ServicesForSpec: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: string(spec.PluginType)}
}
if rid.Network == relay.EVM {
@@ -428,6 +452,9 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
s4PluginDB := NewDB(d.db, spec.ID, s4PluginId, lggr, d.cfg.Database())
return d.newServicesOCR2Functions(lggr, jb, runResults, bootstrapPeers, kb, ocrDB, thresholdPluginDB, s4PluginDB, lc, ocrLogger)
+ case types.GenericPlugin:
+ return d.newServicesGenericPlugin(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger)
+
default:
return nil, errors.Errorf("plugin type %s not supported", spec.PluginType)
}
@@ -473,6 +500,124 @@ func GetEVMEffectiveTransmitterID(jb *job.Job, chain evm.Chain, lggr logger.Suga
return spec.TransmitterID.String, nil
}
+type connProvider interface {
+ ClientConn() grpc.ClientConnInterface
+}
+
+func defaultPathFromPluginName(pluginName string) string {
+ // By default we install the command on the system path, in the
+ // form: `chainlink-`
+ return fmt.Sprintf("chainlink-%s", pluginName)
+}
+
+func (d *Delegate) newServicesGenericPlugin(
+ ctx context.Context,
+ lggr logger.SugaredLogger,
+ jb job.Job,
+ bootstrapPeers []commontypes.BootstrapperLocator,
+ kb ocr2key.KeyBundle,
+ ocrDB *db,
+ lc ocrtypes.LocalConfig,
+ ocrLogger commontypes.Logger,
+) (srvs []job.ServiceCtx, err error) {
+ spec := jb.OCR2OracleSpec
+
+ p := validate.OCR2GenericPluginConfig{}
+ err = json.Unmarshal(spec.PluginConfig.Bytes(), &p)
+ if err != nil {
+ return nil, err
+ }
+ cconf := p.CoreConfig
+
+ command := cconf.Command
+ if command == "" {
+ command = defaultPathFromPluginName(cconf.PluginName)
+ }
+
+ // NOTE: we don't need to validate this config, since that happens as part of creating the job.
+ // See: validate/validate.go's `validateSpec`.
+
+ rid, err := spec.RelayID()
+ if err != nil {
+ return nil, ErrJobSpecNoRelayer{PluginName: cconf.PluginName, Err: err}
+ }
+
+ relayer, err := d.RelayGetter.Get(rid)
+ if err != nil {
+ return nil, ErrRelayNotEnabled{Err: err, Relay: spec.Relay, PluginName: p.CoreConfig.PluginName}
+ }
+
+ provider, err := relayer.NewPluginProvider(ctx, types.RelayArgs{
+ ExternalJobID: jb.ExternalJobID,
+ JobID: spec.ID,
+ ContractID: spec.ContractID,
+ New: d.isNewlyCreatedJob,
+ RelayConfig: spec.RelayConfig.Bytes(),
+ ProviderType: cconf.ProviderType,
+ }, types.PluginArgs{
+ TransmitterID: spec.TransmitterID.String,
+ PluginConfig: spec.PluginConfig.Bytes(),
+ })
+ if err != nil {
+ return nil, err
+ }
+ srvs = append(srvs, provider)
+
+ oracleEndpoint := d.monitoringEndpointGen.GenMonitoringEndpoint(
+ spec.ContractID,
+ synchronization.TelemetryType(cconf.TelemetryType),
+ rid.Network,
+ rid.ChainID,
+ )
+ oracleArgs := libocr2.OCR2OracleArgs{
+ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2,
+ V2Bootstrappers: bootstrapPeers,
+ Database: ocrDB,
+ LocalConfig: lc,
+ Logger: ocrLogger,
+ MonitoringEndpoint: oracleEndpoint,
+ OffchainKeyring: kb,
+ OnchainKeyring: kb,
+ ContractTransmitter: provider.ContractTransmitter(),
+ ContractConfigTracker: provider.ContractConfigTracker(),
+ OffchainConfigDigester: provider.OffchainConfigDigester(),
+ }
+
+ pluginLggr := lggr.Named(cconf.PluginName).Named(spec.ContractID).Named(spec.GetID())
+ cmdFn, grpcOpts, err := d.cfg.RegisterLOOP(fmt.Sprintf("%s-%s-%s", cconf.PluginName, spec.ContractID, spec.GetID()), command)
+ if err != nil {
+ return nil, fmt.Errorf("failed to register loop: %w", err)
+ }
+
+ errorLog := &errorLog{jobID: jb.ID, recordError: d.jobORM.RecordError}
+ providerConn, ok := provider.(connProvider)
+ if !ok {
+ return nil, errors.New("provider not supported: the provider is not a LOOPP provider")
+ }
+
+ pluginConfig := types.ReportingPluginServiceConfig{
+ PluginName: cconf.PluginName,
+ Command: command,
+ ProviderType: cconf.ProviderType,
+ PluginConfig: string(p.PluginConfig),
+ }
+
+ pr := generic.NewPipelineRunnerAdapter(pluginLggr, jb, d.pipelineRunner)
+ ta := generic.NewTelemetryAdapter(d.monitoringEndpointGen)
+
+ plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerConn.ClientConn(), pr, ta, errorLog)
+ oracleArgs.ReportingPluginFactory = plugin
+ srvs = append(srvs, plugin)
+
+ oracle, err := libocr2.NewOracle(oracleArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ srvs = append(srvs, job.NewServiceAdapter(oracle))
+ return srvs, nil
+}
+
func (d *Delegate) newServicesMercury(
ctx context.Context,
lggr logger.SugaredLogger,
@@ -498,14 +643,14 @@ func (d *Delegate) newServicesMercury(
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("mercury services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "mercury"}
}
if rid.Network != relay.EVM {
return nil, fmt.Errorf("mercury services: expected EVM relayer got %s", rid.Network)
}
relayer, err := d.RelayGetter.Get(rid)
if err != nil {
- return nil, fmt.Errorf("failed to get relay %s is it enabled?: %w", spec.Relay, err)
+ return nil, ErrRelayNotEnabled{Err: err, Relay: spec.Relay, PluginName: "mercury"}
}
chain, err := d.legacyChains.Get(rid.ChainID)
if err != nil {
@@ -574,7 +719,7 @@ func (d *Delegate) newServicesMedian(
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("median services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "median"}
}
oracleArgsNoPlugin := libocr2.OCR2OracleArgs{
@@ -593,7 +738,7 @@ func (d *Delegate) newServicesMedian(
relayer, err := d.RelayGetter.Get(rid)
if err != nil {
- return nil, fmt.Errorf("median services; failed to get relay %s is it enabled?: %w", spec.Relay, err)
+ return nil, ErrRelayNotEnabled{Err: err, PluginName: "median", Relay: spec.Relay}
}
medianServices, err2 := median.NewMedianServices(ctx, jb, d.isNewlyCreatedJob, relayer, d.pipelineRunner, runResults, lggr, oracleArgsNoPlugin, mConfig, enhancedTelemChan, errorLog)
@@ -618,7 +763,7 @@ func (d *Delegate) newServicesDKG(
spec := jb.OCR2OracleSpec
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("DKG services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "DKG"}
}
if rid.Network != relay.EVM {
return nil, fmt.Errorf("DKG services: expected EVM relayer got %s", rid.Network)
@@ -687,7 +832,7 @@ func (d *Delegate) newServicesOCR2VRF(
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("VRF services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "VRF"}
}
if rid.Network != relay.EVM {
return nil, fmt.Errorf("VRF services: expected EVM relayer got %s", rid.Network)
@@ -912,7 +1057,7 @@ func (d *Delegate) newServicesOCR2Keepers21(
mc := d.cfg.Mercury().Credentials(credName)
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("keeper2 services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keeper2"}
}
if rid.Network != relay.EVM {
return nil, fmt.Errorf("keeper2 services: expected EVM relayer got %s", rid.Network)
@@ -1026,7 +1171,7 @@ func (d *Delegate) newServicesOCR2Keepers20(
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("keepers2.0 services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keepers2.0"}
}
if rid.Network != relay.EVM {
return nil, fmt.Errorf("keepers2.0 services: expected EVM relayer got %s", rid.Network)
@@ -1161,7 +1306,7 @@ func (d *Delegate) newServicesOCR2Functions(
rid, err := spec.RelayID()
if err != nil {
- return nil, fmt.Errorf("functions services: %w: %w", ErrJobSpecNoRelayer, err)
+ return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "functions"}
}
if rid.Network != relay.EVM {
return nil, fmt.Errorf("functions services: expected EVM relayer got %s", rid.Network)
diff --git a/core/services/ocr2/plugins/generic/helpers_test.go b/core/services/ocr2/plugins/generic/helpers_test.go
new file mode 100644
index 0000000000..e23e8e4642
--- /dev/null
+++ b/core/services/ocr2/plugins/generic/helpers_test.go
@@ -0,0 +1,7 @@
+package generic
+
+import "github.com/smartcontractkit/libocr/commontypes"
+
+func (t *TelemetryAdapter) Endpoints() map[[4]string]commontypes.MonitoringEndpoint {
+ return t.endpoints
+}
diff --git a/core/services/ocr2/plugins/generic/merge_test.go b/core/services/ocr2/plugins/generic/merge_test.go
new file mode 100644
index 0000000000..9618c62357
--- /dev/null
+++ b/core/services/ocr2/plugins/generic/merge_test.go
@@ -0,0 +1,32 @@
+package generic
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestMerge(t *testing.T) {
+ vars := map[string]interface{}{
+ "jb": map[string]interface{}{
+ "databaseID": "some-job-id",
+ },
+ }
+ addedVars := map[string]interface{}{
+ "jb": map[string]interface{}{
+ "some-other-var": "foo",
+ },
+ "val": 0,
+ }
+
+ merge(vars, addedVars)
+
+ assert.True(t, reflect.DeepEqual(vars, map[string]interface{}{
+ "jb": map[string]interface{}{
+ "databaseID": "some-job-id",
+ "some-other-var": "foo",
+ },
+ "val": 0,
+ }), vars)
+}
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 ee0038232d..ef0e7421b5 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
@@ -1,9 +1,8 @@
-package generic
+package generic_test
import (
"context"
"net/http"
- "reflect"
"testing"
"time"
@@ -20,6 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/generic"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -52,7 +52,7 @@ func TestAdapter_Integration(t *testing.T) {
http.DefaultClient,
http.DefaultClient,
)
- pra := NewPipelineRunnerAdapter(logger, job.Job{}, pr)
+ pra := generic.NewPipelineRunnerAdapter(logger, job.Job{}, pr)
results, err := pra.ExecuteRun(context.Background(), spec, types.Vars{Vars: map[string]interface{}{"val": 1}}, types.Options{})
require.NoError(t, err)
@@ -83,7 +83,7 @@ func TestAdapter_AddsDefaultVars(t *testing.T) {
logger := logger.TestLogger(t)
mpr := newMockPipelineRunner()
jobID, externalJobID, name := int32(100), uuid.New(), null.StringFrom("job-name")
- pra := NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name}, mpr)
+ pra := generic.NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name}, mpr)
_, err := pra.ExecuteRun(context.Background(), spec, types.Vars{}, types.Options{})
require.NoError(t, err)
@@ -105,7 +105,7 @@ func TestPipelineRunnerAdapter_SetsVarsOnSpec(t *testing.T) {
logger := logger.TestLogger(t)
mpr := newMockPipelineRunner()
jobID, externalJobID, name, jobType := int32(100), uuid.New(), null.StringFrom("job-name"), job.Type("generic")
- pra := NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name, Type: jobType}, mpr)
+ pra := generic.NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name, Type: jobType}, mpr)
maxDuration := time.Duration(100 * time.Second)
_, err := pra.ExecuteRun(context.Background(), spec, types.Vars{}, types.Options{MaxTaskDuration: maxDuration})
@@ -115,29 +115,4 @@ func TestPipelineRunnerAdapter_SetsVarsOnSpec(t *testing.T) {
assert.Equal(t, name.ValueOrZero(), mpr.spec.JobName)
assert.Equal(t, string(jobType), mpr.spec.JobType)
assert.Equal(t, maxDuration, mpr.spec.MaxTaskDuration.Duration())
-
-}
-
-func TestMerge(t *testing.T) {
- vars := map[string]interface{}{
- "jb": map[string]interface{}{
- "databaseID": "some-job-id",
- },
- }
- addedVars := map[string]interface{}{
- "jb": map[string]interface{}{
- "some-other-var": "foo",
- },
- "val": 0,
- }
-
- merge(vars, addedVars)
-
- assert.True(t, reflect.DeepEqual(vars, map[string]interface{}{
- "jb": map[string]interface{}{
- "databaseID": "some-job-id",
- "some-other-var": "foo",
- },
- "val": 0,
- }), vars)
}
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter.go b/core/services/ocr2/plugins/generic/telemetry_adapter.go
index a81befa985..e7f87dcd46 100644
--- a/core/services/ocr2/plugins/generic/telemetry_adapter.go
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter.go
@@ -6,17 +6,20 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
+ "github.com/smartcontractkit/chainlink/v2/core/services/synchronization"
+ "github.com/smartcontractkit/chainlink/v2/core/services/telemetry"
+
"github.com/smartcontractkit/chainlink-relay/pkg/types"
)
var _ types.TelemetryService = (*TelemetryAdapter)(nil)
type TelemetryAdapter struct {
- endpointGenerator types.MonitoringEndpointGenerator
+ endpointGenerator telemetry.MonitoringEndpointGenerator
endpoints map[[4]string]commontypes.MonitoringEndpoint
}
-func NewTelemetryAdapter(endpointGen types.MonitoringEndpointGenerator) *TelemetryAdapter {
+func NewTelemetryAdapter(endpointGen telemetry.MonitoringEndpointGenerator) *TelemetryAdapter {
return &TelemetryAdapter{
endpoints: make(map[[4]string]commontypes.MonitoringEndpoint),
endpointGenerator: endpointGen,
@@ -24,7 +27,7 @@ func NewTelemetryAdapter(endpointGen types.MonitoringEndpointGenerator) *Telemet
}
func (t *TelemetryAdapter) Send(ctx context.Context, network string, chainID string, contractID string, telemetryType string, payload []byte) error {
- e, err := t.getOrCreateEndpoint(contractID, telemetryType, network, chainID)
+ e, err := t.getOrCreateEndpoint(network, chainID, contractID, telemetryType)
if err != nil {
return err
}
@@ -32,7 +35,7 @@ func (t *TelemetryAdapter) Send(ctx context.Context, network string, chainID str
return nil
}
-func (t *TelemetryAdapter) getOrCreateEndpoint(contractID string, telemetryType string, network string, chainID string) (commontypes.MonitoringEndpoint, error) {
+func (t *TelemetryAdapter) getOrCreateEndpoint(network string, chainID string, contractID string, telemetryType string) (commontypes.MonitoringEndpoint, error) {
if contractID == "" {
return nil, errors.New("contractID cannot be empty")
}
@@ -49,7 +52,7 @@ func (t *TelemetryAdapter) getOrCreateEndpoint(contractID string, telemetryType
key := [4]string{network, chainID, contractID, telemetryType}
e, ok := t.endpoints[key]
if !ok {
- e = t.endpointGenerator.GenMonitoringEndpoint(network, chainID, contractID, telemetryType)
+ e = t.endpointGenerator.GenMonitoringEndpoint(contractID, synchronization.TelemetryType(telemetryType), network, chainID)
t.endpoints[key] = e
}
return e, nil
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
index d430b889a4..9c42b0f85d 100644
--- a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
@@ -1,13 +1,15 @@
-package generic
+package generic_test
import (
"context"
- "fmt"
"testing"
"github.com/smartcontractkit/libocr/commontypes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/generic"
+ "github.com/smartcontractkit/chainlink/v2/core/services/synchronization"
)
type mockEndpoint struct {
@@ -22,17 +24,17 @@ func (m *mockEndpoint) SendLog(payload []byte) { m.payload = payload }
type mockGenerator struct{}
-func (m *mockGenerator) GenMonitoringEndpoint(network, chainID, contractID, telemetryType string) commontypes.MonitoringEndpoint {
+func (m *mockGenerator) GenMonitoringEndpoint(contractID string, telemetryType synchronization.TelemetryType, network string, chainID string) commontypes.MonitoringEndpoint {
return &mockEndpoint{
network: network,
chainID: chainID,
contractID: contractID,
- telemetryType: telemetryType,
+ telemetryType: string(telemetryType),
}
}
func TestTelemetryAdapter(t *testing.T) {
- ta := NewTelemetryAdapter(&mockGenerator{})
+ ta := generic.NewTelemetryAdapter(&mockGenerator{})
tests := []struct {
name string
@@ -92,8 +94,7 @@ func TestTelemetryAdapter(t *testing.T) {
} else {
require.NoError(t, err)
key := [4]string{test.networkID, test.chainID, test.contractID, test.telemetryType}
- fmt.Printf("%+v", ta.endpoints)
- endpoint, ok := ta.endpoints[key]
+ endpoint, ok := ta.Endpoints()[key]
require.True(t, ok)
me := endpoint.(*mockEndpoint)
diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go
index cde1a1f927..78802f6559 100644
--- a/core/services/ocr2/validate/validate.go
+++ b/core/services/ocr2/validate/validate.go
@@ -114,6 +114,8 @@ func validateSpec(tree *toml.Tree, spec job.Job) error {
return nil
case types.Mercury:
return validateOCR2MercurySpec(spec.OCR2OracleSpec.PluginConfig, *spec.OCR2OracleSpec.FeedID)
+ case types.GenericPlugin:
+ return validateOCR2GenericPluginSpec(spec.OCR2OracleSpec.PluginConfig)
case "":
return errors.New("no plugin specified")
default:
@@ -123,6 +125,37 @@ func validateSpec(tree *toml.Tree, spec job.Job) error {
return nil
}
+type coreConfig struct {
+ Command string `json:"command"`
+ ProviderType string `json:"providerType"`
+ PluginName string `json:"pluginName"`
+ TelemetryType string `json:"telemetryType"`
+}
+
+type OCR2GenericPluginConfig struct {
+ CoreConfig coreConfig `json:"coreConfig"`
+ PluginConfig json.RawMessage
+}
+
+func validateOCR2GenericPluginSpec(jsonConfig job.JSONConfig) error {
+ p := OCR2GenericPluginConfig{}
+ err := json.Unmarshal(jsonConfig.Bytes(), &p)
+ if err != nil {
+ return err
+ }
+
+ cc := p.CoreConfig
+ if cc.PluginName == "" {
+ return errors.New("generic config invalid: must provide plugin name")
+ }
+
+ if cc.TelemetryType == "" {
+ return errors.New("generic config invalid: must provide telemetry type")
+ }
+
+ return nil
+}
+
func validateDKGSpec(jsonConfig job.JSONConfig) error {
if jsonConfig == nil {
return errors.New("pluginConfig is empty")
diff --git a/core/services/ocr2/validate/validate_test.go b/core/services/ocr2/validate/validate_test.go
index 4685ed745d..5b40224a4b 100644
--- a/core/services/ocr2/validate/validate_test.go
+++ b/core/services/ocr2/validate/validate_test.go
@@ -580,6 +580,89 @@ KeyID = "6f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c
require.Contains(t, err.Error(), "validation error for keyID")
},
},
+ {
+ name: "Generic plugin config validation - nothing provided",
+ toml: `
+type = "offchainreporting2"
+schemaVersion = 1
+name = "dkg"
+externalJobID = "6d46d85f-d38c-4f4a-9f00-ac29a25b6330"
+maxTaskDuration = "1s"
+contractID = "0x3e54dCc49F16411A3aaa4cDbC41A25bCa9763Cee"
+ocrKeyBundleID = "08d14c6eed757414d72055d28de6caf06535806c6a14e450f3a2f1c854420e17"
+p2pv2Bootstrappers = [
+ "12D3KooWSbPRwXY4gxFRJT7LWCnjgGbR4S839nfCRCDgQUiNenxa@127.0.0.1:8000"
+]
+relay = "evm"
+pluginType = "plugin"
+transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35"
+
+[relayConfig]
+chainID = 4
+
+[pluginConfig.coreConfig]
+`,
+ assertion: func(t *testing.T, os job.Job, err error) {
+ require.Error(t, err)
+ require.ErrorContains(t, err, "must provide plugin name")
+ },
+ },
+ {
+ name: "Generic plugin config validation - plugin name provided",
+ toml: `
+type = "offchainreporting2"
+schemaVersion = 1
+name = "dkg"
+externalJobID = "6d46d85f-d38c-4f4a-9f00-ac29a25b6330"
+maxTaskDuration = "1s"
+contractID = "0x3e54dCc49F16411A3aaa4cDbC41A25bCa9763Cee"
+ocrKeyBundleID = "08d14c6eed757414d72055d28de6caf06535806c6a14e450f3a2f1c854420e17"
+p2pv2Bootstrappers = [
+ "12D3KooWSbPRwXY4gxFRJT7LWCnjgGbR4S839nfCRCDgQUiNenxa@127.0.0.1:8000"
+]
+relay = "evm"
+pluginType = "plugin"
+transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35"
+
+[relayConfig]
+chainID = 4
+
+[pluginConfig.coreConfig]
+pluginName = "median"
+`,
+ assertion: func(t *testing.T, os job.Job, err error) {
+ require.Error(t, err)
+ require.ErrorContains(t, err, "must provide telemetry type")
+ },
+ },
+ {
+ name: "Generic plugin config validation - all provided",
+ toml: `
+type = "offchainreporting2"
+schemaVersion = 1
+name = "dkg"
+externalJobID = "6d46d85f-d38c-4f4a-9f00-ac29a25b6330"
+maxTaskDuration = "1s"
+contractID = "0x3e54dCc49F16411A3aaa4cDbC41A25bCa9763Cee"
+ocrKeyBundleID = "08d14c6eed757414d72055d28de6caf06535806c6a14e450f3a2f1c854420e17"
+p2pv2Bootstrappers = [
+ "12D3KooWSbPRwXY4gxFRJT7LWCnjgGbR4S839nfCRCDgQUiNenxa@127.0.0.1:8000"
+]
+relay = "evm"
+pluginType = "plugin"
+transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35"
+
+[relayConfig]
+chainID = 4
+
+[pluginConfig.coreConfig]
+pluginName = "median"
+telemetryType = "median"
+`,
+ assertion: func(t *testing.T, os job.Job, err error) {
+ require.NoError(t, err)
+ },
+ },
}
for _, tc := range tt {
diff --git a/go.mod b/go.mod
index 569912ed1b..820e42c330 100644
--- a/go.mod
+++ b/go.mod
@@ -97,6 +97,7 @@ require (
golang.org/x/time v0.3.0
golang.org/x/tools v0.14.0
gonum.org/v1/gonum v0.13.0
+ google.golang.org/grpc v1.58.3
google.golang.org/protobuf v1.31.0
gopkg.in/guregu/null.v2 v2.1.2
gopkg.in/guregu/null.v4 v4.0.0
@@ -364,7 +365,6 @@ require (
google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect
- google.golang.org/grpc v1.58.3 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
From 2c295a7756fa41b83039a721598514bdaa522297 Mon Sep 17 00:00:00 2001
From: ilija42 <57732589+ilija42@users.noreply.github.com>
Date: Thu, 2 Nov 2023 17:16:20 +0100
Subject: [PATCH 056/327] BCF-2749 remove legacy chains job orm (#11140)
* Remove legacy chains from job orm
- This removes evm cfg loading into jobs str8 from db
* Remove legacy chains from tests that used it for job orm
* Remove legacy env var test from TestRunner integration tests
* minor fix for test runner
* minor err handling change in vrf delegate_test.go
---
core/internal/cltest/cltest.go | 2 +-
core/internal/cltest/factories.go | 4 +-
core/internal/cltest/job_factories.go | 6 +-
core/internal/features/features_test.go | 3 +-
core/services/chainlink/application.go | 2 +-
core/services/cron/cron_test.go | 6 +-
core/services/directrequest/delegate_test.go | 2 +-
core/services/feeds/orm_test.go | 4 +-
core/services/fluxmonitorv2/orm_test.go | 6 +-
core/services/job/job_orm_test.go | 96 ++++++-----------
.../job/job_pipeline_orm_integration_test.go | 2 +-
core/services/job/orm.go | 68 +++---------
core/services/job/orm_test.go | 5 +-
core/services/job/runner_integration_test.go | 100 +-----------------
core/services/job/spawner_test.go | 11 +-
core/services/pipeline/orm_test.go | 10 +-
core/services/vrf/delegate_test.go | 4 +-
17 files changed, 75 insertions(+), 256 deletions(-)
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 4cb9808fe2..fb4a69cf30 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -191,7 +191,7 @@ func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipeline
lggr := logger.TestLogger(t)
prm := pipeline.NewORM(db, lggr, dbCfg, jpcfg.MaxSuccessfulRuns())
btORM := bridges.NewORM(db, lggr, dbCfg)
- jrm := job.NewORM(db, legacyChains, prm, btORM, keyStore, lggr, dbCfg)
+ jrm := job.NewORM(db, prm, btORM, keyStore, lggr, dbCfg)
pr := pipeline.NewRunner(prm, btORM, jpcfg, cfg, legacyChains, keyStore.Eth(), keyStore.VRF(), lggr, restrictedHTTPClient, unrestrictedHTTPClient)
return JobPipelineV2TestHelper{
prm,
diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go
index 85ffc6b02b..82235baf6b 100644
--- a/core/internal/cltest/factories.go
+++ b/core/internal/cltest/factories.go
@@ -563,7 +563,7 @@ func MustInsertV2JobSpec(t *testing.T, db *sqlx.DB, transmitterAddress common.Ad
PipelineSpecID: pipelineSpec.ID,
}
- jorm := job.NewORM(db, nil, nil, nil, nil, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database())
+ jorm := job.NewORM(db, nil, nil, nil, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database())
err = jorm.InsertJob(&jb)
require.NoError(t, err)
return jb
@@ -619,7 +619,7 @@ func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm keeper.ORM, from ethkey
tlg := logger.TestLogger(t)
prm := pipeline.NewORM(db, tlg, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
btORM := bridges.NewORM(db, tlg, cfg.Database())
- jrm := job.NewORM(db, nil, prm, btORM, nil, tlg, cfg.Database())
+ jrm := job.NewORM(db, prm, btORM, nil, tlg, cfg.Database())
err = jrm.InsertJob(&jb)
require.NoError(t, err)
return jb
diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go
index 77fee125e2..b76d6c7ec2 100644
--- a/core/internal/cltest/job_factories.go
+++ b/core/internal/cltest/job_factories.go
@@ -11,13 +11,11 @@ import (
"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"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
)
const (
@@ -66,9 +64,7 @@ func getORMs(t *testing.T, db *sqlx.DB) (jobORM job.ORM, pipelineORM pipeline.OR
lggr := logger.TestLogger(t)
pipelineORM = pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgeORM := bridges.NewORM(db, lggr, config.Database())
- cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(cc)
- jobORM = job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, config.Database())
+ jobORM = job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database())
t.Cleanup(func() { jobORM.Close() })
return
}
diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go
index 058c8325b9..3293066191 100644
--- a/core/internal/features/features_test.go
+++ b/core/internal/features/features_test.go
@@ -237,8 +237,7 @@ observationSource = """
pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
bridgeORM := bridges.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.Database())
- legacyChains := app.GetRelayers().LegacyEVMChains()
- jobORM := job.NewORM(app.GetSqlxDB(), legacyChains, pipelineORM, bridgeORM, app.KeyStore, logger.TestLogger(t), cfg.Database())
+ jobORM := job.NewORM(app.GetSqlxDB(), pipelineORM, bridgeORM, app.KeyStore, logger.TestLogger(t), cfg.Database())
runs := cltest.WaitForPipelineComplete(t, 0, jobID, 1, 2, jobORM, 5*time.Second, 300*time.Millisecond)
require.Len(t, runs, 1)
diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go
index 354f047904..63a9b2696c 100644
--- a/core/services/chainlink/application.go
+++ b/core/services/chainlink/application.go
@@ -251,7 +251,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
sessionORM = sessions.NewORM(db, cfg.WebServer().SessionTimeout().Duration(), globalLogger, cfg.Database(), auditLogger)
mercuryORM = mercury.NewORM(db, globalLogger, cfg.Database())
pipelineRunner = pipeline.NewRunner(pipelineORM, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyEVMChains, keyStore.Eth(), keyStore.VRF(), globalLogger, restrictedHTTPClient, unrestrictedHTTPClient)
- jobORM = job.NewORM(db, legacyEVMChains, pipelineORM, bridgeORM, keyStore, globalLogger, cfg.Database())
+ jobORM = job.NewORM(db, pipelineORM, bridgeORM, keyStore, globalLogger, cfg.Database())
txmORM = txmgr.NewTxStore(db, globalLogger, cfg.Database())
)
diff --git a/core/services/cron/cron_test.go b/core/services/cron/cron_test.go
index 19a51a3065..b561248edd 100644
--- a/core/services/cron/cron_test.go
+++ b/core/services/cron/cron_test.go
@@ -12,14 +12,12 @@ 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/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/cron"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
pipelinemocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks"
- evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
)
func TestCronV2Pipeline(t *testing.T) {
@@ -28,12 +26,10 @@ func TestCronV2Pipeline(t *testing.T) {
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db, cfg.Database())
- relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: evmtest.NewEthClientMockWithDefaultChain(t), KeyStore: keyStore.Eth()})
lggr := logger.TestLogger(t)
orm := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
btORM := bridges.NewORM(db, lggr, cfg.Database())
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayerExtenders)
- jobORM := job.NewORM(db, legacyChains, orm, btORM, keyStore, lggr, cfg.Database())
+ jobORM := job.NewORM(db, orm, btORM, keyStore, lggr, cfg.Database())
jb := &job.Job{
Type: job.Cron,
diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go
index e58dbaeb50..34c79a0afb 100644
--- a/core/services/directrequest/delegate_test.go
+++ b/core/services/directrequest/delegate_test.go
@@ -88,8 +88,8 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi
lggr := logger.TestLogger(t)
orm := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
btORM := bridges.NewORM(db, lggr, cfg.Database())
+ jobORM := job.NewORM(db, orm, btORM, keyStore, lggr, cfg.Database())
legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := job.NewORM(db, legacyChains, orm, btORM, keyStore, lggr, cfg.Database())
delegate := directrequest.NewDelegate(lggr, runner, orm, legacyChains, mailMon)
jb := cltest.MakeDirectRequestJobSpec(t)
diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go
index 746956bbfc..3d51ad45ff 100644
--- a/core/services/feeds/orm_test.go
+++ b/core/services/feeds/orm_test.go
@@ -1656,8 +1656,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job {
bridgeORM = bridges.NewORM(db, lggr, config.Database())
relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
)
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, config.Database())
+ orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database())
require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey))
require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey))
@@ -1667,6 +1666,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job {
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
+ legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
jb, err := ocr.ValidatedOracleSpecToml(legacyChains,
testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{
JobID: externalJobID.String(),
diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go
index 0bb0803261..6e06a1e65b 100644
--- a/core/services/fluxmonitorv2/orm_test.go
+++ b/core/services/fluxmonitorv2/orm_test.go
@@ -17,13 +17,11 @@ 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/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -96,11 +94,9 @@ func TestORM_UpdateFluxMonitorRoundStats(t *testing.T) {
pipelineORM := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
bridgeORM := bridges.NewORM(db, lggr, cfg.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{GeneralConfig: cfg, DB: db, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
// Instantiate a real job ORM because we need to create a job to satisfy
// a check in pipeline.CreateRun
- jobORM := job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, cfg.Database())
+ jobORM := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, cfg.Database())
orm := newORM(t, db, cfg.Database(), nil)
address := testutils.NewAddress()
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index 74416e68dc..6306dedcef 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -83,9 +83,7 @@ func TestORM(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: ethKeyStore})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
borm := bridges.NewORM(db, logger.TestLogger(t), config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
@@ -331,9 +329,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) {
lggr := logger.TestLogger(t)
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
scopedConfig := evmtest.NewChainScopedConfig(t, config)
korm := keeper.NewORM(db, logger.TestLogger(t), scopedConfig.Database())
@@ -342,6 +338,8 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) {
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
+ relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
+ legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
jb, err := ocr.ValidatedOracleSpecToml(legacyChains, testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{
TransmitterAddress: address.Hex(),
DS1BridgeName: bridge.Name.String(),
@@ -431,10 +429,8 @@ func TestORM_CreateJob_VRFV2(t *testing.T) {
lggr := logger.TestLogger(t)
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()}
jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(
@@ -514,9 +510,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) {
lggr := logger.TestLogger(t)
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(cc)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()}
jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(
@@ -599,9 +593,7 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) {
lggr := logger.TestLogger(t)
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jb, err := ocrbootstrap.ValidatedBootstrapSpecToml(testspecs.GetOCRBootstrapSpec())
require.NoError(t, err)
@@ -628,9 +620,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) {
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
t.Run("evm chain id validation for ocr works", func(t *testing.T) {
jb := job.Job{
@@ -725,9 +715,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) {
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
// defaultChainID is deprecated
defaultChainID := customChainID
@@ -745,6 +733,8 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) {
TransmitterAddress: address.Hex(),
JobID: externalJobID.UUID.String(),
})
+ relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
+ legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
jb, err := ocr.ValidatedOracleSpecToml(legacyChains, spec.Toml())
require.NoError(t, err)
@@ -794,9 +784,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) {
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
@@ -857,10 +845,7 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing
pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- require.True(t, relayExtenders.Len() > 0)
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jb, err := ocr2validate.ValidatedOracleSpecToml(config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal())
require.NoError(t, err)
@@ -974,14 +959,15 @@ func Test_FindJobs(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
+ relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
+ legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
jb1, err := ocr.ValidatedOracleSpecToml(legacyChains,
testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{
JobID: uuid.New().String(),
@@ -1054,9 +1040,8 @@ func Test_FindJob(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
@@ -1065,6 +1050,8 @@ func Test_FindJob(t *testing.T) {
// Must uniquely name the OCR Specs to properly insert a new job in the job table.
externalJobID := uuid.New()
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
+ relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
+ legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
job, err := ocr.ValidatedOracleSpecToml(legacyChains,
testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{
JobID: externalJobID.String(),
@@ -1232,9 +1219,7 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec())
require.NoError(t, err)
@@ -1263,20 +1248,7 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) {
})
t.Run("with chainID disabled", func(t *testing.T) {
- newCfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0] = &evmcfg.EVMConfig{
- ChainID: utils.NewBigI(0),
- Enabled: ptr(false),
- }
- c.EVM = append(c.EVM, &evmcfg.EVMConfig{
- ChainID: utils.NewBigI(123123123),
- Enabled: ptr(true),
- })
- })
- relayExtenders2 := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: newCfg, KeyStore: keyStore.Eth()})
- legacyChains2 := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders2)
-
- orm2 := NewTestORM(t, db, legacyChains2, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm2 := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jbs, err2 := orm2.FindJobsByPipelineSpecIDs([]int32{jb.PipelineSpecID})
require.NoError(t, err2)
@@ -1297,7 +1269,7 @@ func Test_FindPipelineRuns(t *testing.T) {
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
@@ -1358,7 +1330,7 @@ func Test_PipelineRunsByJobID(t *testing.T) {
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
@@ -1419,7 +1391,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) {
bridgesORM := bridges.NewORM(db, lggr, config.Database())
relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
@@ -1527,7 +1499,7 @@ func Test_FindPipelineRunsByIDs(t *testing.T) {
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
@@ -1583,9 +1555,7 @@ func Test_FindPipelineRunByID(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec())
require.NoError(t, err)
@@ -1628,9 +1598,7 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec())
require.NoError(t, err)
@@ -1667,9 +1635,7 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec())
require.NoError(t, err)
@@ -1705,7 +1671,7 @@ func Test_CountPipelineRunsByJobID(t *testing.T) {
bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database())
relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database())
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database())
_, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
_, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database())
diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go
index 1158fc4626..a2b6cc4618 100644
--- a/core/services/job/job_pipeline_orm_integration_test.go
+++ b/core/services/job/job_pipeline_orm_integration_test.go
@@ -156,7 +156,7 @@ 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, legacyChains, orm, btORM, keyStore, cfg.Database())
+ jobORM := NewTestORM(t, db, orm, btORM, keyStore, cfg.Database())
dbSpec := makeVoterTurnoutOCRJobSpec(t, transmitterAddress, bridge.Name.String(), bridge2.Name.String())
diff --git a/core/services/job/orm.go b/core/services/job/orm.go
index 372b2fe74a..c6ec4ed5c8 100644
--- a/core/services/job/orm.go
+++ b/core/services/job/orm.go
@@ -21,8 +21,6 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
- "github.com/smartcontractkit/chainlink/v2/core/chains"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -85,35 +83,25 @@ type ORMConfig interface {
}
type orm struct {
- q pg.Q
- legacyChains evm.LegacyChainContainer
- keyStore keystore.Master
- pipelineORM pipeline.ORM
- lggr logger.SugaredLogger
- cfg pg.QConfig
- bridgeORM bridges.ORM
+ q pg.Q
+ keyStore keystore.Master
+ pipelineORM pipeline.ORM
+ lggr logger.SugaredLogger
+ cfg pg.QConfig
+ bridgeORM bridges.ORM
}
var _ ORM = (*orm)(nil)
-func NewORM(
- db *sqlx.DB,
- legacyChains evm.LegacyChainContainer,
- pipelineORM pipeline.ORM,
- bridgeORM bridges.ORM,
- keyStore keystore.Master, // needed to validation key properties on new job creation
- lggr logger.Logger,
- cfg pg.QConfig,
-) *orm {
+func NewORM(db *sqlx.DB, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, lggr logger.Logger, cfg pg.QConfig) *orm {
namedLogger := logger.Sugared(lggr.Named("JobORM"))
return &orm{
- q: pg.NewQ(db, namedLogger, cfg),
- legacyChains: legacyChains,
- keyStore: keyStore,
- pipelineORM: pipelineORM,
- bridgeORM: bridgeORM,
- lggr: namedLogger,
- cfg: cfg,
+ q: pg.NewQ(db, namedLogger, cfg),
+ keyStore: keyStore,
+ pipelineORM: pipelineORM,
+ bridgeORM: bridgeORM,
+ lggr: namedLogger,
+ cfg: cfg,
}
}
func (o *orm) Close() error {
@@ -704,29 +692,12 @@ func (o *orm) FindJobs(offset, limit int) (jobs []Job, count int, err error) {
if err != nil {
return err
}
- for i := range jobs {
- err = multierr.Combine(err, o.LoadConfigVars(&jobs[i]))
- }
+
return nil
})
return jobs, int(count), err
}
-func (o *orm) LoadConfigVars(jb *Job) error {
- if jb.OCROracleSpec != nil {
- ch, err := o.legacyChains.Get(jb.OCROracleSpec.EVMChainID.String())
- if err != nil {
- return err
- }
- newSpec, err := LoadConfigVarsOCR(ch.Config().EVM().OCR(), ch.Config().OCR(), *jb.OCROracleSpec)
- if err != nil {
- return err
- }
- jb.OCROracleSpec = newSpec
- }
- return nil
-}
-
func LoadDefaultVRFPollPeriod(vrfs VRFSpec) *VRFSpec {
if vrfs.PollPeriod == 0 {
vrfs.PollPeriod = 5 * time.Second
@@ -842,7 +813,7 @@ func (o *orm) FindJobWithoutSpecErrors(id int32) (jb Job, err error) {
return jb, errors.Wrap(err, "FindJobWithoutSpecErrors failed")
}
- return jb, o.LoadConfigVars(&jb)
+ return jb, nil
}
// FindSpecErrorsByJobIDs returns all jobs spec errors by jobs IDs
@@ -931,7 +902,7 @@ func (o *orm) findJob(jb *Job, col string, arg interface{}, qopts ...pg.QOpt) er
if err != nil {
return errors.Wrap(err, "findJob failed")
}
- return o.LoadConfigVars(jb)
+ return nil
}
func (o *orm) FindJobIDsWithBridge(name string) (jids []int32, err error) {
@@ -1174,13 +1145,6 @@ func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) {
if err != nil {
return err
}
- for i := range jbs {
- err = o.LoadConfigVars(&jbs[i])
- //We must return the jobs even if the chainID is disabled
- if err != nil && !errors.Is(err, chains.ErrNoSuchChainID) {
- return err
- }
- }
return nil
})
diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go
index cd437147b4..48805388a3 100644
--- a/core/services/job/orm_test.go
+++ b/core/services/job/orm_test.go
@@ -9,7 +9,6 @@ import (
"github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -22,8 +21,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
-func NewTestORM(t *testing.T, db *sqlx.DB, legacyChains evm.LegacyChainContainer, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, cfg pg.QConfig) job.ORM {
- o := job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, logger.TestLogger(t), cfg)
+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)
t.Cleanup(func() { o.Close() })
return o
}
diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go
index c0fff1e560..7e8ed5e87f 100644
--- a/core/services/job/runner_integration_test.go
+++ b/core/services/job/runner_integration_test.go
@@ -85,7 +85,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, legacyChains, pipelineORM, btORM, keyStore, config.Database())
+ jobORM := NewTestORM(t, db, pipelineORM, btORM, keyStore, config.Database())
_, placeHolderAddress := cltest.MustInsertRandomKey(t, keyStore.Eth())
@@ -428,45 +428,7 @@ answer1 [type=median index=0];
}
})
- t.Run("missing required env vars", func(t *testing.T) {
- s := `
- type = "offchainreporting"
- schemaVersion = 1
- contractAddress = "%s"
- isBootstrapPeer = false
- evmChainID = "0"
- observationSource = """
-ds1 [type=http method=GET url="%s" allowunrestrictednetworkaccess="true" %s];
-ds1_parse [type=jsonparse path="USD" lax=true];
-ds1 -> ds1_parse;
-"""
-`
- s = fmt.Sprintf(s, cltest.NewEIP55Address(), "http://blah.com", "")
- jb, err := ocr.ValidatedOracleSpecToml(legacyChains, s)
- require.NoError(t, err)
- err = toml.Unmarshal([]byte(s), &jb)
- require.NoError(t, err)
- jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s"))
- err = jobORM.CreateJob(&jb)
- require.NoError(t, err)
- sd := ocr.NewDelegate(
- db,
- jobORM,
- keyStore,
- nil,
- nil,
- nil,
- legacyChains,
- logger.TestLogger(t),
- config.Database(),
- srvctest.Start(t, utils.NewMailboxMonitor(t.Name())),
- )
- _, err = sd.ServicesForSpec(jb)
- // We expect this to fail as neither the required vars are not set either via the env nor the job itself.
- require.Error(t, err)
- })
-
- t.Run("use env for minimal bootstrap", func(t *testing.T) {
+ t.Run("minimal bootstrap", func(t *testing.T) {
s := `
type = "offchainreporting"
schemaVersion = 1
@@ -504,53 +466,6 @@ ds1 -> ds1_parse;
require.NoError(t, err)
})
- t.Run("use env for minimal non-bootstrap", func(t *testing.T) {
- s := `
- type = "offchainreporting"
- schemaVersion = 1
- contractAddress = "%s"
- isBootstrapPeer = false
- observationTimeout = "15s"
- evmChainID = "0"
- observationSource = """
-ds1 [type=http method=GET url="%s" allowunrestrictednetworkaccess="true" %s];
-ds1_parse [type=jsonparse path="USD" lax=true];
-ds1 -> ds1_parse;
-"""
-`
- s = fmt.Sprintf(s, cltest.NewEIP55Address(), "http://blah.com", "")
- jb, err := ocr.ValidatedOracleSpecToml(legacyChains, s)
- require.NoError(t, err)
- err = toml.Unmarshal([]byte(s), &jb)
- require.NoError(t, err)
- jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s"))
- err = jobORM.CreateJob(&jb)
- require.NoError(t, err)
- // Assert the override
- assert.Equal(t, jb.OCROracleSpec.ObservationTimeout, models.Interval(cltest.MustParseDuration(t, "15s")))
- // Assert that this is default
- assert.Equal(t, models.Interval(20000000000), jb.OCROracleSpec.BlockchainTimeout)
- assert.Equal(t, models.Interval(cltest.MustParseDuration(t, "1s")), jb.MaxTaskDuration)
-
- lggr := logger.TestLogger(t)
- pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr)
- require.NoError(t, pw.Start(testutils.Context(t)))
- sd := ocr.NewDelegate(
- db,
- jobORM,
- keyStore,
- nil,
- pw,
- monitoringEndpoint,
- legacyChains,
- lggr,
- config.Database(),
- srvctest.Start(t, utils.NewMailboxMonitor(t.Name())),
- )
- _, err = sd.ServicesForSpec(jb)
- require.NoError(t, err)
- })
-
t.Run("test min non-bootstrap", func(t *testing.T) {
kb, err := keyStore.OCR().Create()
require.NoError(t, err)
@@ -765,9 +680,6 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) {
})
app := cltest.NewApplicationWithConfig(t, cfg, ethClient, cltest.UseRealExternalInitiatorManager)
- keyStore := cltest.NewKeyStore(t, app.GetSqlxDB(), pgtest.NewQConfig(true))
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: app.GetSqlxDB(), Client: ethClient, GeneralConfig: cfg, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
require.NoError(t, app.Start(testutils.Context(t)))
var (
@@ -898,7 +810,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) {
pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.Database())
- jobORM := NewTestORM(t, app.GetSqlxDB(), legacyChains, pipelineORM, bridgesORM, app.KeyStore, cfg.Database())
+ jobORM := NewTestORM(t, app.GetSqlxDB(), pipelineORM, bridgesORM, app.KeyStore, cfg.Database())
// Trigger v2/resume
select {
@@ -947,10 +859,6 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) {
})
app := cltest.NewApplicationWithConfig(t, cfg, ethClient, cltest.UseRealExternalInitiatorManager)
- keyStore := cltest.NewKeyStore(t, app.GetSqlxDB(), pgtest.NewQConfig(true))
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: app.GetSqlxDB(), Client: ethClient, GeneralConfig: cfg, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
-
require.NoError(t, app.Start(testutils.Context(t)))
var (
@@ -1079,7 +987,7 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) {
pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.Database())
- jobORM := NewTestORM(t, app.GetSqlxDB(), legacyChains, pipelineORM, bridgesORM, app.KeyStore, cfg.Database())
+ jobORM := NewTestORM(t, app.GetSqlxDB(), pipelineORM, bridgesORM, app.KeyStore, cfg.Database())
// Trigger v2/resume
select {
diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go
index be4a480a6c..1f10a86e9c 100644
--- a/core/services/job/spawner_test.go
+++ b/core/services/job/spawner_test.go
@@ -13,6 +13,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -97,7 +98,7 @@ 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, legacyChains, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
+ orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
a := utils.NewDependentAwaiter()
a.AddDependents(1)
spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{}, db, lggr, []utils.DependentAwaiter{a})
@@ -120,7 +121,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, legacyChains, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
+ orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
eventuallyA := cltest.NewAwaiter()
serviceA1 := mocks.NewServiceCtx(t)
@@ -185,7 +186,7 @@ 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, legacyChains, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
+ orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
mailMon := srvctest.Start(t, utils.NewMailboxMonitor(t.Name()))
d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon)
delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d}
@@ -219,7 +220,7 @@ 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, legacyChains, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
+ orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
mailMon := srvctest.Start(t, utils.NewMailboxMonitor(t.Name()))
d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon)
delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d}
@@ -297,7 +298,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) {
jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, config, address, chain.ID(), 2)
- orm := NewTestORM(t, db, legacyChains, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
+ orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database())
mailMon := srvctest.Start(t, utils.NewMailboxMonitor(t.Name()))
processConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, func(name string) (*plugins.RegisteredLoop, error) { return nil, nil })
diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go
index a487c231fb..f916c24f0a 100644
--- a/core/services/pipeline/orm_test.go
+++ b/core/services/pipeline/orm_test.go
@@ -17,14 +17,12 @@ 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/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -522,9 +520,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) {
porm := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgeORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jorm := job.NewORM(db, legacyChains, porm, bridgeORM, keyStore, lggr, config.Database())
+ jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr, config.Database())
defer func() { assert.NoError(t, jorm.Close()) }()
timestamp := time.Now()
@@ -624,9 +620,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) {
porm := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns())
bridgeORM := bridges.NewORM(db, lggr, config.Database())
- relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()})
- legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
- jorm := job.NewORM(db, legacyChains, porm, bridgeORM, keyStore, lggr, config.Database())
+ jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr, config.Database())
defer func() { assert.NoError(t, jorm.Close()) }()
timestamp := time.Now()
diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go
index 38b361716b..91ae4400e3 100644
--- a/core/services/vrf/delegate_test.go
+++ b/core/services/vrf/delegate_test.go
@@ -78,10 +78,10 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv
btORM := bridges.NewORM(db, lggr, cfg.Database())
txm := txmmocks.NewMockEvmTxManager(t)
ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database())
+ jrm := job.NewORM(db, prm, btORM, ks, lggr, cfg.Database())
+ 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)
- jrm := job.NewORM(db, legacyChains, prm, btORM, ks, lggr, cfg.Database())
- t.Cleanup(func() { jrm.Close() })
pr := pipeline.NewRunner(prm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ks.Eth(), ks.VRF(), lggr, nil, nil)
require.NoError(t, ks.Unlock(testutils.Password))
k, err := ks.Eth().Create(testutils.FixtureChainID)
From 96567e127d72f3f58c7a3e75dfdd1a69a6c316d4 Mon Sep 17 00:00:00 2001
From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com>
Date: Thu, 2 Nov 2023 20:35:04 +0400
Subject: [PATCH 057/327] add sepolia-arbitrum to automation benchmark test
(#11149)
* add sepolia-arbitrum to automation benchmark test
* add back P2P.V2 Enabled
* fix switch case in DeployKeeperRegistry
---
.github/workflows/automation-benchmark-tests.yml | 1 +
integration-tests/benchmark/keeper_test.go | 11 +++++++++--
integration-tests/contracts/contract_deployer.go | 14 ++++++++++----
3 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index 5c4dced934..d78e5e76ac 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -25,6 +25,7 @@ on:
- MUMBAI
- SEPOLIA
- BASE_GOERLI
+ - ARBITRUM_SEPOLIA
TestInputs:
description: TestInputs
required: false
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index 55f769e73b..25a147fbf0 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -37,6 +37,7 @@ Enabled = true
[P2P]
[P2P.V2]
+Enabled = true
AnnounceAddresses = ["0.0.0.0:6690"]
ListenAddresses = ["0.0.0.0:6690"]
[Keeper]
@@ -242,13 +243,13 @@ func repeatRegistries(registryVersion eth_contracts.KeeperRegistryVersion, numbe
var networkConfig = map[string]NetworkConfig{
"SimulatedGeth": {
- upkeepSLA: int64(20),
+ upkeepSLA: int64(120), //2 minutes
blockTime: time.Second,
deltaStage: 30 * time.Second,
funding: big.NewFloat(100_000),
},
"geth": {
- upkeepSLA: int64(20),
+ upkeepSLA: int64(120), //2 minutes
blockTime: time.Second,
deltaStage: 30 * time.Second,
funding: big.NewFloat(100_000),
@@ -289,6 +290,12 @@ var networkConfig = map[string]NetworkConfig{
deltaStage: 20 * time.Second,
funding: big.NewFloat(ChainlinkNodeFunding),
},
+ "ArbitrumSepolia": {
+ upkeepSLA: int64(120),
+ blockTime: time.Second,
+ deltaStage: 20 * time.Second,
+ funding: big.NewFloat(ChainlinkNodeFunding),
+ },
}
func getEnv(key, fallback string) string {
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index 94f6c73386..e203d8318f 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -876,14 +876,20 @@ func (e *EthereumContractDeployer) DeployKeeperRegistry(
opts *KeeperRegistryOpts,
) (KeeperRegistry, error) {
var mode uint8
- switch e.client.GetChainID() {
+ switch e.client.GetChainID().Int64() {
//Arbitrum payment model
- case big.NewInt(421613):
+ //Goerli Arbitrum
+ case 421613:
+ mode = uint8(1)
+ //Sepolia Arbitrum
+ case 421614:
mode = uint8(1)
//Optimism payment model
- case big.NewInt(420):
+ //Goerli Optimism
+ case 420:
mode = uint8(2)
- case big.NewInt(84531):
+ //Goerli Base
+ case 84531:
mode = uint8(2)
default:
mode = uint8(0)
From 388b267e1776262008a3488b656620f1f776742c Mon Sep 17 00:00:00 2001
From: Ryan Hall
Date: Thu, 2 Nov 2023 13:20:09 -0400
Subject: [PATCH 058/327] debug script improvements (#11152)
---
core/scripts/chaincli/handler/debug.go | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go
index 7cf801d332..daf012ee16 100644
--- a/core/scripts/chaincli/handler/debug.go
+++ b/core/scripts/chaincli/handler/debug.go
@@ -275,13 +275,21 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
if err != nil {
failUnknown("failed to execute mercury callback ", err)
}
+ if callbackResult.UpkeepFailureReason != 0 {
+ message(fmt.Sprintf("checkCallback failed with UpkeepFailureReason %d", checkResult.UpkeepFailureReason))
+ }
upkeepNeeded, performData = callbackResult.UpkeepNeeded, callbackResult.PerformData
- // do tenderly simulation
+ // do tenderly simulations
rawCall, err := core.RegistryABI.Pack("checkCallback", upkeepID, values, streamsLookup.extraData)
if err != nil {
- failUnknown("failed to pack raw checkUpkeep call", err)
+ failUnknown("failed to pack raw checkCallback call", err)
}
addLink("checkCallback simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, registryAddress))
+ rawCall, err = core.StreamsCompatibleABI.Pack("checkCallback", values, streamsLookup.extraData)
+ if err != nil {
+ failUnknown("failed to pack raw checkCallback (direct) call", err)
+ }
+ addLink("checkCallback (direct) simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, upkeepInfo.Target))
} else {
message("did not revert with StreamsLookup error")
}
From 206fb8b3ab4dc96bb55788bc111abd54939ea040 Mon Sep 17 00:00:00 2001
From: chainchad <96362174+chainchad@users.noreply.github.com>
Date: Thu, 2 Nov 2023 13:36:28 -0400
Subject: [PATCH 059/327] Avoid rate limiting when pulling public docker hub
images (#11153)
---
.../build-sign-publish-chainlink/action.yml | 22 +++++++++++++++++++
.github/workflows/build-publish-develop.yml | 2 ++
.github/workflows/build-publish.yml | 12 +++++-----
.github/workflows/build.yml | 5 +++--
4 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml
index 55c682bc8d..fe4ef858f5 100644
--- a/.github/actions/build-sign-publish-chainlink/action.yml
+++ b/.github/actions/build-sign-publish-chainlink/action.yml
@@ -13,6 +13,12 @@ inputs:
description: Path to the Dockerfile (relative to the repo root)
default: core/chainlink.Dockerfile
required: false
+ dockerhub_username:
+ description: Username for Docker Hub to avoid rate limits when pulling public images
+ required: false
+ dockerhub_password:
+ description: Password for Docker Hub to avoid rate limits when pulling public images
+ required: false
ecr-hostname:
description: The ECR registry scope
default: public.ecr.aws
@@ -126,6 +132,14 @@ runs:
type=semver,pattern={{version}},suffix=${{ inputs.ecr-tag-suffix }}-root
type=sha,format=short,suffix=${{ inputs.ecr-tag-suffix }}-root
+ # To avoid rate limiting from Docker Hub, we login with a paid user account.
+ - name: Login to Docker Hub
+ if: inputs.dockerhub_username && inputs.dockerhub_password
+ uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
+ with:
+ username: ${{ inputs.dockerhub_username }}
+ password: ${{ inputs.dockerhub_password }}
+
- name: Build and push root docker image
id: buildpush-root
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
@@ -159,6 +173,14 @@ runs:
images: ${{ env.shared-images }}
tags: ${{ env.shared-tag-list }}
+ # To avoid rate limiting from Docker Hub, we login with a paid user account.
+ - name: Login to Docker Hub
+ if: inputs.dockerhub_username && inputs.dockerhub_password
+ uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
+ with:
+ username: ${{ inputs.dockerhub_username }}
+ password: ${{ inputs.dockerhub_password }}
+
- name: Build and push non-root docker image
id: buildpush-nonroot
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
diff --git a/.github/workflows/build-publish-develop.yml b/.github/workflows/build-publish-develop.yml
index 076fdf817d..b885972237 100644
--- a/.github/workflows/build-publish-develop.yml
+++ b/.github/workflows/build-publish-develop.yml
@@ -52,6 +52,8 @@ jobs:
ecr-image-name: chainlink
ecr-tag-suffix: ${{ matrix.image.tag-suffix }}
dockerfile: ${{ matrix.image.dockerfile }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
git-commit-sha: ${{ steps.git-ref.outputs.checked-out || github.sha }}
- name: Collect Metrics
if: always()
diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml
index 4d5a42a369..1bda6957a2 100644
--- a/.github/workflows/build-publish.yml
+++ b/.github/workflows/build-publish.yml
@@ -1,17 +1,17 @@
-name: 'Build Chainlink and Publish'
+name: "Build Chainlink and Publish"
on:
# Mimics old circleci behaviour
push:
tags:
- - 'v*'
+ - "v*"
branches:
- master
- - 'release/**'
+ - "release/**"
jobs:
checks:
- name: 'Checks'
+ name: "Checks"
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
@@ -42,10 +42,12 @@ jobs:
aws-role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }}
aws-region: ${{ secrets.AWS_REGION }}
sign-images: true
- sign-method: 'keypair'
+ sign-method: "keypair"
cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }}
cosign-public-key: ${{ secrets.COSIGN_PUBLIC_KEY }}
cosign-password: ${{ secrets.COSIGN_PASSWORD }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
verify-signature: true
- name: Collect Metrics
if: always()
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0f9a8ea8b3..6282e2168d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,4 +1,4 @@
-name: 'Build Chainlink'
+name: "Build Chainlink"
on:
pull_request:
@@ -7,7 +7,6 @@ on:
- master
jobs:
-
build-chainlink:
runs-on: ubuntu-20.04
steps:
@@ -17,6 +16,8 @@ jobs:
- name: Build chainlink image
uses: ./.github/actions/build-sign-publish-chainlink
with:
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
publish: false
sign-images: false
- name: Collect Metrics
From a9d27aa2ccdebcb8b79af9ddf4d42d7f1fab6d9e Mon Sep 17 00:00:00 2001
From: David Cauchi <13139524+davidcauchi@users.noreply.github.com>
Date: Thu, 2 Nov 2023 19:40:47 +0100
Subject: [PATCH 060/327] Remove duplicate table (#11151)
---
integration-tests/config/config.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/integration-tests/config/config.go b/integration-tests/config/config.go
index 44c108b0d7..1da8254e0e 100644
--- a/integration-tests/config/config.go
+++ b/integration-tests/config/config.go
@@ -8,7 +8,6 @@ Enabled = true
[P2P.V2]
Enabled = false
-[P2P]
[P2P.V1]
Enabled = true
ListenIP = '0.0.0.0'
From 618d06b3adf412ad5e3eea2fab39177ed8505c15 Mon Sep 17 00:00:00 2001
From: Tate
Date: Thu, 2 Nov 2023 13:42:06 -0600
Subject: [PATCH 061/327] [TT-668] E2E Dockerhub Login Rate Limit Issue Fix
(#11155)
---
.../workflows/automation-benchmark-tests.yml | 2 +-
.../workflows/automation-ondemand-tests.yml | 2 +-
.github/workflows/integration-chaos-tests.yml | 2 +-
.github/workflows/integration-tests.yml | 28 ++++++++++++-------
.github/workflows/on-demand-ocr-soak-test.yml | 2 +-
.../on-demand-vrfv2plus-performance-test.yml | 2 +-
.github/workflows/performance-tests.yml | 2 +-
7 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index d78e5e76ac..7bdb66c919 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -109,7 +109,7 @@ jobs:
QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
DETACH_RUNNER: true
TEST_SUITE: benchmark
diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml
index fb8adcfdb6..88c2c126dc 100644
--- a/.github/workflows/automation-ondemand-tests.yml
+++ b/.github/workflows/automation-ondemand-tests.yml
@@ -172,7 +172,7 @@ jobs:
echo "version=${{ inputs.chainlinkVersionUpdate }}" >>$GITHUB_OUTPUT
fi
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
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 }}
diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml
index 4ad985e915..892a43e76f 100644
--- a/.github/workflows/integration-chaos-tests.yml
+++ b/.github/workflows/integration-chaos-tests.yml
@@ -109,7 +109,7 @@ jobs:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 ./chaos 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index b66ab58d55..445a027731 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -212,7 +212,7 @@ jobs:
## Run this step when changes that require tests to be run are made
- name: Run Tests
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725
PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }}
@@ -223,6 +223,8 @@ jobs:
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
artifacts_location: ./integration-tests/smoke/logs/
publish_check_name: ${{ matrix.product.name }}
token: ${{ secrets.GITHUB_TOKEN }}
@@ -231,7 +233,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: ""
- name: Collect Metrics
if: always()
id: collect-gha-metrics
@@ -411,7 +413,7 @@ jobs:
## Run this step when changes that require tests to be run are made
- name: Run Tests
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725
PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }}
@@ -422,6 +424,8 @@ jobs:
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}${{ matrix.product.tag_suffix }}
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
artifacts_name: ${{ matrix.product.name }}-test-logs
artifacts_location: ./integration-tests/smoke/logs/
publish_check_name: ${{ matrix.product.name }}
@@ -431,11 +435,11 @@ 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: ""
## Run this step when changes that do not need the test to run are made
- name: Run Setup
if: needs.changes.outputs.src == 'false'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
test_download_vendor_packages_command: cd ./integration-tests && go mod download
go_mod_path: ./integration-tests/go.mod
@@ -572,7 +576,7 @@ jobs:
run: |
echo "Running migration tests from version '${{ steps.get_latest_version.outputs.latest_version }}' to: '${{ github.sha }}'"
- name: Run Migration Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
@@ -817,12 +821,14 @@ jobs:
ref: ${{ needs.get_solana_sha.outputs.sha }}
- name: Run Setup
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
go_mod_path: ./integration-tests/go.mod
cache_restore_only: true
cache_key_id: core-solana-e2e-${{ env.MOD_CACHE_VERSION }}
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
@@ -844,7 +850,7 @@ jobs:
docker rm "$CONTAINER_ID"
- name: Run Tests
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
test_command_to_run: export ENV_JOB_IMAGE=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} && make test_smoke
cl_repo: ${{ env.CHAINLINK_IMAGE }}
@@ -857,7 +863,7 @@ jobs:
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
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: ""
run_setup: false
- name: Upload test log
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
@@ -929,7 +935,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
## Only run OCR smoke test for now
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
PYROSCOPE_ENVIRONMENT: ci-smoke-ocr-evm-${{ matrix.testnet }} # TODO: Only for OCR for now
@@ -940,6 +946,8 @@ jobs:
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
artifacts_location: ./integration-tests/smoke/logs
publish_check_name: ${{ matrix.testnet }} OCR Smoke Test Results
token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index 1fb79d8ccd..4a18aabf22 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -129,7 +129,7 @@ jobs:
QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
DETACH_RUNNER: true
TEST_SUITE: soak
diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
index deb977e43f..c51f7f5a2f 100644
--- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml
+++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
@@ -118,7 +118,7 @@ jobs:
with:
fetch-depth: 0
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
test_command_to_run: cd ./integration-tests && go test -v -count=1 -timeout 6h -run TestVRFV2PlusPerformance/vrfv2plus_performance_test ./load/vrfv2plus
test_download_vendor_packages_command: cd ./integration-tests && go mod download
diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml
index 87fb75beca..57907fe6c2 100644
--- a/.github/workflows/performance-tests.yml
+++ b/.github/workflows/performance-tests.yml
@@ -57,7 +57,7 @@ jobs:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
with:
test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 10 ./performance 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: make gomod
From 1208fb3d3dec36876dfd74a9a05db437840ce9fc Mon Sep 17 00:00:00 2001
From: amit-momin <108959691+amit-momin@users.noreply.github.com>
Date: Thu, 2 Nov 2023 16:05:10 -0500
Subject: [PATCH 062/327] Remove direct TXM DB reads from VRF (#10987)
* Removed direct TXM DB reads from VRF
* Addressed PR feedback
* Added tx deduping to vrf respCount method
* Fixed linting
* Fixed failing test
---------
Co-authored-by: Prashant Yadav <34992934+prashantkumar1982@users.noreply.github.com>
---
common/txmgr/mocks/tx_manager.go | 104 ++++++
common/txmgr/txmgr.go | 40 +++
common/txmgr/types/mocks/tx_store.go | 105 ++++++
common/txmgr/types/tx_store.go | 8 +
.../evm/client/simulated_backend_client.go | 3 +-
core/chains/evm/txmgr/evm_tx_store.go | 79 ++++-
core/chains/evm/txmgr/mocks/evm_tx_store.go | 104 ++++++
core/chains/evm/txmgr/test_helpers.go | 151 ++++++++
core/chains/evm/txmgr/txmgr_test.go | 177 ++--------
core/services/vrf/delegate.go | 137 +-------
core/services/vrf/delegate_test.go | 36 +-
core/services/vrf/v1/listener_v1.go | 103 ++++--
.../vrf/v2/integration_helpers_test.go | 28 +-
.../vrf/v2/integration_v2_plus_test.go | 2 +-
core/services/vrf/v2/integration_v2_test.go | 169 ++++-----
core/services/vrf/v2/listener_v2.go | 222 +++++++-----
.../vrf/v2/listener_v2_helpers_test.go | 22 ++
core/services/vrf/v2/listener_v2_test.go | 329 +++++++++++-------
core/services/vrf/v2/listener_v2_types.go | 6 +-
core/services/vrf/vrfcommon/utils.go | 78 +++++
core/web/jobs_controller_test.go | 14 +-
21 files changed, 1265 insertions(+), 652 deletions(-)
create mode 100644 core/chains/evm/txmgr/test_helpers.go
create mode 100644 core/services/vrf/vrfcommon/utils.go
diff --git a/common/txmgr/mocks/tx_manager.go b/common/txmgr/mocks/tx_manager.go
index c01f182c9b..89abf1dea5 100644
--- a/common/txmgr/mocks/tx_manager.go
+++ b/common/txmgr/mocks/tx_manager.go
@@ -59,6 +59,110 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Create
return r0, r1
}
+// FindTxesByMetaFieldAndStates provides a mock function with given fields: ctx, metaField, metaValue, states, chainID
+func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, metaField, metaValue, states, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, metaField, metaValue, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, metaField, metaValue, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, string, []txmgrtypes.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, metaValue, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID
+func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, ids, states, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, ids, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, ids, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, ids, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithMetaFieldByReceiptBlockNum provides a mock function with given fields: ctx, metaField, blockNum, chainID
+func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, metaField, blockNum, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, metaField, blockNum, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, metaField, blockNum, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, int64, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, blockNum, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithMetaFieldByStates provides a mock function with given fields: ctx, metaField, states, chainID
+func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, metaField, states, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, metaField, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, metaField, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, []txmgrtypes.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// GetForwarderForEOA provides a mock function with given fields: eoa
func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetForwarderForEOA(eoa ADDR) (ADDR, error) {
ret := _m.Called(eoa)
diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go
index d80f534ad2..5b7afd3224 100644
--- a/common/txmgr/txmgr.go
+++ b/common/txmgr/txmgr.go
@@ -47,6 +47,14 @@ type TxManager[
RegisterResumeCallback(fn ResumeCallback)
SendNativeToken(ctx context.Context, chainID CHAIN_ID, from, to ADDR, value big.Int, gasLimit uint32) (etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
Reset(addr ADDR, abandon bool) error
+ // Find transactions by a field in the TxMeta blob and transaction states
+ FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
+ // Find transactions with a non-null TxMeta field that was provided by transaction states
+ FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
+ // Find transactions with a non-null TxMeta field that was provided and a receipt block number greater than or equal to the one provided
+ FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
+ // Find transactions loaded with transaction attempts and receipts by transaction IDs and states
+ FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
}
type reset struct {
@@ -530,6 +538,26 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SendNative
return etx, nil
}
+func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ txes, err = b.txStore.FindTxesByMetaFieldAndStates(ctx, metaField, metaValue, states, chainID)
+ return
+}
+
+func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ txes, err = b.txStore.FindTxesWithMetaFieldByStates(ctx, metaField, states, chainID)
+ return
+}
+
+func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ txes, err = b.txStore.FindTxesWithMetaFieldByReceiptBlockNum(ctx, metaField, blockNum, chainID)
+ return
+}
+
+func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ txes, err = b.txStore.FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx, ids, states, chainID)
+ return
+}
+
type NullTxManager[
CHAIN_ID types.ID,
HEAD types.Head[BLOCK_HASH],
@@ -584,3 +612,15 @@ func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Hea
}
func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RegisterResumeCallback(fn ResumeCallback) {
}
+func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ return txes, errors.New(n.ErrMsg)
+}
+func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ return txes, errors.New(n.ErrMsg)
+}
+func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ return txes, errors.New(n.ErrMsg)
+}
+func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) {
+ return txes, errors.New(n.ErrMsg)
+}
diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go
index 02388e40f4..7da51de606 100644
--- a/common/txmgr/types/mocks/tx_store.go
+++ b/common/txmgr/types/mocks/tx_store.go
@@ -4,6 +4,7 @@ package mocks
import (
context "context"
+ big "math/big"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
mock "github.com/stretchr/testify/mock"
@@ -361,6 +362,110 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxWithS
return r0, r1
}
+// FindTxesByMetaFieldAndStates provides a mock function with given fields: ctx, metaField, metaValue, states, chainID
+func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, metaField, metaValue, states, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, metaField, metaValue, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, metaField, metaValue, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, string, []txmgrtypes.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, metaValue, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID
+func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, ids, states, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, ids, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, ids, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, ids, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithMetaFieldByReceiptBlockNum provides a mock function with given fields: ctx, metaField, blockNum, chainID
+func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, metaField, blockNum, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, metaField, blockNum, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, metaField, blockNum, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, int64, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, blockNum, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithMetaFieldByStates provides a mock function with given fields: ctx, metaField, states, chainID
+func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
+ ret := _m.Called(ctx, metaField, states, chainID)
+
+ var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok {
+ return rf(ctx, metaField, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok {
+ r0 = rf(ctx, metaField, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, []txmgrtypes.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// FindTxsRequiringGasBump provides a mock function with given fields: ctx, address, blockNum, gasBumpThreshold, depth, chainID
func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxsRequiringGasBump(ctx context.Context, address ADDR, blockNum int64, gasBumpThreshold int64, depth int64, chainID CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
ret := _m.Called(ctx, address, blockNum, gasBumpThreshold, depth, chainID)
diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go
index 059a87d7ab..83cb4b85ee 100644
--- a/common/txmgr/types/tx_store.go
+++ b/common/txmgr/types/tx_store.go
@@ -43,6 +43,14 @@ type TxStore[
CheckTxQueueCapacity(ctx context.Context, fromAddress ADDR, maxQueuedTransactions uint64, chainID CHAIN_ID) (err error)
Close()
Abandon(ctx context.Context, id CHAIN_ID, addr ADDR) error
+ // Find transactions by a field in the TxMeta blob and transaction states
+ FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []TxState, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
+ // Find transactions with a non-null TxMeta field that was provided by transaction states
+ FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []TxState, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
+ // Find transactions with a non-null TxMeta field that was provided and a receipt block number greater than or equal to the one provided
+ FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
+ // Find transactions loaded with transaction attempts and receipts by transaction IDs and states
+ FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []TxState, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error)
}
// TransactionStore contains the persistence layer methods needed to manage Txs and TxAttempts
diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go
index abab204662..cde536bc7b 100644
--- a/core/chains/evm/client/simulated_backend_client.go
+++ b/core/chains/evm/client/simulated_backend_client.go
@@ -318,7 +318,8 @@ func (c *SimulatedBackendClient) BlockByHash(ctx context.Context, hash common.Ha
}
func (c *SimulatedBackendClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) {
- panic("not implemented")
+ header, err := c.b.HeaderByNumber(ctx, nil)
+ return header.Number, err
}
// ChainID returns the ethereum ChainID.
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 86a06b6025..971103bdfd 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -184,6 +184,7 @@ type DbEthTx struct {
func (db *DbEthTx) FromTx(tx *Tx) {
db.ID = tx.ID
+ db.IdempotencyKey = tx.IdempotencyKey
db.FromAddress = tx.FromAddress
db.ToAddress = tx.ToAddress
db.EncodedPayload = tx.EncodedPayload
@@ -511,8 +512,8 @@ func (o *evmTxStore) InsertTx(etx *Tx) error {
if etx.CreatedAt == (time.Time{}) {
etx.CreatedAt = time.Now()
}
- const insertEthTxSQL = `INSERT INTO evm.txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, error, broadcast_at, initial_broadcast_at, created_at, state, meta, subject, pipeline_task_run_id, min_confirmations, evm_chain_id, transmit_checker) VALUES (
-:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit, :error, :broadcast_at, :initial_broadcast_at, :created_at, :state, :meta, :subject, :pipeline_task_run_id, :min_confirmations, :evm_chain_id, :transmit_checker
+ const insertEthTxSQL = `INSERT INTO evm.txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, error, broadcast_at, initial_broadcast_at, created_at, state, meta, subject, pipeline_task_run_id, min_confirmations, evm_chain_id, transmit_checker, idempotency_key) VALUES (
+:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit, :error, :broadcast_at, :initial_broadcast_at, :created_at, :state, :meta, :subject, :pipeline_task_run_id, :min_confirmations, :evm_chain_id, :transmit_checker, :idempotency_key
) RETURNING *`
var dbTx DbEthTx
dbTx.FromTx(etx)
@@ -548,14 +549,14 @@ func (o *evmTxStore) FindTxWithAttempts(etxID int64) (etx Tx, err error) {
err = o.q.Transaction(func(tx pg.Queryer) error {
var dbEtx DbEthTx
if err = tx.Get(&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 eth_tx with id %d", etxID)
+ return pkgerrors.Wrapf(err, "failed to find evm.tx with id %d", etxID)
}
dbEtx.ToTx(&etx)
if err = o.loadTxAttemptsAtomic(&etx, pg.WithQueryer(tx)); err != nil {
- return pkgerrors.Wrapf(err, "failed to load evm.tx_attempts for eth_tx with id %d", etxID)
+ return pkgerrors.Wrapf(err, "failed to load evm.tx_attempts for evm.tx with id %d", etxID)
}
if err = loadEthTxAttemptsReceipts(tx, &etx); err != nil {
- return pkgerrors.Wrapf(err, "failed to load evm.receipts for eth_tx with id %d", etxID)
+ return pkgerrors.Wrapf(err, "failed to load evm.receipts for evm.tx with id %d", etxID)
}
return nil
}, pg.OptReadOnlyTx())
@@ -637,6 +638,8 @@ func loadEthTxesAttemptsReceipts(q pg.Queryer, etxs []*Tx) (err error) {
for _, receipt := range receipts {
attempt := attemptHashM[receipt.TxHash]
+ // Although the attempts struct supports multiple receipts, the expectation for EVM is that there is only one receipt
+ // per tx and therefore attempt too.
attempt.Receipts = append(attempt.Receipts, receipt)
}
return nil
@@ -1776,6 +1779,72 @@ func (o *evmTxStore) Abandon(ctx context.Context, chainID *big.Int, addr common.
return err
}
+// Find transactions by a field in the TxMeta blob and transaction states
+func (o *evmTxStore) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) ([]*Tx, error) {
+ var cancel context.CancelFunc
+ ctx, cancel = o.mergeContexts(ctx)
+ defer cancel()
+ qq := o.q.WithOpts(pg.WithParentCtx(ctx))
+ var dbEtxs []DbEthTx
+ sql := fmt.Sprintf("SELECT * FROM evm.txes WHERE evm_chain_id = $1 AND meta->>'%s' = $2 AND state = ANY($3)", metaField)
+ err := qq.Select(&dbEtxs, sql, chainID.String(), metaValue, pq.Array(states))
+ txes := make([]*Tx, len(dbEtxs))
+ dbEthTxsToEvmEthTxPtrs(dbEtxs, txes)
+ return txes, pkgerrors.Wrap(err, "failed to FindTxesByMetaFieldAndStates")
+}
+
+// Find transactions with a non-null TxMeta field that was provided by transaction states
+func (o *evmTxStore) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) (txes []*Tx, err error) {
+ var cancel context.CancelFunc
+ ctx, cancel = o.mergeContexts(ctx)
+ defer cancel()
+ qq := o.q.WithOpts(pg.WithParentCtx(ctx))
+ var dbEtxs []DbEthTx
+ sql := fmt.Sprintf("SELECT * FROM evm.txes WHERE meta->'%s' IS NOT NULL AND state = ANY($1) AND evm_chain_id = $2", metaField)
+ err = qq.Select(&dbEtxs, sql, pq.Array(states), chainID.String())
+ txes = make([]*Tx, len(dbEtxs))
+ dbEthTxsToEvmEthTxPtrs(dbEtxs, txes)
+ return txes, pkgerrors.Wrap(err, "failed to FindTxesWithMetaFieldByStates")
+}
+
+// Find transactions with a non-null TxMeta field that was provided and a receipt block number greater than or equal to the one provided
+func (o *evmTxStore) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txes []*Tx, err error) {
+ var cancel context.CancelFunc
+ ctx, cancel = o.mergeContexts(ctx)
+ defer cancel()
+ qq := o.q.WithOpts(pg.WithParentCtx(ctx))
+ var dbEtxs []DbEthTx
+ sql := fmt.Sprintf("SELECT et.* FROM evm.txes et JOIN evm.tx_attempts eta on et.id = eta.eth_tx_id JOIN evm.receipts er on eta.hash = er.tx_hash WHERE et.meta->'%s' IS NOT NULL AND er.block_number >= $1 AND et.evm_chain_id = $2", metaField)
+ err = qq.Select(&dbEtxs, sql, blockNum, chainID.String())
+ txes = make([]*Tx, len(dbEtxs))
+ dbEthTxsToEvmEthTxPtrs(dbEtxs, txes)
+ return txes, pkgerrors.Wrap(err, "failed to FindTxesWithMetaFieldByReceiptBlockNum")
+}
+
+// Find transactions loaded with transaction attempts and receipts by transaction IDs and states
+func (o *evmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*Tx, err error) {
+ var cancel context.CancelFunc
+ ctx, cancel = o.mergeContexts(ctx)
+ defer cancel()
+ qq := o.q.WithOpts(pg.WithParentCtx(ctx))
+ err = qq.Transaction(func(tx pg.Queryer) error {
+ var dbEtxs []DbEthTx
+ if err = tx.Select(&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")
+ }
+ txes = make([]*Tx, len(dbEtxs))
+ dbEthTxsToEvmEthTxPtrs(dbEtxs, txes)
+ if err = o.LoadTxesAttempts(txes, pg.WithQueryer(tx)); err != nil {
+ return pkgerrors.Wrapf(err, "failed to load evm.tx_attempts for evm.tx")
+ }
+ if err = loadEthTxesAttemptsReceipts(tx, txes); err != nil {
+ return pkgerrors.Wrapf(err, "failed to load evm.receipts for evm.tx")
+ }
+ return nil
+ })
+ return txes, pkgerrors.Wrap(err, "FindTxesWithAttemptsAndReceiptsByIdsAndState failed")
+}
+
// Returns a context that contains the values of the provided context,
// and which is canceled when either the provided contextg or TxStore parent context is canceled.
func (o *evmTxStore) mergeContexts(ctx context.Context) (context.Context, context.CancelFunc) {
diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go
index 69a0d257f7..4632a8ae34 100644
--- a/core/chains/evm/txmgr/mocks/evm_tx_store.go
+++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go
@@ -467,6 +467,110 @@ func (_m *EvmTxStore) FindTxWithSequence(ctx context.Context, fromAddress common
return r0, r1
}
+// FindTxesByMetaFieldAndStates provides a mock function with given fields: ctx, metaField, metaValue, states, chainID
+func (_m *EvmTxStore) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
+ ret := _m.Called(ctx, metaField, metaValue, states, chainID)
+
+ var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, []types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok {
+ return rf(ctx, metaField, metaValue, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, []types.TxState, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok {
+ r0 = rf(ctx, metaField, metaValue, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, string, []types.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, metaValue, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID
+func (_m *EvmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
+ ret := _m.Called(ctx, ids, states, chainID)
+
+ var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok {
+ return rf(ctx, ids, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []types.TxState, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok {
+ r0 = rf(ctx, ids, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, []big.Int, []types.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, ids, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithMetaFieldByReceiptBlockNum provides a mock function with given fields: ctx, metaField, blockNum, chainID
+func (_m *EvmTxStore) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
+ ret := _m.Called(ctx, metaField, blockNum, chainID)
+
+ var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok {
+ return rf(ctx, metaField, blockNum, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok {
+ r0 = rf(ctx, metaField, blockNum, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, int64, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, blockNum, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindTxesWithMetaFieldByStates provides a mock function with given fields: ctx, metaField, states, chainID
+func (_m *EvmTxStore) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
+ ret := _m.Called(ctx, metaField, states, chainID)
+
+ var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, []types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok {
+ return rf(ctx, metaField, states, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, []types.TxState, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok {
+ r0 = rf(ctx, metaField, states, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, []types.TxState, *big.Int) error); ok {
+ r1 = rf(ctx, metaField, states, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// FindTxsRequiringGasBump provides a mock function with given fields: ctx, address, blockNum, gasBumpThreshold, depth, chainID
func (_m *EvmTxStore) FindTxsRequiringGasBump(ctx context.Context, address common.Address, blockNum int64, gasBumpThreshold int64, depth int64, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
ret := _m.Called(ctx, address, blockNum, gasBumpThreshold, depth, chainID)
diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go
new file mode 100644
index 0000000000..f9c0423a62
--- /dev/null
+++ b/core/chains/evm/txmgr/test_helpers.go
@@ -0,0 +1,151 @@
+package txmgr
+
+import (
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg"
+
+ evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
+)
+
+func ptr[T any](t T) *T { return &t }
+
+type TestDatabaseConfig struct {
+ config.Database
+ defaultQueryTimeout time.Duration
+}
+
+func (d *TestDatabaseConfig) DefaultQueryTimeout() time.Duration {
+ return d.defaultQueryTimeout
+}
+
+func (d *TestDatabaseConfig) LogSQL() bool {
+ return false
+}
+
+type TestListenerConfig struct {
+ config.Listener
+}
+
+func (l *TestListenerConfig) FallbackPollInterval() time.Duration {
+ return 1 * time.Minute
+}
+
+func (d *TestDatabaseConfig) Listener() config.Listener {
+ return &TestListenerConfig{}
+}
+
+type TestEvmConfig struct {
+ evmconfig.EVM
+ MaxInFlight uint32
+ ReaperInterval time.Duration
+ ReaperThreshold time.Duration
+ ResendAfterThreshold time.Duration
+ BumpThreshold uint64
+ MaxQueued uint64
+}
+
+func (e *TestEvmConfig) Transactions() evmconfig.Transactions {
+ return &transactionsConfig{e: e}
+}
+
+func (e *TestEvmConfig) NonceAutoSync() bool { return true }
+
+func (e *TestEvmConfig) FinalityDepth() uint32 { return 42 }
+
+type TestGasEstimatorConfig struct {
+ bumpThreshold uint64
+}
+
+func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory {
+ return &TestBlockHistoryConfig{}
+}
+
+func (g *TestGasEstimatorConfig) EIP1559DynamicFees() bool { return false }
+func (g *TestGasEstimatorConfig) LimitDefault() uint32 { return 42 }
+func (g *TestGasEstimatorConfig) BumpPercent() uint16 { return 42 }
+func (g *TestGasEstimatorConfig) BumpThreshold() uint64 { return g.bumpThreshold }
+func (g *TestGasEstimatorConfig) BumpMin() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) FeeCapDefault() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) PriceDefault() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) TipCapDefault() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) TipCapMin() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) LimitMax() uint32 { return 0 }
+func (g *TestGasEstimatorConfig) LimitMultiplier() float32 { return 0 }
+func (g *TestGasEstimatorConfig) BumpTxDepth() uint32 { return 42 }
+func (g *TestGasEstimatorConfig) LimitTransfer() uint32 { return 42 }
+func (g *TestGasEstimatorConfig) PriceMax() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) PriceMin() *assets.Wei { return assets.NewWeiI(42) }
+func (g *TestGasEstimatorConfig) Mode() string { return "FixedPrice" }
+func (g *TestGasEstimatorConfig) LimitJobType() evmconfig.LimitJobType {
+ return &TestLimitJobTypeConfig{}
+}
+func (g *TestGasEstimatorConfig) PriceMaxKey(addr common.Address) *assets.Wei {
+ return assets.NewWeiI(42)
+}
+
+func (e *TestEvmConfig) GasEstimator() evmconfig.GasEstimator {
+ return &TestGasEstimatorConfig{bumpThreshold: e.BumpThreshold}
+}
+
+type TestLimitJobTypeConfig struct {
+}
+
+func (l *TestLimitJobTypeConfig) OCR() *uint32 { return ptr(uint32(0)) }
+func (l *TestLimitJobTypeConfig) OCR2() *uint32 { return ptr(uint32(0)) }
+func (l *TestLimitJobTypeConfig) DR() *uint32 { return ptr(uint32(0)) }
+func (l *TestLimitJobTypeConfig) FM() *uint32 { return ptr(uint32(0)) }
+func (l *TestLimitJobTypeConfig) Keeper() *uint32 { return ptr(uint32(0)) }
+func (l *TestLimitJobTypeConfig) VRF() *uint32 { return ptr(uint32(0)) }
+
+type TestBlockHistoryConfig struct {
+ evmconfig.BlockHistory
+}
+
+func (b *TestBlockHistoryConfig) BatchSize() uint32 { return 42 }
+func (b *TestBlockHistoryConfig) BlockDelay() uint16 { return 42 }
+func (b *TestBlockHistoryConfig) BlockHistorySize() uint16 { return 42 }
+func (b *TestBlockHistoryConfig) EIP1559FeeCapBufferBlocks() uint16 { return 42 }
+func (b *TestBlockHistoryConfig) TransactionPercentile() uint16 { return 42 }
+
+type transactionsConfig struct {
+ evmconfig.Transactions
+ e *TestEvmConfig
+}
+
+func (*transactionsConfig) ForwardersEnabled() bool { return true }
+func (t *transactionsConfig) MaxInFlight() uint32 { return t.e.MaxInFlight }
+func (t *transactionsConfig) MaxQueued() uint64 { return t.e.MaxQueued }
+func (t *transactionsConfig) ReaperInterval() time.Duration { return t.e.ReaperInterval }
+func (t *transactionsConfig) ReaperThreshold() time.Duration { return t.e.ReaperThreshold }
+func (t *transactionsConfig) ResendAfterThreshold() time.Duration { return t.e.ResendAfterThreshold }
+
+type MockConfig struct {
+ EvmConfig *TestEvmConfig
+ RpcDefaultBatchSize uint32
+ finalityDepth uint32
+ finalityTagEnabled bool
+}
+
+func (c *MockConfig) EVM() evmconfig.EVM {
+ return c.EvmConfig
+}
+
+func (c *MockConfig) NonceAutoSync() bool { return true }
+func (c *MockConfig) ChainType() config.ChainType { return "" }
+func (c *MockConfig) FinalityDepth() uint32 { return c.finalityDepth }
+func (c *MockConfig) SetFinalityDepth(fd uint32) { c.finalityDepth = fd }
+func (c *MockConfig) FinalityTagEnabled() bool { return c.finalityTagEnabled }
+func (c *MockConfig) RPCDefaultBatchSize() uint32 { return c.RpcDefaultBatchSize }
+
+func MakeTestConfigs(t *testing.T) (*MockConfig, *TestDatabaseConfig, *TestEvmConfig) {
+ db := &TestDatabaseConfig{defaultQueryTimeout: pg.DefaultQueryTimeout}
+ ec := &TestEvmConfig{BumpThreshold: 42, MaxInFlight: uint32(42), MaxQueued: uint64(0), ReaperInterval: time.Duration(0), ReaperThreshold: time.Duration(0)}
+ config := &MockConfig{EvmConfig: ec}
+ return config, db, ec
+}
diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go
index e9823ee021..4aa54bc52a 100644
--- a/core/chains/evm/txmgr/txmgr_test.go
+++ b/core/chains/evm/txmgr/txmgr_test.go
@@ -8,7 +8,6 @@ import (
"testing"
"time"
- "github.com/ethereum/go-ethereum/common"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/google/uuid"
@@ -27,7 +26,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"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"
@@ -36,7 +34,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -76,7 +73,7 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) {
to := utils.ZeroAddress
value := assets.NewEth(1).ToInt()
- config, dbConfig, evmConfig := makeConfigs(t)
+ config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
keyStore := cltest.NewKeyStore(t, db, dbConfig).Eth()
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
@@ -102,7 +99,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
gasLimit := uint32(1000)
payload := []byte{1, 2, 3}
- config, dbConfig, evmConfig := makeConfigs(t)
+ config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
@@ -115,7 +112,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
strategy := newMockTxStrategy(t)
strategy.On("Subject").Return(uuid.NullUUID{UUID: subject, Valid: true})
strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(int64(0), nil)
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
FromAddress: fromAddress,
ToAddress: toAddress,
@@ -151,7 +148,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
cltest.MustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, fromAddress)
t.Run("with queue at capacity does not insert eth_tx", func(t *testing.T) {
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
_, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
FromAddress: fromAddress,
ToAddress: testutils.NewAddress(),
@@ -165,7 +162,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
})
t.Run("doesn't insert eth_tx if a matching tx already exists for that pipeline_task_run_id", func(t *testing.T) {
- evmConfig.maxQueued = uint64(3)
+ evmConfig.MaxQueued = uint64(3)
id := uuid.New()
tx1, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
FromAddress: fromAddress,
@@ -221,7 +218,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
checker := txmgr.TransmitCheckerSpec{
CheckerType: txmgr.TransmitCheckerTypeSimulate,
}
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
FromAddress: fromAddress,
ToAddress: toAddress,
@@ -260,7 +257,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
SubID: &testDefaultSubID,
GlobalSubID: &testDefaultGlobalSubID,
}
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
checker := txmgr.TransmitCheckerSpec{
CheckerType: txmgr.TransmitCheckerTypeVRFV2,
VRFCoordinatorAddress: testutils.NewAddressPtr(),
@@ -292,7 +289,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
t.Run("forwards tx when a proper forwarder is set up", func(t *testing.T) {
pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
pgtest.MustExec(t, db, `DELETE FROM evm.forwarders`)
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
// Create mock forwarder, mock authorizedsenders call.
form := forwarders.NewORM(db, logger.TestLogger(t), cfg.Database())
@@ -322,7 +319,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
})
t.Run("insert Tx successfully with a IdempotencyKey", func(t *testing.T) {
- evmConfig.maxQueued = uint64(3)
+ evmConfig.MaxQueued = uint64(3)
id := uuid.New()
idempotencyKey := "1"
_, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
@@ -338,7 +335,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
})
t.Run("doesn't insert eth_tx if a matching tx already exists for that IdempotencyKey", func(t *testing.T) {
- evmConfig.maxQueued = uint64(3)
+ evmConfig.MaxQueued = uint64(3)
id := uuid.New()
idempotencyKey := "2"
tx1, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
@@ -371,138 +368,6 @@ func newMockTxStrategy(t *testing.T) *commontxmmocks.TxStrategy {
return commontxmmocks.NewTxStrategy(t)
}
-type databaseConfig struct {
- config.Database
- defaultQueryTimeout time.Duration
-}
-
-func (d *databaseConfig) DefaultQueryTimeout() time.Duration {
- return d.defaultQueryTimeout
-}
-
-func (d *databaseConfig) LogSQL() bool {
- return false
-}
-
-type listenerConfig struct {
- config.Listener
-}
-
-func (l *listenerConfig) FallbackPollInterval() time.Duration {
- return 1 * time.Minute
-}
-
-func (d *databaseConfig) Listener() config.Listener {
- return &listenerConfig{}
-}
-
-type evmConfig struct {
- evmconfig.EVM
- maxInFlight uint32
- reaperInterval time.Duration
- reaperThreshold time.Duration
- resendAfterThreshold time.Duration
- bumpThreshold uint64
- maxQueued uint64
-}
-
-func (e *evmConfig) Transactions() evmconfig.Transactions {
- return &transactionsConfig{e: e}
-}
-
-func (e *evmConfig) GasEstimator() evmconfig.GasEstimator {
- return &gasEstimatorConfig{bumpThreshold: e.bumpThreshold}
-}
-
-func (e *evmConfig) NonceAutoSync() bool { return true }
-
-func (e *evmConfig) FinalityDepth() uint32 { return 42 }
-
-type gasEstimatorConfig struct {
- bumpThreshold uint64
-}
-
-func (g *gasEstimatorConfig) BlockHistory() evmconfig.BlockHistory {
- return &blockHistoryConfig{}
-}
-
-func (g *gasEstimatorConfig) EIP1559DynamicFees() bool { return false }
-func (g *gasEstimatorConfig) LimitDefault() uint32 { return 42 }
-func (g *gasEstimatorConfig) BumpPercent() uint16 { return 42 }
-func (g *gasEstimatorConfig) BumpThreshold() uint64 { return g.bumpThreshold }
-func (g *gasEstimatorConfig) BumpMin() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) FeeCapDefault() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) PriceDefault() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) TipCapDefault() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) TipCapMin() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) LimitMax() uint32 { return 0 }
-func (g *gasEstimatorConfig) LimitMultiplier() float32 { return 0 }
-func (g *gasEstimatorConfig) BumpTxDepth() uint32 { return 42 }
-func (g *gasEstimatorConfig) LimitTransfer() uint32 { return 42 }
-func (g *gasEstimatorConfig) PriceMax() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) PriceMin() *assets.Wei { return assets.NewWeiI(42) }
-func (g *gasEstimatorConfig) Mode() string { return "FixedPrice" }
-func (g *gasEstimatorConfig) LimitJobType() evmconfig.LimitJobType { return &limitJobTypeConfig{} }
-func (g *gasEstimatorConfig) PriceMaxKey(addr common.Address) *assets.Wei {
- return assets.NewWeiI(42)
-}
-
-type limitJobTypeConfig struct {
-}
-
-func (l *limitJobTypeConfig) OCR() *uint32 { return ptr(uint32(0)) }
-func (l *limitJobTypeConfig) OCR2() *uint32 { return ptr(uint32(0)) }
-func (l *limitJobTypeConfig) DR() *uint32 { return ptr(uint32(0)) }
-func (l *limitJobTypeConfig) FM() *uint32 { return ptr(uint32(0)) }
-func (l *limitJobTypeConfig) Keeper() *uint32 { return ptr(uint32(0)) }
-func (l *limitJobTypeConfig) VRF() *uint32 { return ptr(uint32(0)) }
-
-type blockHistoryConfig struct {
- evmconfig.BlockHistory
-}
-
-func (b *blockHistoryConfig) BatchSize() uint32 { return 42 }
-func (b *blockHistoryConfig) BlockDelay() uint16 { return 42 }
-func (b *blockHistoryConfig) BlockHistorySize() uint16 { return 42 }
-func (b *blockHistoryConfig) EIP1559FeeCapBufferBlocks() uint16 { return 42 }
-func (b *blockHistoryConfig) TransactionPercentile() uint16 { return 42 }
-
-type transactionsConfig struct {
- evmconfig.Transactions
- e *evmConfig
-}
-
-func (*transactionsConfig) ForwardersEnabled() bool { return true }
-func (t *transactionsConfig) MaxInFlight() uint32 { return t.e.maxInFlight }
-func (t *transactionsConfig) MaxQueued() uint64 { return t.e.maxQueued }
-func (t *transactionsConfig) ReaperInterval() time.Duration { return t.e.reaperInterval }
-func (t *transactionsConfig) ReaperThreshold() time.Duration { return t.e.reaperThreshold }
-func (t *transactionsConfig) ResendAfterThreshold() time.Duration { return t.e.resendAfterThreshold }
-
-type mockConfig struct {
- evmConfig *evmConfig
- rpcDefaultBatchSize uint32
- finalityDepth uint32
- finalityTagEnabled bool
-}
-
-func (c *mockConfig) EVM() evmconfig.EVM {
- return c.evmConfig
-}
-
-func (c *mockConfig) NonceAutoSync() bool { return true }
-func (c *mockConfig) ChainType() config.ChainType { return "" }
-func (c *mockConfig) FinalityDepth() uint32 { return c.finalityDepth }
-func (c *mockConfig) FinalityTagEnabled() bool { return c.finalityTagEnabled }
-func (c *mockConfig) RPCDefaultBatchSize() uint32 { return c.rpcDefaultBatchSize }
-
-func makeConfigs(t *testing.T) (*mockConfig, *databaseConfig, *evmConfig) {
- db := &databaseConfig{defaultQueryTimeout: pg.DefaultQueryTimeout}
- ec := &evmConfig{bumpThreshold: 42, maxInFlight: uint32(42), maxQueued: uint64(0), reaperInterval: time.Duration(0), reaperThreshold: time.Duration(0)}
- config := &mockConfig{evmConfig: ec}
- return config, db, ec
-}
-
func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewGeneralConfig(t, nil)
@@ -517,7 +382,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
gasLimit := uint32(1000)
toAddress := testutils.NewAddress()
- config, dbConfig, evmConfig := makeConfigs(t)
+ config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator())
@@ -527,7 +392,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
t.Run("if another key has any transactions with insufficient eth errors, transmits as normal", func(t *testing.T) {
payload := cltest.MustRandomBytes(t, 100)
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
cltest.MustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, otherKey.Address)
strategy := newMockTxStrategy(t)
strategy.On("Subject").Return(uuid.NullUUID{})
@@ -550,7 +415,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
t.Run("if this key has any transactions with insufficient eth errors, inserts it anyway", func(t *testing.T) {
payload := cltest.MustRandomBytes(t, 100)
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
cltest.MustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, thisKey.Address)
strategy := newMockTxStrategy(t)
@@ -578,7 +443,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
strategy.On("Subject").Return(uuid.NullUUID{})
strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(int64(0), nil)
- evmConfig.maxQueued = uint64(1)
+ evmConfig.MaxQueued = uint64(1)
etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
FromAddress: evmFromAddress,
ToAddress: toAddress,
@@ -598,13 +463,13 @@ func TestTxm_Lifecycle(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
kst := ksmocks.NewEth(t)
- config, dbConfig, evmConfig := makeConfigs(t)
- config.finalityDepth = uint32(42)
- config.rpcDefaultBatchSize = uint32(4)
+ config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
+ config.SetFinalityDepth(uint32(42))
+ config.RpcDefaultBatchSize = uint32(4)
- evmConfig.resendAfterThreshold = 1 * time.Hour
- evmConfig.reaperThreshold = 1 * time.Hour
- evmConfig.reaperInterval = 1 * time.Hour
+ evmConfig.ResendAfterThreshold = 1 * time.Hour
+ evmConfig.ReaperThreshold = 1 * time.Hour
+ evmConfig.ReaperInterval = 1 * time.Hour
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return([]gethcommon.Address{}, nil)
@@ -619,7 +484,7 @@ func TestTxm_Lifecycle(t *testing.T) {
// It should not hang or panic
txm.OnNewLongestChain(testutils.Context(t), head)
- evmConfig.bumpThreshold = uint64(1)
+ evmConfig.BumpThreshold = uint64(1)
require.NoError(t, txm.Start(testutils.Context(t)))
diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go
index f6b6a460b8..558d48752d 100644
--- a/core/services/vrf/delegate.go
+++ b/core/services/vrf/delegate.go
@@ -1,10 +1,7 @@
package vrf
import (
- "encoding/hex"
"fmt"
- "math/big"
- "strings"
"time"
"github.com/avast/retry-go/v4"
@@ -87,7 +84,6 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
if err != nil {
return nil, err
}
- chainId := chain.Client().ConfiguredChainID()
coordinator, err := solidity_vrf_coordinator_interface.NewVRFCoordinator(jb.VRFSpec.CoordinatorAddress.Address(), chain.Client())
if err != nil {
return nil, err
@@ -168,23 +164,19 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
chain.Config().EVM(),
chain.Config().EVM().GasEstimator(),
lV2Plus,
- chain.Client(),
+ chain,
chain.ID(),
- chain.LogBroadcaster(),
d.q,
v2.NewCoordinatorV2_5(coordinatorV2Plus),
batchCoordinatorV2,
vrfOwner,
aggregator,
- chain.TxManager(),
d.pr,
d.ks.Eth(),
jb,
d.mailMon,
utils.NewHighCapacityMailbox[log.Broadcast](),
func() {},
- GetStartingResponseCountsV2(d.q, lV2Plus, chainId.Uint64(), chain.Config().EVM().FinalityDepth()),
- chain.HeadBroadcaster(),
vrfcommon.NewLogDeduper(int(chain.Config().EVM().FinalityDepth())))}, nil
}
if _, ok := task.(*pipeline.VRFTaskV2); ok {
@@ -223,49 +215,42 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
chain.Config().EVM(),
chain.Config().EVM().GasEstimator(),
lV2,
- chain.Client(),
+ chain,
chain.ID(),
- chain.LogBroadcaster(),
d.q,
v2.NewCoordinatorV2(coordinatorV2),
batchCoordinatorV2,
vrfOwner,
aggregator,
- chain.TxManager(),
d.pr,
d.ks.Eth(),
jb,
d.mailMon,
utils.NewHighCapacityMailbox[log.Broadcast](),
func() {},
- GetStartingResponseCountsV2(d.q, lV2, chainId.Uint64(), chain.Config().EVM().FinalityDepth()),
- chain.HeadBroadcaster(),
vrfcommon.NewLogDeduper(int(chain.Config().EVM().FinalityDepth())))}, nil
}
if _, ok := task.(*pipeline.VRFTask); ok {
return []job.ServiceCtx{&v1.Listener{
- Cfg: chain.Config().EVM(),
- FeeCfg: chain.Config().EVM().GasEstimator(),
- L: logger.Sugared(lV1),
- HeadBroadcaster: chain.HeadBroadcaster(),
- LogBroadcaster: chain.LogBroadcaster(),
- Q: d.q,
- Txm: chain.TxManager(),
- Coordinator: coordinator,
- PipelineRunner: d.pr,
- GethKs: d.ks.Eth(),
- Job: jb,
- MailMon: d.mailMon,
+ Cfg: chain.Config().EVM(),
+ FeeCfg: chain.Config().EVM().GasEstimator(),
+ L: logger.Sugared(lV1),
+ Q: d.q,
+ Coordinator: coordinator,
+ PipelineRunner: d.pr,
+ GethKs: d.ks.Eth(),
+ Job: jb,
+ MailMon: d.mailMon,
// Note the mailbox size effectively sets a limit on how many logs we can replay
// in the event of a VRF outage.
ReqLogs: utils.NewHighCapacityMailbox[log.Broadcast](),
ChStop: make(chan struct{}),
WaitOnStop: make(chan struct{}),
NewHead: make(chan struct{}, 1),
- ResponseCount: GetStartingResponseCountsV1(d.q, lV1, chainId.Uint64(), chain.Config().EVM().FinalityDepth()),
BlockNumberToReqID: pairing.New(),
ReqAdded: func() {},
Deduper: vrfcommon.NewLogDeduper(int(chain.Config().EVM().FinalityDepth())),
+ Chain: chain,
}}, nil
}
}
@@ -314,101 +299,3 @@ func FromAddressMaxGasPricesAllEqual(jb job.Job, keySpecificMaxGasPriceWei keySp
}
return
}
-
-func GetStartingResponseCountsV1(q pg.Q, l logger.Logger, chainID uint64, evmFinalityDepth uint32) map[[32]byte]uint64 {
- respCounts := map[[32]byte]uint64{}
-
- // Only check as far back as the evm finality depth for completed transactions.
- counts, err := getRespCounts(q, chainID, evmFinalityDepth)
- if err != nil {
- // Continue with an empty map, do not block job on this.
- l.Errorw("Unable to read previous confirmed fulfillments", "err", err)
- return respCounts
- }
-
- for _, c := range counts {
- // Remove the quotes from the json
- req := strings.Replace(c.RequestID, `"`, ``, 2)
- // Remove the 0x prefix
- b, err := hex.DecodeString(req[2:])
- if err != nil {
- l.Errorw("Unable to read fulfillment", "err", err, "reqID", c.RequestID)
- continue
- }
- var reqID [32]byte
- copy(reqID[:], b)
- respCounts[reqID] = uint64(c.Count)
- }
-
- return respCounts
-}
-
-func GetStartingResponseCountsV2(
- q pg.Q,
- l logger.Logger,
- chainID uint64,
- evmFinalityDepth uint32,
-) map[string]uint64 {
- respCounts := map[string]uint64{}
-
- // Only check as far back as the evm finality depth for completed transactions.
- counts, err := getRespCounts(q, chainID, evmFinalityDepth)
- if err != nil {
- // Continue with an empty map, do not block job on this.
- l.Errorw("Unable to read previous confirmed fulfillments", "err", err)
- return respCounts
- }
-
- for _, c := range counts {
- // Remove the quotes from the json
- req := strings.Replace(c.RequestID, `"`, ``, 2)
- // Remove the 0x prefix
- b, err := hex.DecodeString(req[2:])
- if err != nil {
- l.Errorw("Unable to read fulfillment", "err", err, "reqID", c.RequestID)
- continue
- }
- bi := new(big.Int).SetBytes(b)
- respCounts[bi.String()] = uint64(c.Count)
- }
- return respCounts
-}
-
-func getRespCounts(q pg.Q, chainID uint64, evmFinalityDepth uint32) (
- []struct {
- RequestID string
- Count int
- },
- error,
-) {
- counts := []struct {
- RequestID string
- Count int
- }{}
- // This query should use the idx_evm.txes_state_from_address_evm_chain_id
- // index, since the quantity of unconfirmed/unstarted/in_progress transactions _should_ be small
- // relative to the rest of the data.
- unconfirmedQuery := `
-SELECT meta->'RequestID' AS request_id, count(meta->'RequestID') AS count
-FROM evm.txes et
-WHERE et.meta->'RequestID' IS NOT NULL
-AND et.state IN ('unconfirmed', 'unstarted', 'in_progress')
-GROUP BY meta->'RequestID'
- `
- // Fetch completed transactions only as far back as the given cutoffBlockNumber. This avoids
- // a table scan of the evm.txes table, which could be large if it is unpruned.
- confirmedQuery := `
-SELECT meta->'RequestID' AS request_id, count(meta->'RequestID') AS count
-FROM evm.txes et JOIN evm.tx_attempts eta on et.id = eta.eth_tx_id
- join evm.receipts er on eta.hash = er.tx_hash
-WHERE et.meta->'RequestID' is not null
-AND er.block_number >= (SELECT number FROM evm.heads WHERE evm_chain_id = $1 ORDER BY number DESC LIMIT 1) - $2
-GROUP BY meta->'RequestID'
- `
- query := unconfirmedQuery + "\nUNION ALL\n" + confirmedQuery
- err := q.Select(&counts, query, chainID, evmFinalityDepth)
- if err != nil {
- return nil, err
- }
- return counts, nil
-}
diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go
index 91ae4400e3..927e2ae682 100644
--- a/core/services/vrf/delegate_test.go
+++ b/core/services/vrf/delegate_test.go
@@ -17,9 +17,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
- txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
+ "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/evmtest"
@@ -58,7 +58,7 @@ type vrfUniverse struct {
ks keystore.Master
vrfkey vrfkey.KeyV2
submitter common.Address
- txm *txmmocks.MockEvmTxManager
+ txm *txmgr.TxManager
hb httypes.HeadBroadcaster
legacyChains evm.LegacyChainContainer
cid big.Int
@@ -68,28 +68,33 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv
// Mock all chain interactions
lb := log_mocks.NewBroadcaster(t)
lb.On("AddDependents", 1).Maybe()
+ lb.On("Register", mock.Anything, mock.Anything).Return(func() {}).Maybe()
ec := evmclimocks.NewClient(t)
ec.On("ConfiguredChainID").Return(testutils.FixtureChainID)
+ ec.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(51), nil).Maybe()
lggr := logger.TestLogger(t)
hb := headtracker.NewHeadBroadcaster(lggr)
// Don't mock db interactions
prm := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
btORM := bridges.NewORM(db, lggr, cfg.Database())
- txm := txmmocks.NewMockEvmTxManager(t)
ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database())
+ _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
+ txm, err := txmgr.NewTxm(db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil)
+ orm := headtracker.NewORM(db, lggr, cfg.Database(), *testutils.FixtureChainID)
+ require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(51)))
jrm := job.NewORM(db, prm, btORM, ks, lggr, cfg.Database())
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)
pr := pipeline.NewRunner(prm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ks.Eth(), ks.VRF(), lggr, nil, nil)
require.NoError(t, ks.Unlock(testutils.Password))
- k, err := ks.Eth().Create(testutils.FixtureChainID)
- require.NoError(t, err)
+ k, err2 := ks.Eth().Create(testutils.FixtureChainID)
+ require.NoError(t, err2)
submitter := k.Address
require.NoError(t, err)
- vrfkey, err := ks.VRF().Create()
- require.NoError(t, err)
+ vrfkey, err3 := ks.VRF().Create()
+ require.NoError(t, err3)
return vrfUniverse{
jrm: jrm,
@@ -100,7 +105,7 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv
ks: ks,
vrfkey: vrfkey,
submitter: submitter,
- txm: txm,
+ txm: &txm,
hb: hb,
legacyChains: legacyChains,
cid: *ec.ConfiguredChainID(),
@@ -172,6 +177,7 @@ func setup(t *testing.T) (vrfUniverse, *v1.Listener, job.Job) {
listener.RunHeadListener(func() {})
}()
t.Cleanup(func() { listener.Stop(t) })
+ require.NoError(t, listener.Start(testutils.Context(t)))
return vuni, listener, jb
}
@@ -302,20 +308,6 @@ func TestDelegate_ValidLog(t *testing.T) {
// Expect a call to check if the req is already fulfilled.
vuni.ec.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(generateCallbackReturnValues(t, false), nil)
- // Ensure we queue up a valid eth transaction
- // Linked to requestID
- vuni.txm.On("CreateTransaction",
- mock.Anything,
- mock.MatchedBy(func(txRequest txmgr.TxRequest) bool {
- meta := txRequest.Meta
- return txRequest.FromAddress == vuni.submitter &&
- txRequest.ToAddress == common.HexToAddress(jb.VRFSpec.CoordinatorAddress.String()) &&
- txRequest.FeeLimit == uint32(500000) &&
- meta.JobID != nil && meta.RequestID != nil && meta.RequestTxHash != nil &&
- (*meta.JobID > 0 && *meta.RequestID == tc.reqID && *meta.RequestTxHash == txHash)
- }),
- ).Once().Return(txmgr.Tx{}, nil)
-
listener.HandleLog(log.NewLogBroadcast(tc.log, vuni.cid, nil))
// Wait until the log is present
waitForChannel(t, added, time.Second, "request not added to the queue")
diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go
index 92e697f229..b1f9bbb503 100644
--- a/core/services/vrf/v1/listener_v1.go
+++ b/core/services/vrf/v1/listener_v1.go
@@ -3,20 +3,22 @@ package v1
import (
"context"
"encoding/hex"
+ "errors"
"fmt"
"math/big"
+ "strings"
"sync"
"time"
+ "github.com/avast/retry-go/v4"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
heaps "github.com/theodesp/go-heaps"
"github.com/theodesp/go-heaps/pairing"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -46,24 +48,22 @@ type request struct {
type Listener struct {
services.StateMachine
- Cfg vrfcommon.Config
- FeeCfg vrfcommon.FeeConfig
- L logger.SugaredLogger
- LogBroadcaster log.Broadcaster
- Coordinator *solidity_vrf_coordinator_interface.VRFCoordinator
- PipelineRunner pipeline.Runner
- Job job.Job
- Q pg.Q
- HeadBroadcaster httypes.HeadBroadcasterRegistry
- Txm txmgr.TxManager
- GethKs vrfcommon.GethKeyStore
- MailMon *utils.MailboxMonitor
- ReqLogs *utils.Mailbox[log.Broadcast]
- ChStop utils.StopChan
- WaitOnStop chan struct{}
- NewHead chan struct{}
- LatestHead uint64
- LatestHeadMu sync.RWMutex
+ Cfg vrfcommon.Config
+ FeeCfg vrfcommon.FeeConfig
+ L logger.SugaredLogger
+ Coordinator *solidity_vrf_coordinator_interface.VRFCoordinator
+ PipelineRunner pipeline.Runner
+ Job job.Job
+ Q pg.Q
+ GethKs vrfcommon.GethKeyStore
+ MailMon *utils.MailboxMonitor
+ ReqLogs *utils.Mailbox[log.Broadcast]
+ ChStop utils.StopChan
+ WaitOnStop chan struct{}
+ NewHead chan struct{}
+ LatestHead uint64
+ LatestHeadMu sync.RWMutex
+ Chain evm.Chain
// We can keep these pending logs in memory because we
// only mark them confirmed once we send a corresponding fulfillment transaction.
@@ -110,11 +110,11 @@ func (lsn *Listener) getLatestHead() uint64 {
}
// Start complies with job.Service
-func (lsn *Listener) Start(context.Context) error {
+func (lsn *Listener) Start(ctx context.Context) error {
return lsn.StartOnce("VRFListener", func() error {
spec := job.LoadDefaultVRFPollPeriod(*lsn.Job.VRFSpec)
- unsubscribeLogs := lsn.LogBroadcaster.Register(lsn, log.ListenerOpts{
+ unsubscribeLogs := lsn.Chain.LogBroadcaster().Register(lsn, log.ListenerOpts{
Contract: lsn.Coordinator.Address(),
ParseLog: lsn.Coordinator.ParseLog,
LogsWithTopics: map[common.Hash][][]log.Topic{
@@ -136,10 +136,19 @@ func (lsn *Listener) Start(context.Context) error {
})
// Subscribe to the head broadcaster for handling
// per request conf requirements.
- latestHead, unsubscribeHeadBroadcaster := lsn.HeadBroadcaster.Subscribe(lsn)
+ latestHead, unsubscribeHeadBroadcaster := lsn.Chain.HeadBroadcaster().Subscribe(lsn)
if latestHead != nil {
lsn.setLatestHead(latestHead)
}
+
+ // Populate the response count map
+ lsn.RespCountMu.Lock()
+ defer lsn.RespCountMu.Unlock()
+ respCount, err := lsn.GetStartingResponseCountsV1(ctx)
+ if err != nil {
+ return err
+ }
+ lsn.ResponseCount = respCount
go lsn.RunLogListener([]func(){unsubscribeLogs}, spec.MinIncomingConfirmations)
go lsn.RunHeadListener(unsubscribeHeadBroadcaster)
@@ -148,6 +157,48 @@ func (lsn *Listener) Start(context.Context) error {
})
}
+func (lsn *Listener) GetStartingResponseCountsV1(ctx context.Context) (respCount map[[32]byte]uint64, err error) {
+ respCounts := make(map[[32]byte]uint64)
+ var latestBlockNum *big.Int
+ // Retry client call for LatestBlockHeight if fails
+ // Want to avoid failing startup due to potential faulty RPC call
+ err = retry.Do(func() error {
+ latestBlockNum, err = lsn.Chain.Client().LatestBlockHeight(ctx)
+ return err
+ }, retry.Attempts(10), retry.Delay(500*time.Millisecond))
+ if err != nil {
+ return nil, err
+ }
+ if latestBlockNum == nil {
+ return nil, errors.New("LatestBlockHeight return nil block num")
+ }
+ confirmedBlockNum := latestBlockNum.Int64() - int64(lsn.Chain.Config().EVM().FinalityDepth())
+ // Only check as far back as the evm finality depth for completed transactions.
+ var counts []vrfcommon.RespCountEntry
+ counts, err = vrfcommon.GetRespCounts(ctx, lsn.Chain.TxManager(), lsn.Chain.Client().ConfiguredChainID(), confirmedBlockNum)
+ if err != nil {
+ // Continue with an empty map, do not block job on this.
+ lsn.L.Errorw("Unable to read previous confirmed fulfillments", "err", err)
+ return respCounts, nil
+ }
+
+ for _, c := range counts {
+ // Remove the quotes from the json
+ req := strings.Replace(c.RequestID, `"`, ``, 2)
+ // Remove the 0x prefix
+ b, err := hex.DecodeString(req[2:])
+ if err != nil {
+ lsn.L.Errorw("Unable to read fulfillment", "err", err, "reqID", c.RequestID)
+ continue
+ }
+ var reqID [32]byte
+ copy(reqID[:], b)
+ respCounts[reqID] = uint64(c.Count)
+ }
+
+ return respCounts, nil
+}
+
// Removes and returns all the confirmed logs from
// the pending queue.
func (lsn *Listener) extractConfirmedLogs() []request {
@@ -314,7 +365,7 @@ func (lsn *Listener) handleLog(lb log.Broadcast, minConfs uint32) {
}
func (lsn *Listener) shouldProcessLog(lb log.Broadcast) bool {
- consumed, err := lsn.LogBroadcaster.WasAlreadyConsumed(lb)
+ consumed, err := lsn.Chain.LogBroadcaster().WasAlreadyConsumed(lb)
if err != nil {
lsn.L.Errorw("Could not determine if log was already consumed", "error", err, "txHash", lb.RawLog().TxHash)
// Do not process, let lb resend it as a retry mechanism.
@@ -324,7 +375,7 @@ func (lsn *Listener) shouldProcessLog(lb log.Broadcast) bool {
}
func (lsn *Listener) markLogAsConsumed(lb log.Broadcast) {
- err := lsn.LogBroadcaster.MarkConsumed(lb)
+ err := lsn.Chain.LogBroadcaster().MarkConsumed(lb)
lsn.L.ErrorIf(err, fmt.Sprintf("Unable to mark log %v as consumed", lb.String()))
}
@@ -432,7 +483,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 pg.Queryer) error {
// Always mark consumed regardless of whether the proof failed or not.
- if err = lsn.LogBroadcaster.MarkConsumed(req.lb, pg.WithQueryer(tx)); err != nil {
+ if err = lsn.Chain.LogBroadcaster().MarkConsumed(req.lb, pg.WithQueryer(tx)); 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 09c9a0ed43..60a7cd18d2 100644
--- a/core/services/vrf/v2/integration_helpers_test.go
+++ b/core/services/vrf/v2/integration_helpers_test.go
@@ -113,7 +113,7 @@ func testSingleConsumerHappyPath(
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, requestID1, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID1, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
// In particular:
@@ -133,7 +133,7 @@ func testSingleConsumerHappyPath(
t.Log("runs", len(runs))
return len(runs) == 2
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mine(t, requestID2, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID2, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
// In particular:
@@ -285,7 +285,7 @@ func testMultipleConsumersNeedBHS(
return len(runs) == 1
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mine(t, requestID, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
rwfe := assertRandomWordsFulfilled(t, requestID, true, coordinator, nativePayment)
if len(assertions) > 0 {
@@ -446,7 +446,7 @@ func testMultipleConsumersNeedTrustedBHS(
return len(runs) == 1
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mine(t, requestID, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
rwfe := assertRandomWordsFulfilled(t, requestID, true, coordinator, nativePayment)
if len(assertions) > 0 {
@@ -592,7 +592,7 @@ func testSingleConsumerHappyPathBatchFulfillment(
return len(runs) == numRequests
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mineBatch(t, reqIDs, subID, uni.backend, db, vrfVersion)
+ mineBatch(t, reqIDs, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
for i, requestID := range reqIDs {
// Assert correct state of RandomWordsFulfilled event.
@@ -694,7 +694,7 @@ func testSingleConsumerNeedsTopUp(
// Mine the fulfillment. Need to wait for Txm to mark the tx as confirmed
// so that we can actually see the event on the simulated chain.
- mine(t, requestID, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert the state of the RandomWordsFulfilled event.
rwfe := assertRandomWordsFulfilled(t, requestID, true, coordinator, nativePayment)
@@ -818,7 +818,7 @@ func testBlockHeaderFeeder(
return len(runs) == 1
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mine(t, requestID, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
rwfe := assertRandomWordsFulfilled(t, requestID, true, coordinator, nativePayment)
if len(assertions) > 0 {
@@ -1021,7 +1021,7 @@ func testSingleConsumerForcedFulfillment(
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, requestID, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
// In this particular case:
@@ -1264,7 +1264,7 @@ func testSingleConsumerBigGasCallbackSandwich(
}, 3*time.Second, 1*time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, reqIDs[1], subID, uni.backend, db, vrfVersion)
+ mine(t, reqIDs[1], subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert the random word was fulfilled
assertRandomWordsFulfilled(t, reqIDs[1], false, uni.rootContract, nativePayment)
@@ -1365,7 +1365,7 @@ func testSingleConsumerMultipleGasLanes(
}, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, cheapRequestID, subID, uni.backend, db, vrfVersion)
+ mine(t, cheapRequestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
assertRandomWordsFulfilled(t, cheapRequestID, true, uni.rootContract, nativePayment)
@@ -1397,7 +1397,7 @@ func testSingleConsumerMultipleGasLanes(
}, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, expensiveRequestID, subID, uni.backend, db, vrfVersion)
+ mine(t, expensiveRequestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
assertRandomWordsFulfilled(t, expensiveRequestID, true, uni.rootContract, nativePayment)
@@ -1477,7 +1477,7 @@ func testSingleConsumerAlwaysRevertingCallbackStillFulfilled(
}, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, requestID, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
assertRandomWordsFulfilled(t, requestID, false, uni.rootContract, nativePayment)
@@ -1552,7 +1552,7 @@ func testConsumerProxyHappyPath(
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, requestID1, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID1, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
assertRandomWordsFulfilled(t, requestID1, true, uni.rootContract, nativePayment)
@@ -1576,7 +1576,7 @@ func testConsumerProxyHappyPath(
t.Log("runs", len(runs))
return len(runs) == 2
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mine(t, requestID2, subID, uni.backend, db, vrfVersion)
+ mine(t, requestID2, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID)
assertRandomWordsFulfilled(t, requestID2, true, uni.rootContract, nativePayment)
// Assert correct number of random words sent by coordinator.
diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go
index 6d2b77acb7..094d7d060e 100644
--- a/core/services/vrf/v2/integration_v2_plus_test.go
+++ b/core/services/vrf/v2/integration_v2_plus_test.go
@@ -1200,7 +1200,7 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) {
return len(runs) == 1
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
- mine(t, requestID, subID, uni.backend, db, vrfcommon.V2Plus)
+ mine(t, requestID, subID, uni.backend, db, vrfcommon.V2Plus, testutils.SimulatedChainID)
assertRandomWordsFulfilled(t, requestID, true, uni.rootContract, false)
// Assert correct number of random words sent by coordinator.
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index 093adc8eaa..3a691ec2e2 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -24,6 +24,7 @@ import (
"github.com/onsi/gomega"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
@@ -32,6 +33,8 @@ import (
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
evmlogger "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
@@ -58,6 +61,8 @@ 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/evmtest"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -67,9 +72,10 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1"
- "github.com/smartcontractkit/chainlink/v2/core/services/vrf"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof"
+ v1 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v1"
v22 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers"
@@ -127,24 +133,14 @@ type coordinatorV2Universe struct {
batchCoordinatorContractAddress common.Address
}
-const (
- ConfirmedEthTxesV2Query = `SELECT * FROM evm.txes
- WHERE evm.txes.state = 'confirmed'
- AND evm.txes.meta->>'RequestID' = $1
- AND CAST(evm.txes.meta->>'SubId' AS NUMERIC) = $2 LIMIT 1`
- ConfirmedEthTxesV2PlusQuery = `SELECT * FROM evm.txes
- WHERE evm.txes.state = 'confirmed'
- AND evm.txes.meta->>'RequestID' = $1
- AND CAST(evm.txes.meta->>'GlobalSubId' AS NUMERIC) = $2 LIMIT 1`
- ConfirmedEthTxesV2BatchQuery = `
- SELECT * FROM evm.txes
- WHERE evm.txes.state = 'confirmed'
- AND CAST(evm.txes.meta->>'SubId' AS NUMERIC) = $1`
- ConfirmedEthTxesV2PlusBatchQuery = `
- SELECT * FROM evm.txes
- WHERE evm.txes.state = 'confirmed'
- AND CAST(evm.txes.meta->>'GlobalSubId' AS NUMERIC) = $1`
-)
+func makeTestTxm(t *testing.T, txStore txmgr.TestEvmTxStore, keyStore keystore.Master, ec *evmclimocks.Client) txmgrcommon.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] {
+ _, _, evmConfig := txmgr.MakeTestConfigs(t)
+ txmConfig := txmgr.NewEvmTxmConfig(evmConfig)
+ txm := txmgr.NewEvmTxm(ec.ConfiguredChainID(), txmConfig, evmConfig.Transactions(), keyStore.Eth(), logger.TestLogger(t), nil, nil,
+ nil, txStore, nil, nil, nil, nil)
+
+ return txm
+}
func newVRFCoordinatorV2Universe(t *testing.T, key ethkey.KeyV2, numConsumers int) coordinatorV2Universe {
testutils.SkipShort(t, "VRFCoordinatorV2Universe")
@@ -454,7 +450,7 @@ func sendEth(t *testing.T, key ethkey.KeyV2, ec *backends.SimulatedBackend, to c
nonce, err := ec.PendingNonceAt(testutils.Context(t), key.Address)
require.NoError(t, err)
tx := gethtypes.NewTx(&gethtypes.DynamicFeeTx{
- ChainID: big.NewInt(1337),
+ ChainID: testutils.SimulatedChainID,
Nonce: nonce,
GasTipCap: big.NewInt(1),
GasFeeCap: assets.GWei(10).ToInt(), // block base fee in sim
@@ -463,7 +459,7 @@ func sendEth(t *testing.T, key ethkey.KeyV2, ec *backends.SimulatedBackend, to c
Value: big.NewInt(0).Mul(big.NewInt(int64(eth)), big.NewInt(1e18)),
Data: nil,
})
- signedTx, err := gethtypes.SignTx(tx, gethtypes.NewLondonSigner(big.NewInt(1337)), key.ToEcdsaPrivKey())
+ signedTx, err := gethtypes.SignTx(tx, gethtypes.NewLondonSigner(testutils.SimulatedChainID), key.ToEcdsaPrivKey())
require.NoError(t, err)
err = ec.SendTransaction(testutils.Context(t), signedTx)
require.NoError(t, err)
@@ -762,32 +758,42 @@ func assertNumRandomWords(
}
}
-func mine(t *testing.T, requestID, subID *big.Int, backend *backends.SimulatedBackend, db *sqlx.DB, vrfVersion vrfcommon.Version) bool {
- var query string
+func mine(t *testing.T, requestID, subID *big.Int, backend *backends.SimulatedBackend, db *sqlx.DB, vrfVersion vrfcommon.Version, chainId *big.Int) bool {
+ cfg := pgtest.NewQConfig(false)
+ txstore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg)
+ var metaField string
if vrfVersion == vrfcommon.V2Plus {
- query = ConfirmedEthTxesV2PlusQuery
+ metaField = "GlobalSubId"
} else if vrfVersion == vrfcommon.V2 {
- query = ConfirmedEthTxesV2Query
+ metaField = "SubId"
} else {
t.Errorf("unsupported vrf version %s", vrfVersion)
}
+
return gomega.NewWithT(t).Eventually(func() bool {
backend.Commit()
- var txs []txmgr.DbEthTx
- err := db.Select(&txs, query, common.BytesToHash(requestID.Bytes()).String(), subID.String())
+ txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, chainId)
require.NoError(t, err)
- t.Log("num txs", len(txs))
- return len(txs) == 1
+ for _, tx := range txes {
+ meta, err := tx.GetMeta()
+ require.NoError(t, err)
+ if meta.RequestID.String() == common.BytesToHash(requestID.Bytes()).String() {
+ return true
+ }
+ }
+ return false
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
}
-func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend *backends.SimulatedBackend, db *sqlx.DB, vrfVersion vrfcommon.Version) bool {
+func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend *backends.SimulatedBackend, db *sqlx.DB, vrfVersion vrfcommon.Version, chainId *big.Int) bool {
requestIDMap := map[string]bool{}
- var query string
+ cfg := pgtest.NewQConfig(false)
+ txstore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg)
+ var metaField string
if vrfVersion == vrfcommon.V2Plus {
- query = ConfirmedEthTxesV2PlusBatchQuery
+ metaField = "GlobalSubId"
} else if vrfVersion == vrfcommon.V2 {
- query = ConfirmedEthTxesV2BatchQuery
+ metaField = "SubId"
} else {
t.Errorf("unsupported vrf version %s", vrfVersion)
}
@@ -796,12 +802,10 @@ func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend *bac
}
return gomega.NewWithT(t).Eventually(func() bool {
backend.Commit()
- var txs []txmgr.DbEthTx
- require.NoError(t, db.Select(&txs, query, subID.String()))
- for _, tx := range txs {
- var evmTx txmgr.Tx
- tx.ToTx(&evmTx)
- meta, err := evmTx.GetMeta()
+ txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, chainId)
+ require.NoError(t, err)
+ for _, tx := range txes {
+ meta, err := tx.GetMeta()
require.NoError(t, err)
for _, requestID := range meta.RequestIDs {
if _, ok := requestIDMap[requestID.String()]; ok {
@@ -1188,7 +1192,7 @@ func TestVRFV2Integration_SingleConsumer_Wrapper(t *testing.T) {
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, requestID, new(big.Int).SetUint64(wrapperSubID), uni.backend, db, vrfcommon.V2)
+ mine(t, requestID, new(big.Int).SetUint64(wrapperSubID), uni.backend, db, vrfcommon.V2, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
assertRandomWordsFulfilled(t, requestID, true, uni.rootContract, false)
@@ -1268,7 +1272,7 @@ func TestVRFV2Integration_Wrapper_High_Gas(t *testing.T) {
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
// Mine the fulfillment that was queued.
- mine(t, requestID, new(big.Int).SetUint64(wrapperSubID), uni.backend, db, vrfcommon.V2)
+ mine(t, requestID, new(big.Int).SetUint64(wrapperSubID), uni.backend, db, vrfcommon.V2, testutils.SimulatedChainID)
// Assert correct state of RandomWordsFulfilled event.
assertRandomWordsFulfilled(t, requestID, true, uni.rootContract, false)
@@ -1599,6 +1603,10 @@ func TestIntegrationVRFV2(t *testing.T) {
require.Zero(t, key.Cmp(keys[0]))
require.NoError(t, app.Start(testutils.Context(t)))
+ var chain evm.Chain
+ chain, err = app.GetRelayers().LegacyEVMChains().Get(testutils.SimulatedChainID.String())
+ require.NoError(t, err)
+ listenerV2 := v22.MakeTestListenerV2(chain)
jbs := createVRFJobs(
t,
@@ -1751,11 +1759,10 @@ func TestIntegrationVRFV2(t *testing.T) {
})
// We should see the response count present
- chain, err := app.GetRelayers().LegacyEVMChains().Get(big.NewInt(1337).String())
require.NoError(t, err)
-
- q := pg.NewQ(app.GetSqlxDB(), app.Logger, app.Config.Database())
- counts := vrf.GetStartingResponseCountsV2(q, app.Logger, chain.Client().ConfiguredChainID().Uint64(), chain.Config().EVM().FinalityDepth())
+ var counts map[string]uint64
+ counts, err = listenerV2.GetStartingResponseCountsV2(testutils.Context(t))
+ require.NoError(t, err)
t.Log(counts, rf[0].RequestID().String())
assert.Equal(t, uint64(1), counts[rf[0].RequestID().String()])
}
@@ -1997,19 +2004,30 @@ func TestFulfillmentCost(t *testing.T) {
func TestStartingCountsV1(t *testing.T) {
cfg, db := heavyweight.FullTestDBNoFixturesV2(t, "vrf_test_starting_counts", nil)
- _, err := db.Exec(`INSERT INTO evm.heads (hash, number, parent_hash, created_at, timestamp, evm_chain_id)
- VALUES ($1, 4, $2, NOW(), NOW(), 1337)`, utils.NewHash(), utils.NewHash())
- require.NoError(t, err)
lggr := logger.TestLogger(t)
- q := pg.NewQ(db, lggr, cfg.Database())
- finalityDepth := 3
- counts := vrf.GetStartingResponseCountsV1(q, lggr, 1337, uint32(finalityDepth))
- assert.Equal(t, 0, len(counts))
+ qCfg := pgtest.NewQConfig(false)
+ txStore := txmgr.NewTxStore(db, logger.TestLogger(t), qCfg)
ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database())
+ ec := evmclimocks.NewClient(t)
+ ec.On("ConfiguredChainID").Return(testutils.SimulatedChainID)
+ ec.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(2), nil).Maybe()
+ txm := makeTestTxm(t, txStore, ks, ec)
+ relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm})
+ legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
+ chain, err := legacyChains.Get(testutils.SimulatedChainID.String())
+ require.NoError(t, err)
+ listenerV1 := &v1.Listener{
+ Chain: chain,
+ }
+ listenerV2 := v22.MakeTestListenerV2(chain)
+ var counts map[[32]byte]uint64
+ counts, err = listenerV1.GetStartingResponseCountsV1(testutils.Context(t))
+ require.NoError(t, err)
+ assert.Equal(t, 0, len(counts))
err = ks.Unlock(testutils.Password)
require.NoError(t, err)
- k, err := ks.Eth().Create(big.NewInt(1337))
+ k, err := ks.Eth().Create(testutils.SimulatedChainID)
require.NoError(t, err)
b := time.Now()
n1, n2, n3, n4 := evmtypes.Nonce(0), evmtypes.Nonce(1), evmtypes.Nonce(2), evmtypes.Nonce(3)
@@ -2027,7 +2045,7 @@ func TestStartingCountsV1(t *testing.T) {
md2, err := json.Marshal(&m2)
md2_ := datatypes.JSON(md2)
require.NoError(t, err)
- chainID := utils.NewBig(big.NewInt(1337))
+ chainID := utils.NewBig(testutils.SimulatedChainID)
confirmedTxes := []txmgr.Tx{
{
Sequence: &n1,
@@ -2100,16 +2118,13 @@ func TestStartingCountsV1(t *testing.T) {
ChainID: chainID.ToInt(),
})
}
- sql := `INSERT INTO evm.txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, state, created_at, broadcast_at, initial_broadcast_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id)
-VALUES (:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit, :state, :created_at, :broadcast_at, :initial_broadcast_at, :meta, :subject, :evm_chain_id, :min_confirmations, :pipeline_task_run_id);`
- for _, tx := range append(confirmedTxes, unconfirmedTxes...) {
- var dbEtx txmgr.DbEthTx
- dbEtx.FromTx(&tx) //nolint:gosec // just copying fields
- _, err = db.NamedExec(sql, &dbEtx)
+ txList := append(confirmedTxes, unconfirmedTxes...)
+ for i := range txList {
+ err = txStore.InsertTx(&txList[i])
require.NoError(t, err)
}
- // add evm.tx_attempts for confirmed
+ // add tx attempt for confirmed
broadcastBlock := int64(1)
var txAttempts []txmgr.TxAttempt
for i := range confirmedTxes {
@@ -2124,7 +2139,7 @@ VALUES (:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit
ChainSpecificFeeLimit: uint32(100),
})
}
- // add evm.tx_attempts for unconfirmed
+ // add tx attempt for unconfirmed
for i := range unconfirmedTxes {
txAttempts = append(txAttempts, txmgr.TxAttempt{
TxID: int64(i + 1 + len(confirmedTxes)),
@@ -2139,41 +2154,35 @@ VALUES (:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit
for _, txAttempt := range txAttempts {
t.Log("tx attempt eth tx id: ", txAttempt.TxID)
}
- sql = `INSERT INTO evm.tx_attempts (eth_tx_id, gas_price, signed_raw_tx, hash, state, created_at, chain_specific_gas_limit)
- VALUES (:eth_tx_id, :gas_price, :signed_raw_tx, :hash, :state, :created_at, :chain_specific_gas_limit)`
- for _, attempt := range txAttempts {
- var dbAttempt txmgr.DbEthTxAttempt
- dbAttempt.FromTxAttempt(&attempt) //nolint:gosec // just copying fields
- _, err = db.NamedExec(sql, &dbAttempt)
+ for i := range txAttempts {
+ err = txStore.InsertTxAttempt(&txAttempts[i])
require.NoError(t, err)
}
// add evm.receipts
- receipts := []txmgr.Receipt{}
+ receipts := []evmtypes.Receipt{}
for i := 0; i < 4; i++ {
- receipts = append(receipts, txmgr.Receipt{
+ receipts = append(receipts, evmtypes.Receipt{
BlockHash: utils.NewHash(),
TxHash: txAttempts[i].Hash,
- BlockNumber: broadcastBlock,
+ BlockNumber: big.NewInt(broadcastBlock),
TransactionIndex: 1,
- Receipt: evmtypes.Receipt{},
- CreatedAt: time.Now(),
})
}
- sql = `INSERT INTO evm.receipts (block_hash, tx_hash, block_number, transaction_index, receipt, created_at)
- VALUES (:block_hash, :tx_hash, :block_number, :transaction_index, :receipt, :created_at)`
- for _, r := range receipts {
- _, err2 := db.NamedExec(sql, r)
- require.NoError(t, err2)
+ for i := range receipts {
+ _, err = txStore.InsertReceipt(&receipts[i])
+ require.NoError(t, err)
}
- counts = vrf.GetStartingResponseCountsV1(q, lggr, 1337, uint32(finalityDepth))
+ counts, err = listenerV1.GetStartingResponseCountsV1(testutils.Context(t))
+ require.NoError(t, err)
assert.Equal(t, 3, len(counts))
assert.Equal(t, uint64(1), counts[utils.PadByteToHash(0x10)])
assert.Equal(t, uint64(2), counts[utils.PadByteToHash(0x11)])
assert.Equal(t, uint64(2), counts[utils.PadByteToHash(0x12)])
- countsV2 := vrf.GetStartingResponseCountsV2(q, lggr, 1337, uint32(finalityDepth))
+ countsV2, err := listenerV2.GetStartingResponseCountsV2(testutils.Context(t))
+ require.NoError(t, err)
t.Log(countsV2)
assert.Equal(t, 3, len(countsV2))
assert.Equal(t, uint64(1), countsV2[big.NewInt(0x10).String()])
diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go
index 8bac485d65..17cb9ec96e 100644
--- a/core/services/vrf/v2/listener_v2.go
+++ b/core/services/vrf/v2/listener_v2.go
@@ -4,6 +4,7 @@ import (
"cmp"
"context"
"database/sql"
+ "encoding/hex"
"fmt"
"math"
"math/big"
@@ -12,6 +13,7 @@ import (
"sync"
"time"
+ "github.com/avast/retry-go/v4"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
@@ -27,8 +29,7 @@ import (
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
- httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -56,6 +57,8 @@ var (
batchCoordinatorV2ABI = evmtypes.MustGetABI(batch_vrf_coordinator_v2.BatchVRFCoordinatorV2ABI)
batchCoordinatorV2PlusABI = evmtypes.MustGetABI(batch_vrf_coordinator_v2plus.BatchVRFCoordinatorV2PlusABI)
vrfOwnerABI = evmtypes.MustGetABI(vrf_owner.VRFOwnerMetaData.ABI)
+ // These are the transaction states used when summing up already reserved subscription funds that are about to be used in in-flight transactions
+ reserveEthLinkQueryStates = []txmgrtypes.TxState{txmgrcommon.TxUnconfirmed, txmgrcommon.TxUnstarted, txmgrcommon.TxInProgress}
)
const (
@@ -73,29 +76,8 @@ const (
// backoffFactor is the factor by which to increase the delay each time a request fails.
backoffFactor = 1.3
- V2ReservedLinkQuery = `SELECT SUM(CAST(meta->>'MaxLink' AS NUMERIC(78, 0)))
- FROM evm.txes
- WHERE meta->>'MaxLink' IS NOT NULL
- AND evm_chain_id = $1
- AND CAST(meta->>'SubId' AS NUMERIC) = $2
- AND state IN ('unconfirmed', 'unstarted', 'in_progress')
- GROUP BY meta->>'SubId'`
-
- V2PlusReservedLinkQuery = `SELECT SUM(CAST(meta->>'MaxLink' AS NUMERIC(78, 0)))
- FROM evm.txes
- WHERE meta->>'MaxLink' IS NOT NULL
- AND evm_chain_id = $1
- AND CAST(meta->>'GlobalSubId' AS NUMERIC) = $2
- AND state IN ('unconfirmed', 'unstarted', 'in_progress')
- GROUP BY meta->>'GlobalSubId'`
-
- V2PlusReservedEthQuery = `SELECT SUM(CAST(meta->>'MaxEth' AS NUMERIC(78, 0)))
- FROM evm.txes
- WHERE meta->>'MaxEth' IS NOT NULL
- AND evm_chain_id = $1
- AND CAST(meta->>'GlobalSubId' AS NUMERIC) = $2
- AND state IN ('unconfirmed', 'unstarted', 'in_progress')
- GROUP BY meta->>'GlobalSubId'`
+ txMetaFieldSubId = "SubId"
+ txMetaGlobalSubId = "GlobalSubId"
CouldNotDetermineIfLogConsumedMsg = "Could not determine if log was already consumed"
)
@@ -116,33 +98,27 @@ func New(
cfg vrfcommon.Config,
feeCfg vrfcommon.FeeConfig,
l logger.Logger,
- ethClient evmclient.Client,
+ chain evm.Chain,
chainID *big.Int,
- logBroadcaster log.Broadcaster,
q pg.Q,
coordinator CoordinatorV2_X,
batchCoordinator batch_vrf_coordinator_v2.BatchVRFCoordinatorV2Interface,
vrfOwner vrf_owner.VRFOwnerInterface,
aggregator *aggregator_v3_interface.AggregatorV3Interface,
- txm txmgr.TxManager,
pipelineRunner pipeline.Runner,
gethks keystore.Eth,
job job.Job,
mailMon *utils.MailboxMonitor,
reqLogs *utils.Mailbox[log.Broadcast],
reqAdded func(),
- respCount map[string]uint64,
- headBroadcaster httypes.HeadBroadcasterRegistry,
deduper *vrfcommon.LogDeduper,
) job.ServiceCtx {
return &listenerV2{
cfg: cfg,
feeCfg: feeCfg,
l: logger.Sugared(l),
- ethClient: ethClient,
+ chain: chain,
chainID: chainID,
- logBroadcaster: logBroadcaster,
- txm: txm,
mailMon: mailMon,
coordinator: coordinator,
batchCoordinator: batchCoordinator,
@@ -154,9 +130,7 @@ func New(
reqLogs: reqLogs,
chStop: make(chan struct{}),
reqAdded: reqAdded,
- respCount: respCount,
blockNumberToReqID: pairing.New(),
- headBroadcaster: headBroadcaster,
latestHeadMu: sync.RWMutex{},
wg: &sync.WaitGroup{},
aggregator: aggregator,
@@ -193,14 +167,12 @@ type vrfPipelineResult struct {
type listenerV2 struct {
services.StateMachine
- cfg vrfcommon.Config
- feeCfg vrfcommon.FeeConfig
- l logger.SugaredLogger
- ethClient evmclient.Client
- chainID *big.Int
- logBroadcaster log.Broadcaster
- txm txmgr.TxManager
- mailMon *utils.MailboxMonitor
+ cfg vrfcommon.Config
+ feeCfg vrfcommon.FeeConfig
+ l logger.SugaredLogger
+ chain evm.Chain
+ chainID *big.Int
+ mailMon *utils.MailboxMonitor
coordinator CoordinatorV2_X
batchCoordinator batch_vrf_coordinator_v2.BatchVRFCoordinatorV2Interface
@@ -229,7 +201,6 @@ type listenerV2 struct {
blockNumberToReqID *pairing.PairHeap
// head tracking data structures
- headBroadcaster httypes.HeadBroadcasterRegistry
latestHeadMu sync.RWMutex
latestHeadNumber uint64
@@ -273,7 +244,7 @@ func (lsn *listenerV2) Start(ctx context.Context) error {
spec := job.LoadDefaultVRFPollPeriod(*lsn.job.VRFSpec)
- unsubscribeLogs := lsn.logBroadcaster.Register(lsn, log.ListenerOpts{
+ unsubscribeLogs := lsn.chain.LogBroadcaster().Register(lsn, log.ListenerOpts{
Contract: lsn.coordinator.Address(),
ParseLog: lsn.coordinator.ParseLog,
LogsWithTopics: lsn.coordinator.LogsWithTopics(spec.PublicKey.MustHash()),
@@ -284,11 +255,20 @@ func (lsn *listenerV2) Start(ctx context.Context) error {
ReplayStartedCallback: lsn.ReplayStartedCallback,
})
- latestHead, unsubscribeHeadBroadcaster := lsn.headBroadcaster.Subscribe(lsn)
+ latestHead, unsubscribeHeadBroadcaster := lsn.chain.HeadBroadcaster().Subscribe(lsn)
if latestHead != nil {
lsn.setLatestHead(latestHead)
}
+ lsn.respCountMu.Lock()
+ defer lsn.respCountMu.Unlock()
+ var respCount map[string]uint64
+ respCount, err = lsn.GetStartingResponseCountsV2(ctx)
+ if err != nil {
+ return err
+ }
+ lsn.respCount = respCount
+
// Log listener gathers request logs
lsn.wg.Add(1)
go func() {
@@ -306,6 +286,46 @@ func (lsn *listenerV2) Start(ctx context.Context) error {
})
}
+func (lsn *listenerV2) GetStartingResponseCountsV2(ctx context.Context) (respCount map[string]uint64, err error) {
+ respCounts := map[string]uint64{}
+ var latestBlockNum *big.Int
+ // Retry client call for LatestBlockHeight if fails
+ // Want to avoid failing startup due to potential faulty RPC call
+ err = retry.Do(func() error {
+ latestBlockNum, err = lsn.chain.Client().LatestBlockHeight(ctx)
+ return err
+ }, retry.Attempts(10), retry.Delay(500*time.Millisecond))
+ if err != nil {
+ return nil, err
+ }
+ if latestBlockNum == nil {
+ return nil, errors.New("LatestBlockHeight return nil block num")
+ }
+ confirmedBlockNum := latestBlockNum.Int64() - int64(lsn.chain.Config().EVM().FinalityDepth())
+ // Only check as far back as the evm finality depth for completed transactions.
+ var counts []vrfcommon.RespCountEntry
+ counts, err = vrfcommon.GetRespCounts(ctx, lsn.chain.TxManager(), lsn.chainID, confirmedBlockNum)
+ if err != nil {
+ // Continue with an empty map, do not block job on this.
+ lsn.l.Errorw("Unable to read previous confirmed fulfillments", "err", err)
+ return respCounts, nil
+ }
+
+ for _, c := range counts {
+ // Remove the quotes from the json
+ req := strings.Replace(c.RequestID, `"`, ``, 2)
+ // Remove the 0x prefix
+ b, err := hex.DecodeString(req[2:])
+ if err != nil {
+ lsn.l.Errorw("Unable to read fulfillment", "err", err, "reqID", c.RequestID)
+ continue
+ }
+ bi := new(big.Int).SetBytes(b)
+ respCounts[bi.String()] = uint64(c.Count)
+ }
+ return respCounts, nil
+}
+
func (lsn *listenerV2) setLatestHead(head *evmtypes.Head) {
lsn.latestHeadMu.Lock()
defer lsn.latestHeadMu.Unlock()
@@ -520,68 +540,80 @@ func (lsn *listenerV2) processPendingVRFRequests(ctx context.Context) {
// MaybeSubtractReservedLink figures out how much LINK is reserved for other VRF requests that
// have not been fully confirmed yet on-chain, and subtracts that from the given startBalance,
// and returns that value if there are no errors.
-func MaybeSubtractReservedLink(q pg.Q, startBalance *big.Int, chainID uint64, subID *big.Int, vrfVersion vrfcommon.Version) (*big.Int, error) {
- var (
- reservedLink string
- query string
- )
+func (lsn *listenerV2) MaybeSubtractReservedLink(ctx context.Context, startBalance *big.Int, chainID *big.Int, subID *big.Int, vrfVersion vrfcommon.Version) (*big.Int, error) {
+ var metaField string
if vrfVersion == vrfcommon.V2Plus {
- query = V2PlusReservedLinkQuery
+ metaField = txMetaGlobalSubId
} else if vrfVersion == vrfcommon.V2 {
- query = V2ReservedLinkQuery
+ metaField = txMetaFieldSubId
} else {
return nil, errors.Errorf("unsupported vrf version %s", vrfVersion)
}
- err := q.Get(&reservedLink, query, chainID, subID.String())
+ txes, err := lsn.chain.TxManager().FindTxesByMetaFieldAndStates(ctx, metaField, subID.String(), reserveEthLinkQueryStates, chainID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
- return nil, errors.Wrap(err, "getting reserved LINK")
+ return nil, errors.Wrap(err, "TXM FindTxesByMetaFieldAndStates failed")
}
- if reservedLink != "" {
- reservedLinkInt, success := big.NewInt(0).SetString(reservedLink, 10)
- if !success {
- return nil, fmt.Errorf("converting reserved LINK %s", reservedLink)
+ reservedLinkSum := big.NewInt(0)
+ // Aggregate non-null MaxLink from all txes returned
+ for _, tx := range txes {
+ var meta *txmgrtypes.TxMeta[common.Address, common.Hash]
+ meta, err = tx.GetMeta()
+ if err != nil {
+ return nil, errors.Wrap(err, "GetMeta for Tx failed")
}
+ if meta != nil && meta.MaxLink != nil {
+ txMaxLink, success := new(big.Int).SetString(*meta.MaxLink, 10)
+ if !success {
+ return nil, fmt.Errorf("converting reserved LINK %s", *meta.MaxLink)
+ }
- return new(big.Int).Sub(startBalance, reservedLinkInt), nil
+ reservedLinkSum.Add(reservedLinkSum, txMaxLink)
+ }
}
- return new(big.Int).Set(startBalance), nil
+ return new(big.Int).Sub(startBalance, reservedLinkSum), nil
}
// MaybeSubtractReservedEth figures out how much ether is reserved for other VRF requests that
// have not been fully confirmed yet on-chain, and subtracts that from the given startBalance,
// and returns that value if there are no errors.
-func MaybeSubtractReservedEth(q pg.Q, startBalance *big.Int, chainID uint64, subID *big.Int, vrfVersion vrfcommon.Version) (*big.Int, error) {
- var (
- reservedEther string
- query string
- )
+func (lsn *listenerV2) MaybeSubtractReservedEth(ctx context.Context, startBalance *big.Int, chainID *big.Int, subID *big.Int, vrfVersion vrfcommon.Version) (*big.Int, error) {
+ var metaField string
if vrfVersion == vrfcommon.V2Plus {
- query = V2PlusReservedEthQuery
+ metaField = txMetaGlobalSubId
} else if vrfVersion == vrfcommon.V2 {
// native payment is not supported for v2, so returning 0 reserved ETH
return big.NewInt(0), nil
} else {
return nil, errors.Errorf("unsupported vrf version %s", vrfVersion)
}
- err := q.Get(&reservedEther, query, chainID, subID.String())
+ txes, err := lsn.chain.TxManager().FindTxesByMetaFieldAndStates(ctx, metaField, subID.String(), reserveEthLinkQueryStates, chainID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
- return nil, errors.Wrap(err, "getting reserved ether")
+ return nil, errors.Wrap(err, "TXM FindTxesByMetaFieldAndStates failed")
}
- if reservedEther != "" {
- reservedEtherInt, success := big.NewInt(0).SetString(reservedEther, 10)
- if !success {
- return nil, fmt.Errorf("converting reserved ether %s", reservedEther)
+ reservedEthSum := big.NewInt(0)
+ // Aggregate non-null MaxEth from all txes returned
+ for _, tx := range txes {
+ var meta *txmgrtypes.TxMeta[common.Address, common.Hash]
+ meta, err = tx.GetMeta()
+ if err != nil {
+ return nil, errors.Wrap(err, "GetMeta for Tx failed")
}
+ if meta != nil && meta.MaxEth != nil {
+ txMaxEth, success := new(big.Int).SetString(*meta.MaxEth, 10)
+ if !success {
+ return nil, fmt.Errorf("converting reserved ETH %s", *meta.MaxEth)
+ }
- return new(big.Int).Sub(startBalance, reservedEtherInt), nil
+ reservedEthSum.Add(reservedEthSum, txMaxEth)
+ }
}
if startBalance != nil {
- return new(big.Int).Set(startBalance), nil
+ return new(big.Int).Sub(startBalance, reservedEthSum), nil
}
return big.NewInt(0), nil
}
@@ -812,14 +844,14 @@ func (lsn *listenerV2) processRequestsPerSubBatch(
subIsActive bool,
) map[string]struct{} {
var processed = make(map[string]struct{})
- startBalanceNoReserveLink, err := MaybeSubtractReservedLink(
- lsn.q, startLinkBalance, lsn.chainID.Uint64(), subID, lsn.coordinator.Version())
+ startBalanceNoReserveLink, err := lsn.MaybeSubtractReservedLink(
+ ctx, startLinkBalance, lsn.chainID, subID, lsn.coordinator.Version())
if err != nil {
lsn.l.Errorw("Couldn't get reserved LINK for subscription", "sub", reqs[0].req.SubID(), "err", err)
return processed
}
- startBalanceNoReserveEth, err := MaybeSubtractReservedEth(
- lsn.q, startEthBalance, lsn.chainID.Uint64(), subID, lsn.coordinator.Version())
+ startBalanceNoReserveEth, err := lsn.MaybeSubtractReservedEth(
+ ctx, startEthBalance, lsn.chainID, subID, lsn.coordinator.Version())
if err != nil {
lsn.l.Errorw("Couldn't get reserved ether for subscription", "sub", reqs[0].req.SubID(), "err", err)
return processed
@@ -883,7 +915,7 @@ func (lsn *listenerV2) enqueueForceFulfillment(
// fulfill the request through the VRF owner
err = lsn.q.Transaction(func(tx pg.Queryer) error {
- if err = lsn.logBroadcaster.MarkConsumed(p.req.lb, pg.WithQueryer(tx)); err != nil {
+ if err = lsn.chain.LogBroadcaster().MarkConsumed(p.req.lb, pg.WithQueryer(tx)); err != nil {
return err
}
@@ -901,7 +933,7 @@ func (lsn *listenerV2) enqueueForceFulfillment(
if err != nil {
return errors.Wrap(err, "abi pack VRFOwner.fulfillRandomWords")
}
- estimateGasLimit, err := lsn.ethClient.EstimateGas(ctx, ethereum.CallMsg{
+ estimateGasLimit, err := lsn.chain.Client().EstimateGas(ctx, ethereum.CallMsg{
From: fromAddress,
To: &vrfOwnerAddressSpec,
Data: txData,
@@ -919,7 +951,7 @@ func (lsn *listenerV2) enqueueForceFulfillment(
requestID := common.BytesToHash(p.req.req.RequestID().Bytes())
subID := p.req.req.SubID()
requestTxHash := p.req.req.Raw().TxHash
- etx, err = lsn.txm.CreateTransaction(ctx, txmgr.TxRequest{
+ etx, err = lsn.chain.TxManager().CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: fromAddress,
ToAddress: lsn.vrfOwner.Address(),
EncodedPayload: txData,
@@ -943,7 +975,7 @@ func (lsn *listenerV2) enqueueForceFulfillment(
func (lsn *listenerV2) isConsumerValidAfterFinalityDepthElapsed(ctx context.Context, req pendingRequest) bool {
latestHead := lsn.getLatestHead()
if latestHead-req.req.Raw().BlockNumber > uint64(lsn.cfg.FinalityDepth()) {
- code, err := lsn.ethClient.CodeAt(ctx, req.req.Sender(), big.NewInt(int64(latestHead)))
+ code, err := lsn.chain.Client().CodeAt(ctx, req.req.Sender(), big.NewInt(int64(latestHead)))
if err != nil {
lsn.l.Warnw("Failed to fetch contract code", "err", err)
return true // error fetching code, give the benefit of doubt to the consumer
@@ -1103,7 +1135,7 @@ func (lsn *listenerV2) processRequestsPerSubHelper(
if err = lsn.pipelineRunner.InsertFinishedRun(p.run, true, pg.WithQueryer(tx)); err != nil {
return err
}
- if err = lsn.logBroadcaster.MarkConsumed(p.req.lb, pg.WithQueryer(tx)); err != nil {
+ if err = lsn.chain.LogBroadcaster().MarkConsumed(p.req.lb, pg.WithQueryer(tx)); err != nil {
return err
}
@@ -1126,7 +1158,7 @@ func (lsn *listenerV2) processRequestsPerSubHelper(
requestID := common.BytesToHash(p.req.req.RequestID().Bytes())
coordinatorAddress := lsn.coordinator.Address()
requestTxHash := p.req.req.Raw().TxHash
- transaction, err = lsn.txm.CreateTransaction(ctx, txmgr.TxRequest{
+ transaction, err = lsn.chain.TxManager().CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: fromAddress,
ToAddress: lsn.coordinator.Address(),
EncodedPayload: hexutil.MustDecode(p.payload),
@@ -1185,15 +1217,15 @@ func (lsn *listenerV2) processRequestsPerSub(
}
var processed = make(map[string]struct{})
- chainId := lsn.ethClient.ConfiguredChainID()
- startBalanceNoReserveLink, err := MaybeSubtractReservedLink(
- lsn.q, startLinkBalance, chainId.Uint64(), subID, lsn.coordinator.Version())
+ chainId := lsn.chain.Client().ConfiguredChainID()
+ startBalanceNoReserveLink, err := lsn.MaybeSubtractReservedLink(
+ ctx, startLinkBalance, chainId, subID, lsn.coordinator.Version())
if err != nil {
lsn.l.Errorw("Couldn't get reserved LINK for subscription", "sub", reqs[0].req.SubID(), "err", err)
return processed
}
- startBalanceNoReserveEth, err := MaybeSubtractReservedEth(
- lsn.q, startEthBalance, lsn.chainID.Uint64(), subID, lsn.coordinator.Version())
+ startBalanceNoReserveEth, err := lsn.MaybeSubtractReservedEth(
+ ctx, startEthBalance, lsn.chainID, subID, lsn.coordinator.Version())
if err != nil {
lsn.l.Errorw("Couldn't get reserved ETH for subscription", "sub", reqs[0].req.SubID(), "err", err)
return processed
@@ -1299,7 +1331,7 @@ func (lsn *listenerV2) checkReqsFulfilled(ctx context.Context, l logger.Logger,
}
}
- err := lsn.ethClient.BatchCallContext(ctx, calls)
+ err := lsn.chain.Client().BatchCallContext(ctx, calls)
if err != nil {
return fulfilled, errors.Wrap(err, "making batch call")
}
@@ -1582,7 +1614,7 @@ func (lsn *listenerV2) getConfirmedAt(req RandomWordsRequested, nodeMinConfs uin
func (lsn *listenerV2) handleLog(lb log.Broadcast, minConfs uint32) {
if v, ok := lb.DecodedLog().(*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled); ok {
lsn.l.Debugw("Received fulfilled log", "reqID", v.RequestId, "success", v.Success)
- consumed, err := lsn.logBroadcaster.WasAlreadyConsumed(lb)
+ consumed, err := lsn.chain.LogBroadcaster().WasAlreadyConsumed(lb)
if err != nil {
lsn.l.Errorw(CouldNotDetermineIfLogConsumedMsg, "err", err, "txHash", lb.RawLog().TxHash)
return
@@ -1602,7 +1634,7 @@ func (lsn *listenerV2) handleLog(lb log.Broadcast, minConfs uint32) {
if v, ok := lb.DecodedLog().(*vrf_coordinator_v2plus_interface.IVRFCoordinatorV2PlusInternalRandomWordsFulfilled); ok {
lsn.l.Debugw("Received fulfilled log", "reqID", v.RequestId, "success", v.Success)
- consumed, err := lsn.logBroadcaster.WasAlreadyConsumed(lb)
+ consumed, err := lsn.chain.LogBroadcaster().WasAlreadyConsumed(lb)
if err != nil {
lsn.l.Errorw(CouldNotDetermineIfLogConsumedMsg, "err", err, "txHash", lb.RawLog().TxHash)
return
@@ -1623,7 +1655,7 @@ func (lsn *listenerV2) handleLog(lb log.Broadcast, minConfs uint32) {
req, err := lsn.coordinator.ParseRandomWordsRequested(lb.RawLog())
if err != nil {
lsn.l.Errorw("Failed to parse log", "err", err, "txHash", lb.RawLog().TxHash)
- consumed, err := lsn.logBroadcaster.WasAlreadyConsumed(lb)
+ consumed, err := lsn.chain.LogBroadcaster().WasAlreadyConsumed(lb)
if err != nil {
lsn.l.Errorw(CouldNotDetermineIfLogConsumedMsg, "err", err, "txHash", lb.RawLog().TxHash)
return
@@ -1648,7 +1680,7 @@ func (lsn *listenerV2) handleLog(lb log.Broadcast, minConfs uint32) {
}
func (lsn *listenerV2) markLogAsConsumed(lb log.Broadcast) {
- err := lsn.logBroadcaster.MarkConsumed(lb)
+ err := lsn.chain.LogBroadcaster().MarkConsumed(lb)
lsn.l.ErrorIf(err, fmt.Sprintf("Unable to mark log %v as consumed", lb.String()))
}
diff --git a/core/services/vrf/v2/listener_v2_helpers_test.go b/core/services/vrf/v2/listener_v2_helpers_test.go
index 8ba900bdc3..fc34a115b1 100644
--- a/core/services/vrf/v2/listener_v2_helpers_test.go
+++ b/core/services/vrf/v2/listener_v2_helpers_test.go
@@ -7,7 +7,9 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
v2 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2"
+ "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
)
func TestListener_EstimateFeeJuels(t *testing.T) {
@@ -29,3 +31,23 @@ func TestListener_EstimateFeeJuels(t *testing.T) {
require.Nil(t, actual)
require.Error(t, err)
}
+
+func Test_TxListDeduper(t *testing.T) {
+ tx1 := &txmgr.Tx{
+ ID: 1,
+ Value: *big.NewInt(0),
+ ChainID: big.NewInt(0),
+ }
+ tx2 := &txmgr.Tx{
+ ID: 1,
+ Value: *big.NewInt(1),
+ ChainID: big.NewInt(0),
+ }
+ tx3 := &txmgr.Tx{
+ ID: 2,
+ Value: *big.NewInt(1),
+ ChainID: big.NewInt(0),
+ }
+ txList := vrfcommon.DedupeTxList([]*txmgr.Tx{tx1, tx2, tx3})
+ require.Equal(t, len(txList), 2)
+}
diff --git a/core/services/vrf/v2/listener_v2_test.go b/core/services/vrf/v2/listener_v2_test.go
index 70d5b8154e..17615feb63 100644
--- a/core/services/vrf/v2/listener_v2_test.go
+++ b/core/services/vrf/v2/listener_v2_test.go
@@ -1,6 +1,7 @@
package v2
import (
+ "encoding/json"
"math/big"
"sync"
"testing"
@@ -13,39 +14,44 @@ import (
"github.com/stretchr/testify/require"
"github.com/theodesp/go-heaps/pairing"
- "github.com/smartcontractkit/sqlx"
-
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
+ evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
+ evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
+ clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
-const (
- addEthTxQuery = `INSERT INTO evm.txes (from_address, to_address, encoded_payload, value, gas_limit, state, created_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id)
- VALUES (
- $1, $2, $3, $4, $5, $6, NOW(), $7, $8, $9, $10, $11
- )
- RETURNING "txes".*`
-
- addConfirmedEthTxQuery = `INSERT INTO evm.txes (nonce, broadcast_at, initial_broadcast_at, error, from_address, to_address, encoded_payload, value, gas_limit, state, created_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id)
- VALUES (
- $1, NOW(), NOW(), NULL, $2, $3, $4, $5, $6, 'confirmed', NOW(), $7, $8, $9, $10, $11
- )
- RETURNING "txes".*`
-)
+func makeTestTxm(t *testing.T, txStore txmgr.TestEvmTxStore, keyStore keystore.Master) txmgrcommon.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] {
+ _, _, evmConfig := txmgr.MakeTestConfigs(t)
+ ec := evmtest.NewEthClientMockWithDefaultChain(t)
+ txmConfig := txmgr.NewEvmTxmConfig(evmConfig)
+ txm := txmgr.NewEvmTxm(ec.ConfiguredChainID(), txmConfig, evmConfig.Transactions(), keyStore.Eth(), logger.TestLogger(t), nil, nil,
+ nil, txStore, nil, nil, nil, nil)
+
+ return txm
+}
+
+func MakeTestListenerV2(chain evm.Chain) *listenerV2 {
+ return &listenerV2{chainID: chain.Client().ConfiguredChainID(), chain: chain}
+}
func txMetaSubIDs(t *testing.T, vrfVersion vrfcommon.Version, subID *big.Int) (*uint64, *string) {
var (
@@ -62,89 +68,118 @@ func txMetaSubIDs(t *testing.T, vrfVersion vrfcommon.Version, subID *big.Int) (*
return txMetaSubID, txMetaGlobalSubID
}
-func addEthTx(t *testing.T, db *sqlx.DB, from common.Address, state txmgrtypes.TxState, maxLink string, subID *big.Int, reqTxHash common.Hash, vrfVersion vrfcommon.Version) {
+func addEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, from common.Address, state txmgrtypes.TxState, maxLink string, subID *big.Int, reqTxHash common.Hash, vrfVersion vrfcommon.Version) {
txMetaSubID, txMetaGlobalSubID := txMetaSubIDs(t, vrfVersion, subID)
- _, err := db.Exec(addEthTxQuery,
- from, // from
- from, // to
- []byte(`blah`), // payload
- 0, // value
- 0, // limit
- state,
- txmgr.TxMeta{
- MaxLink: &maxLink,
- SubID: txMetaSubID,
- GlobalSubID: txMetaGlobalSubID,
- RequestTxHash: &reqTxHash,
- },
- uuid.NullUUID{},
- 1337,
- 0, // confs
- nil)
+ b, err := json.Marshal(txmgr.TxMeta{
+ MaxLink: &maxLink,
+ SubID: txMetaSubID,
+ GlobalSubID: txMetaGlobalSubID,
+ RequestTxHash: &reqTxHash,
+ })
+ require.NoError(t, err)
+ meta := datatypes.JSON(b)
+ tx := &txmgr.Tx{
+ FromAddress: from,
+ ToAddress: from,
+ EncodedPayload: []byte(`blah`),
+ Value: *big.NewInt(0),
+ FeeLimit: 0,
+ State: state,
+ Meta: &meta,
+ Subject: uuid.NullUUID{},
+ ChainID: testutils.SimulatedChainID,
+ MinConfirmations: clnull.Uint32{Uint32: 0},
+ PipelineTaskRunID: uuid.NullUUID{},
+ }
+ err = txStore.InsertTx(tx)
require.NoError(t, err)
}
-func addConfirmedEthTx(t *testing.T, db *sqlx.DB, from common.Address, maxLink string, subID *big.Int, nonce uint64, vrfVersion vrfcommon.Version) {
+func addConfirmedEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, from common.Address, maxLink string, subID *big.Int, nonce evmtypes.Nonce, vrfVersion vrfcommon.Version) {
txMetaSubID, txMetaGlobalSubID := txMetaSubIDs(t, vrfVersion, subID)
- _, err := db.Exec(addConfirmedEthTxQuery,
- nonce, // nonce
- from, // from
- from, // to
- []byte(`blah`), // payload
- 0, // value
- 0, // limit
- txmgr.TxMeta{
- MaxLink: &maxLink,
- SubID: txMetaSubID,
- GlobalSubID: txMetaGlobalSubID,
- },
- uuid.NullUUID{},
- 1337,
- 0, // confs
- nil)
+ b, err := json.Marshal(txmgr.TxMeta{
+ MaxLink: &maxLink,
+ SubID: txMetaSubID,
+ GlobalSubID: txMetaGlobalSubID,
+ })
+ require.NoError(t, err)
+ meta := datatypes.JSON(b)
+ now := time.Now()
+
+ tx := &txmgr.Tx{
+ Sequence: &nonce,
+ FromAddress: from,
+ ToAddress: from,
+ EncodedPayload: []byte(`blah`),
+ Value: *big.NewInt(0),
+ FeeLimit: 0,
+ State: txmgrcommon.TxConfirmed,
+ Meta: &meta,
+ Subject: uuid.NullUUID{},
+ ChainID: testutils.SimulatedChainID,
+ MinConfirmations: clnull.Uint32{Uint32: 0},
+ PipelineTaskRunID: uuid.NullUUID{},
+ BroadcastAt: &now,
+ InitialBroadcastAt: &now,
+ }
+ err = txStore.InsertTx(tx)
require.NoError(t, err)
}
-func addEthTxNativePayment(t *testing.T, db *sqlx.DB, from common.Address, state txmgrtypes.TxState, maxNative string, subID *big.Int, reqTxHash common.Hash, vrfVersion vrfcommon.Version) {
+func addEthTxNativePayment(t *testing.T, txStore txmgr.TestEvmTxStore, from common.Address, state txmgrtypes.TxState, maxNative string, subID *big.Int, reqTxHash common.Hash, vrfVersion vrfcommon.Version) {
txMetaSubID, txMetaGlobalSubID := txMetaSubIDs(t, vrfVersion, subID)
- _, err := db.Exec(addEthTxQuery,
- from, // from
- from, // to
- []byte(`blah`), // payload
- 0, // value
- 0, // limit
- state,
- txmgr.TxMeta{
- MaxEth: &maxNative,
- SubID: txMetaSubID,
- GlobalSubID: txMetaGlobalSubID,
- RequestTxHash: &reqTxHash,
- },
- uuid.NullUUID{},
- 1337,
- 0, // confs
- nil)
+ b, err := json.Marshal(txmgr.TxMeta{
+ MaxEth: &maxNative,
+ SubID: txMetaSubID,
+ GlobalSubID: txMetaGlobalSubID,
+ RequestTxHash: &reqTxHash,
+ })
+ require.NoError(t, err)
+ meta := datatypes.JSON(b)
+ tx := &txmgr.Tx{
+ FromAddress: from,
+ ToAddress: from,
+ EncodedPayload: []byte(`blah`),
+ Value: *big.NewInt(0),
+ FeeLimit: 0,
+ State: state,
+ Meta: &meta,
+ Subject: uuid.NullUUID{},
+ ChainID: testutils.SimulatedChainID,
+ MinConfirmations: clnull.Uint32{Uint32: 0},
+ PipelineTaskRunID: uuid.NullUUID{},
+ }
+ err = txStore.InsertTx(tx)
require.NoError(t, err)
}
-func addConfirmedEthTxNativePayment(t *testing.T, db *sqlx.DB, from common.Address, maxNative string, subID *big.Int, nonce uint64, vrfVersion vrfcommon.Version) {
+func addConfirmedEthTxNativePayment(t *testing.T, txStore txmgr.TestEvmTxStore, from common.Address, maxNative string, subID *big.Int, nonce evmtypes.Nonce, vrfVersion vrfcommon.Version) {
txMetaSubID, txMetaGlobalSubID := txMetaSubIDs(t, vrfVersion, subID)
- _, err := db.Exec(addConfirmedEthTxQuery,
- nonce, // nonce
- from, // from
- from, // to
- []byte(`blah`), // payload
- 0, // value
- 0, // limit
- txmgr.TxMeta{
- MaxEth: &maxNative,
- SubID: txMetaSubID,
- GlobalSubID: txMetaGlobalSubID,
- },
- uuid.NullUUID{},
- 1337,
- 0, // confs
- nil)
+ b, err := json.Marshal(txmgr.TxMeta{
+ MaxEth: &maxNative,
+ SubID: txMetaSubID,
+ GlobalSubID: txMetaGlobalSubID,
+ })
+ require.NoError(t, err)
+ meta := datatypes.JSON(b)
+ now := time.Now()
+ tx := &txmgr.Tx{
+ Sequence: &nonce,
+ FromAddress: from,
+ ToAddress: from,
+ EncodedPayload: []byte(`blah`),
+ Value: *big.NewInt(0),
+ FeeLimit: 0,
+ State: txmgrcommon.TxConfirmed,
+ Meta: &meta,
+ Subject: uuid.NullUUID{},
+ ChainID: testutils.SimulatedChainID,
+ MinConfirmations: clnull.Uint32{Uint32: 0},
+ PipelineTaskRunID: uuid.NullUUID{},
+ BroadcastAt: &now,
+ InitialBroadcastAt: &now,
+ }
+ err = txStore.InsertTx(tx)
require.NoError(t, err)
}
@@ -152,57 +187,72 @@ func testMaybeSubtractReservedLink(t *testing.T, vrfVersion vrfcommon.Version) {
db := pgtest.NewSqlxDB(t)
lggr := logger.TestLogger(t)
cfg := pgtest.NewQConfig(false)
- q := pg.NewQ(db, lggr, cfg)
ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg)
require.NoError(t, ks.Unlock("blah"))
- chainID := uint64(1337)
- k, err := ks.Eth().Create(big.NewInt(int64(chainID)))
+ chainID := testutils.SimulatedChainID
+ k, err := ks.Eth().Create(chainID)
require.NoError(t, err)
subID := new(big.Int).SetUint64(1)
reqTxHash := common.HexToHash("0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8")
+ j, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{
+ RequestedConfsDelay: 10,
+ }).Toml())
+ require.NoError(t, err)
+ txstore := txmgr.NewTxStore(db, lggr, cfg)
+ txm := makeTestTxm(t, txstore, ks)
+ chain := evmmocks.NewChain(t)
+ chain.On("TxManager").Return(txm)
+ listener := &listenerV2{
+ respCount: map[string]uint64{},
+ job: j,
+ chain: chain,
+ }
+
+ ctx := testutils.Context(t)
+
// Insert an unstarted eth tx with link metadata
- addEthTx(t, db, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
- start, err := MaybeSubtractReservedLink(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTx(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
+ start, err := listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
assert.Equal(t, "90000", start.String())
// A confirmed tx should not affect the starting balance
- addConfirmedEthTx(t, db, k.Address, "10000", subID, 1, vrfVersion)
- start, err = MaybeSubtractReservedLink(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addConfirmedEthTx(t, txstore, k.Address, "10000", subID, 1, vrfVersion)
+ start, err = listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
assert.Equal(t, "90000", start.String())
// An unconfirmed tx _should_ affect the starting balance.
- addEthTx(t, db, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedLink(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTx(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
assert.Equal(t, "80000", start.String())
// One subscriber's reserved link should not affect other subscribers prospective balance.
otherSubID := new(big.Int).SetUint64(2)
require.NoError(t, err)
- addEthTx(t, db, k.Address, txmgrcommon.TxUnstarted, "10000", otherSubID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedLink(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTx(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", otherSubID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
require.Equal(t, "80000", start.String())
// One key's data should not affect other keys' data in the case of different subscribers.
- k2, err := ks.Eth().Create(big.NewInt(1337))
+ k2, err := ks.Eth().Create(testutils.SimulatedChainID)
require.NoError(t, err)
anotherSubID := new(big.Int).SetUint64(3)
- addEthTx(t, db, k2.Address, txmgrcommon.TxUnstarted, "10000", anotherSubID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedLink(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTx(t, txstore, k2.Address, txmgrcommon.TxUnstarted, "10000", anotherSubID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
require.Equal(t, "80000", start.String())
// A subscriber's balance is deducted with the link reserved across multiple keys,
// i.e, gas lanes.
- addEthTx(t, db, k2.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedLink(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTx(t, txstore, k2.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
require.Equal(t, "70000", start.String())
}
@@ -219,57 +269,73 @@ func testMaybeSubtractReservedNative(t *testing.T, vrfVersion vrfcommon.Version)
db := pgtest.NewSqlxDB(t)
lggr := logger.TestLogger(t)
cfg := pgtest.NewQConfig(false)
- q := pg.NewQ(db, lggr, cfg)
ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg)
require.NoError(t, ks.Unlock("blah"))
- chainID := uint64(1337)
- k, err := ks.Eth().Create(big.NewInt(int64(chainID)))
+ chainID := testutils.SimulatedChainID
+ k, err := ks.Eth().Create(chainID)
require.NoError(t, err)
subID := new(big.Int).SetUint64(1)
reqTxHash := common.HexToHash("0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8")
+ j, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{
+ RequestedConfsDelay: 10,
+ }).Toml())
+ require.NoError(t, err)
+ txstore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg)
+ txm := makeTestTxm(t, txstore, ks)
+ require.NoError(t, err)
+ chain := evmmocks.NewChain(t)
+ chain.On("TxManager").Return(txm)
+ listener := &listenerV2{
+ respCount: map[string]uint64{},
+ job: j,
+ chain: chain,
+ }
+
+ ctx := testutils.Context(t)
+
// Insert an unstarted eth tx with native metadata
- addEthTxNativePayment(t, db, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
- start, err := MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTxNativePayment(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
+ start, err := listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
assert.Equal(t, "90000", start.String())
// A confirmed tx should not affect the starting balance
- addConfirmedEthTxNativePayment(t, db, k.Address, "10000", subID, 1, vrfVersion)
- start, err = MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addConfirmedEthTxNativePayment(t, txstore, k.Address, "10000", subID, 1, vrfVersion)
+ start, err = listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
assert.Equal(t, "90000", start.String())
// An unconfirmed tx _should_ affect the starting balance.
- addEthTxNativePayment(t, db, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTxNativePayment(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
assert.Equal(t, "80000", start.String())
// One subscriber's reserved native should not affect other subscribers prospective balance.
otherSubID := new(big.Int).SetUint64(2)
require.NoError(t, err)
- addEthTxNativePayment(t, db, k.Address, txmgrcommon.TxUnstarted, "10000", otherSubID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTxNativePayment(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", otherSubID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
require.Equal(t, "80000", start.String())
// One key's data should not affect other keys' data in the case of different subscribers.
- k2, err := ks.Eth().Create(big.NewInt(1337))
+ k2, err := ks.Eth().Create(testutils.SimulatedChainID)
require.NoError(t, err)
anotherSubID := new(big.Int).SetUint64(3)
- addEthTxNativePayment(t, db, k2.Address, txmgrcommon.TxUnstarted, "10000", anotherSubID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTxNativePayment(t, txstore, k2.Address, txmgrcommon.TxUnstarted, "10000", anotherSubID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
require.Equal(t, "80000", start.String())
// A subscriber's balance is deducted with the native reserved across multiple keys,
// i.e, gas lanes.
- addEthTxNativePayment(t, db, k2.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
- start, err = MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfVersion)
+ addEthTxNativePayment(t, txstore, k2.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion)
+ start, err = listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion)
require.NoError(t, err)
require.Equal(t, "70000", start.String())
}
@@ -282,13 +348,26 @@ func TestMaybeSubtractReservedNativeV2(t *testing.T) {
db := pgtest.NewSqlxDB(t)
lggr := logger.TestLogger(t)
cfg := pgtest.NewQConfig(false)
- q := pg.NewQ(db, lggr, cfg)
ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg)
require.NoError(t, ks.Unlock("blah"))
- chainID := uint64(1337)
+ chainID := testutils.SimulatedChainID
subID := new(big.Int).SetUint64(1)
+
+ j, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{
+ RequestedConfsDelay: 10,
+ }).Toml())
+ require.NoError(t, err)
+ txstore := txmgr.NewTxStore(db, logger.TestLogger(t), cfg)
+ txm := makeTestTxm(t, txstore, ks)
+ chain := evmmocks.NewChain(t)
+ chain.On("TxManager").Return(txm).Maybe()
+ listener := &listenerV2{
+ respCount: map[string]uint64{},
+ job: j,
+ chain: chain,
+ }
// returns error because native payment is not supported for V2
- start, err := MaybeSubtractReservedEth(q, big.NewInt(100_000), chainID, subID, vrfcommon.V2)
+ start, err := listener.MaybeSubtractReservedEth(testutils.Context(t), big.NewInt(100_000), chainID, subID, vrfcommon.V2)
require.NoError(t, err)
assert.Equal(t, big.NewInt(0), start)
}
@@ -445,12 +524,14 @@ func TestListener_handleLog(tt *testing.T) {
lb.On("WasAlreadyConsumed", log).Return(false, nil).Once()
lb.On("MarkConsumed", log).Return(nil).Once()
defer lb.AssertExpectations(t)
+ chain := evmmocks.NewChain(t)
+ chain.On("LogBroadcaster").Return(lb)
listener := &listenerV2{
respCount: map[string]uint64{},
job: j,
blockNumberToReqID: pairing.New(),
latestHeadMu: sync.RWMutex{},
- logBroadcaster: lb,
+ chain: chain,
l: logger.TestLogger(t),
}
listener.handleLog(log, minConfs)
@@ -476,12 +557,14 @@ func TestListener_handleLog(tt *testing.T) {
lb.On("WasAlreadyConsumed", log).Return(false, nil).Once()
lb.On("MarkConsumed", log).Return(nil).Once()
defer lb.AssertExpectations(t)
+ chain := evmmocks.NewChain(t)
+ chain.On("LogBroadcaster").Return(lb)
listener := &listenerV2{
respCount: map[string]uint64{},
job: j,
blockNumberToReqID: pairing.New(),
latestHeadMu: sync.RWMutex{},
- logBroadcaster: lb,
+ chain: chain,
l: logger.TestLogger(t),
}
listener.handleLog(log, minConfs)
diff --git a/core/services/vrf/v2/listener_v2_types.go b/core/services/vrf/v2/listener_v2_types.go
index e0596abcd1..5ad44c31a8 100644
--- a/core/services/vrf/v2/listener_v2_types.go
+++ b/core/services/vrf/v2/listener_v2_types.go
@@ -170,7 +170,7 @@ func (lsn *listenerV2) processBatch(
return errors.Wrap(err, "inserting finished pipeline runs")
}
- if err = lsn.logBroadcaster.MarkManyConsumed(batch.lbs, pg.WithQueryer(tx)); err != nil {
+ if err = lsn.chain.LogBroadcaster().MarkManyConsumed(batch.lbs, pg.WithQueryer(tx)); err != nil {
return errors.Wrap(err, "mark logs consumed")
}
@@ -181,7 +181,7 @@ func (lsn *listenerV2) processBatch(
for _, reqID := range batch.reqIDs {
reqIDHashes = append(reqIDHashes, common.BytesToHash(reqID.Bytes()))
}
- ethTX, err = lsn.txm.CreateTransaction(ctx, txmgr.TxRequest{
+ ethTX, err = lsn.chain.TxManager().CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: fromAddress,
ToAddress: lsn.batchCoordinator.Address(),
EncodedPayload: payload,
@@ -234,7 +234,7 @@ func (lsn *listenerV2) getUnconsumed(l logger.Logger, reqs []pendingRequest) (un
// This check to see if the log was consumed needs to be in the same
// goroutine as the mark consumed to avoid processing duplicates.
- consumed, err := lsn.logBroadcaster.WasAlreadyConsumed(req.lb)
+ consumed, err := lsn.chain.LogBroadcaster().WasAlreadyConsumed(req.lb)
if err != nil {
// Do not process for now, retry on next iteration.
l.Errorw("Could not determine if log was already consumed",
diff --git a/core/services/vrf/vrfcommon/utils.go b/core/services/vrf/vrfcommon/utils.go
new file mode 100644
index 0000000000..f9cc012d8f
--- /dev/null
+++ b/core/services/vrf/vrfcommon/utils.go
@@ -0,0 +1,78 @@
+package vrfcommon
+
+import (
+ "context"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/pkg/errors"
+
+ txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
+ txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
+)
+
+type RespCountEntry struct {
+ RequestID string
+ Count int
+}
+
+func GetRespCounts(ctx context.Context, txm txmgr.TxManager, chainID *big.Int, confirmedBlockNum int64) (
+ []RespCountEntry,
+ error,
+) {
+ counts := []RespCountEntry{}
+ metaField := "RequestID"
+ states := []txmgrtypes.TxState{txmgrcommon.TxUnconfirmed, txmgrcommon.TxUnstarted, txmgrcommon.TxInProgress}
+ // Search for txes with a non-null meta field in the provided states
+ unconfirmedTxes, err := txm.FindTxesWithMetaFieldByStates(ctx, metaField, states, chainID)
+ if err != nil {
+ return nil, errors.Wrap(err, "getRespCounts failed due to error in FindTxesWithMetaFieldByStates")
+ }
+ // Fetch completed transactions only as far back as the given confirmedBlockNum. This avoids
+ // a table scan of the whole table, which could be large if it is unpruned.
+ var confirmedTxes []*txmgr.Tx
+ confirmedTxes, err = txm.FindTxesWithMetaFieldByReceiptBlockNum(ctx, metaField, confirmedBlockNum, chainID)
+ if err != nil {
+ return nil, errors.Wrap(err, "getRespCounts failed due to error in FindTxesWithMetaFieldByReceiptBlockNum")
+ }
+ txes := DedupeTxList(append(unconfirmedTxes, confirmedTxes...))
+ respCountMap := make(map[string]int)
+ // Consolidate the number of txes for each meta RequestID
+ for _, tx := range txes {
+ var meta *txmgrtypes.TxMeta[common.Address, common.Hash]
+ meta, err = tx.GetMeta()
+ if err != nil {
+ return nil, errors.Wrap(err, "getRespCounts failed parsing tx meta field")
+ }
+ if meta != nil && meta.RequestID != nil {
+ requestId := meta.RequestID.String()
+ if _, exists := respCountMap[requestId]; !exists {
+ respCountMap[requestId] = 0
+ }
+ respCountMap[requestId]++
+ }
+ }
+
+ // Parse response count map into output
+ for key, value := range respCountMap {
+ respCountEntry := RespCountEntry{
+ RequestID: key,
+ Count: value,
+ }
+ counts = append(counts, respCountEntry)
+ }
+ return counts, nil
+}
+
+func DedupeTxList(txes []*txmgr.Tx) []*txmgr.Tx {
+ txIdMap := make(map[string]bool)
+ dedupedTxes := []*txmgr.Tx{}
+ for _, tx := range txes {
+ if _, found := txIdMap[tx.GetID()]; !found {
+ txIdMap[tx.GetID()] = true
+ dedupedTxes = append(dedupedTxes, tx)
+ }
+ }
+ return dedupedTxes
+}
diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go
index fc2e8d7a30..0bd947bbce 100644
--- a/core/web/jobs_controller_test.go
+++ b/core/web/jobs_controller_test.go
@@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"io"
+ "math/big"
"net/http"
"net/url"
"strconv"
@@ -19,10 +20,12 @@ import (
p2ppeer "github.com/libp2p/go-libp2p-core/peer"
"github.com/pelletier/go-toml"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/sqlx"
+ evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
@@ -658,7 +661,8 @@ func setupJobsControllerTests(t *testing.T) (ta *cltest.TestApplication, cc clte
c.P2P.V1.Enabled = ptr(true)
c.P2P.PeerID = &cltest.DefaultP2PPeerID
})
- app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey)
+ ec := setupEthClientForControllerTests(t)
+ app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey, ec)
require.NoError(t, app.Start(testutils.Context(t)))
client := app.NewHTTPClient(nil)
@@ -668,6 +672,14 @@ func setupJobsControllerTests(t *testing.T) (ta *cltest.TestApplication, cc clte
return app, client
}
+func setupEthClientForControllerTests(t *testing.T) *evmclimocks.Client {
+ ec := cltest.NewEthMocksWithStartupAssertions(t)
+ ec.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe()
+ ec.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(100), nil).Maybe()
+ ec.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Once().Return(big.NewInt(0), nil).Maybe()
+ return ec
+}
+
func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication, cltest.HTTPClientCleaner, job.Job, int32, job.Job, int32) {
cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.OCR.Enabled = ptr(true)
From 8b6f4899ef0a981b869d7deeed45e40de3193aa2 Mon Sep 17 00:00:00 2001
From: Tate
Date: Thu, 2 Nov 2023 15:40:18 -0600
Subject: [PATCH 063/327] E2E Metrics Missing Tag Suffix (#11163)
---
.github/workflows/integration-tests.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 445a027731..785c48da40 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -455,7 +455,7 @@ jobs:
with:
basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
- this-job-name: ETH Smoke Tests ${{ matrix.product.name }}
+ this-job-name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }}
test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
continue-on-error: true
- name: Keep action running to view traces
From 5cc88a82ec77b1d4f3f37b0255af778a056e7e5c Mon Sep 17 00:00:00 2001
From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com>
Date: Thu, 2 Nov 2023 19:43:54 -0400
Subject: [PATCH 064/327] Handle PR bodies correctly (#11165)
---
.github/workflows/operator-ui-cd.yml | 2 +-
operator_ui/check.sh | 15 ++++++++-------
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/operator-ui-cd.yml b/.github/workflows/operator-ui-cd.yml
index 54f423e6dc..bd589da728 100644
--- a/.github/workflows/operator-ui-cd.yml
+++ b/.github/workflows/operator-ui-cd.yml
@@ -39,7 +39,7 @@ jobs:
url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }}
- name: Open PR
- uses: peter-evans/create-pull-request@38e0b6e68b4c852a5500a94740f0e535e0d7ba54 # v4.2.4
+ uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
with:
title: Update Operator UI from ${{ steps.update.outputs.current_tag }} to ${{ steps.update.outputs.latest_tag }}
token: ${{ steps.get-gh-token.outputs.access-token }}
diff --git a/operator_ui/check.sh b/operator_ui/check.sh
index 614afd4b07..9e73821808 100755
--- a/operator_ui/check.sh
+++ b/operator_ui/check.sh
@@ -26,12 +26,13 @@ else
echo "$latest_tag" >"$tag_file"
echo "Tag updated $current_tag -> $latest_tag"
if [ "$CI" ]; then
- echo "current_tag=$current_tag" >> $GITHUB_OUTPUT
- echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT
- # See https://github.com/peter-evans/create-pull-request/blob/main/docs/examples.md#setting-the-pull-request-body-from-a-file
- body="${body//'%'/'%25'}"
- body="${body//$'\n'/'%0A'}"
- body="${body//$'\r'/'%0D'}"
- echo "body=$body" >> $GITHUB_OUTPUT
+ echo "current_tag=$current_tag" >>$GITHUB_OUTPUT
+ echo "latest_tag=$latest_tag" >>$GITHUB_OUTPUT
+
+ # See https://github.com/orgs/community/discussions/26288#discussioncomment-3876281
+ delimiter="$(openssl rand -hex 8)"
+ echo "body<<${delimiter}" >>"${GITHUB_OUTPUT}"
+ echo "$body" >>"${GITHUB_OUTPUT}"
+ echo "${delimiter}" >>"${GITHUB_OUTPUT}"
fi
fi
From ed9dc15b98c2f0cbf105d0f1b5fd40cf7571998c Mon Sep 17 00:00:00 2001
From: Sri Kidambi <1702865+kidambisrinivas@users.noreply.github.com>
Date: Fri, 3 Nov 2023 10:39:34 +0000
Subject: [PATCH 065/327] fix: v2plus superscript (#11156)
---
.../testnet/v2plusscripts/super_scripts.go | 91 +++++++++++--------
1 file changed, 54 insertions(+), 37 deletions(-)
diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
index f805e7b74f..752e06bbb2 100644
--- a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
+++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
@@ -6,15 +6,16 @@ import (
"encoding/hex"
"flag"
"fmt"
+ "math/big"
+ "os"
+ "strings"
+
"github.com/smartcontractkit/chainlink/core/scripts/common/vrf/constants"
"github.com/smartcontractkit/chainlink/core/scripts/common/vrf/jobs"
"github.com/smartcontractkit/chainlink/core/scripts/common/vrf/model"
"github.com/smartcontractkit/chainlink/core/scripts/common/vrf/util"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface"
- "math/big"
- "os"
- "strings"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
@@ -467,12 +468,12 @@ func DeployUniverseViaCLI(e helpers.Environment) {
deployCmd := flag.NewFlagSet("deploy-universe", flag.ExitOnError)
// required flags
- linkAddress := *deployCmd.String("link-address", "", "address of link token")
- linkEthAddress := *deployCmd.String("link-eth-feed", "", "address of link eth feed")
- bhsContractAddressString := *deployCmd.String("bhs-address", "", "address of BHS contract")
- batchBHSAddressString := *deployCmd.String("batch-bhs-address", "", "address of Batch BHS contract")
- coordinatorAddressString := *deployCmd.String("coordinator-address", "", "address of VRF Coordinator contract")
- batchCoordinatorAddressString := *deployCmd.String("batch-coordinator-address", "", "address Batch VRF Coordinator contract")
+ linkAddress := deployCmd.String("link-address", "", "address of link token")
+ linkEthAddress := deployCmd.String("link-eth-feed", "", "address of link eth feed")
+ bhsContractAddressString := deployCmd.String("bhs-address", "", "address of BHS contract")
+ batchBHSAddressString := deployCmd.String("batch-bhs-address", "", "address of Batch BHS contract")
+ coordinatorAddressString := deployCmd.String("coordinator-address", "", "address of VRF Coordinator contract")
+ batchCoordinatorAddressString := deployCmd.String("batch-coordinator-address", "", "address Batch VRF Coordinator contract")
subscriptionBalanceJuelsString := deployCmd.String("subscription-balance", "1e19", "amount to fund subscription with Link token (Juels)")
subscriptionBalanceNativeWeiString := deployCmd.String("subscription-balance-native", "1e18", "amount to fund subscription with native token (Wei)")
@@ -513,14 +514,14 @@ func DeployUniverseViaCLI(e helpers.Environment) {
SendingKeyFundingAmount: fundingAmount,
}
- bhsContractAddress := common.HexToAddress(bhsContractAddressString)
- batchBHSAddress := common.HexToAddress(batchBHSAddressString)
- coordinatorAddress := common.HexToAddress(coordinatorAddressString)
- batchCoordinatorAddress := common.HexToAddress(batchCoordinatorAddressString)
+ bhsContractAddress := common.HexToAddress(*bhsContractAddressString)
+ batchBHSAddress := common.HexToAddress(*batchBHSAddressString)
+ coordinatorAddress := common.HexToAddress(*coordinatorAddressString)
+ batchCoordinatorAddress := common.HexToAddress(*batchCoordinatorAddressString)
contractAddresses := model.ContractAddresses{
- LinkAddress: linkAddress,
- LinkEthAddress: linkEthAddress,
+ LinkAddress: *linkAddress,
+ LinkEthAddress: *linkEthAddress,
BhsContractAddress: bhsContractAddress,
BatchBHSAddress: batchBHSAddress,
CoordinatorAddress: coordinatorAddress,
@@ -563,28 +564,32 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
batchFulfillmentEnabled bool,
nodesMap map[string]model.Node,
) model.JobSpecs {
- // Put key in ECDSA format
- if strings.HasPrefix(*registerKeyUncompressedPubKey, "0x") {
- *registerKeyUncompressedPubKey = strings.Replace(*registerKeyUncompressedPubKey, "0x", "04", 1)
- }
+ var compressedPkHex string
+ var keyHash common.Hash
+ if len(*registerKeyUncompressedPubKey) > 0 {
+ // Put key in ECDSA format
+ if strings.HasPrefix(*registerKeyUncompressedPubKey, "0x") {
+ *registerKeyUncompressedPubKey = strings.Replace(*registerKeyUncompressedPubKey, "0x", "04", 1)
+ }
- // Generate compressed public key and key hash
- pubBytes, err := hex.DecodeString(*registerKeyUncompressedPubKey)
- helpers.PanicErr(err)
- pk, err := crypto.UnmarshalPubkey(pubBytes)
- helpers.PanicErr(err)
- var pkBytes []byte
- if big.NewInt(0).Mod(pk.Y, big.NewInt(2)).Uint64() != 0 {
- pkBytes = append(pk.X.Bytes(), 1)
- } else {
- pkBytes = append(pk.X.Bytes(), 0)
- }
- var newPK secp256k1.PublicKey
- copy(newPK[:], pkBytes)
+ // Generate compressed public key and key hash
+ pubBytes, err := hex.DecodeString(*registerKeyUncompressedPubKey)
+ helpers.PanicErr(err)
+ pk, err := crypto.UnmarshalPubkey(pubBytes)
+ helpers.PanicErr(err)
+ var pkBytes []byte
+ if big.NewInt(0).Mod(pk.Y, big.NewInt(2)).Uint64() != 0 {
+ pkBytes = append(pk.X.Bytes(), 1)
+ } else {
+ pkBytes = append(pk.X.Bytes(), 0)
+ }
+ var newPK secp256k1.PublicKey
+ copy(newPK[:], pkBytes)
- compressedPkHex := hexutil.Encode(pkBytes)
- keyHash, err := newPK.Hash()
- helpers.PanicErr(err)
+ compressedPkHex = hexutil.Encode(pkBytes)
+ keyHash, err = newPK.Hash()
+ helpers.PanicErr(err)
+ }
if len(contractAddresses.LinkAddress) == 0 {
fmt.Println("\nDeploying LINK Token...")
@@ -689,7 +694,13 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
e.ChainID, //evmChainID
strings.Join(util.MapToAddressArr(nodesMap[model.VRFPrimaryNodeName].SendingKeys), "\",\""), //fromAddresses
contractAddresses.CoordinatorAddress,
- nodesMap[model.VRFPrimaryNodeName].SendingKeys[0].Address,
+ func() string {
+ if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 {
+ return keys[0].Address
+ } else {
+ return common.HexToAddress("0x0").String()
+ }
+ }(),
contractAddresses.CoordinatorAddress,
contractAddresses.CoordinatorAddress,
)
@@ -704,7 +715,13 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
e.ChainID, //evmChainID
strings.Join(util.MapToAddressArr(nodesMap[model.VRFBackupNodeName].SendingKeys), "\",\""), //fromAddresses
contractAddresses.CoordinatorAddress,
- nodesMap[model.VRFPrimaryNodeName].SendingKeys[0],
+ func() string {
+ if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 {
+ return keys[0].Address
+ } else {
+ return common.HexToAddress("0x0").String()
+ }
+ }(),
contractAddresses.CoordinatorAddress,
contractAddresses.CoordinatorAddress,
)
From 4ea52f902f2ff1a0bef53e90c19ee46a3e01cf6c Mon Sep 17 00:00:00 2001
From: "app-token-issuer-infra-releng[bot]"
<120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com>
Date: Fri, 3 Nov 2023 11:17:17 +0000
Subject: [PATCH 066/327] Update Operator UI from v0.8.0-e10948a to
v0.8.0-2f868c3 (#11135)
Co-authored-by: github-merge-queue[bot]
---
operator_ui/TAG | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/operator_ui/TAG b/operator_ui/TAG
index e08ca07267..3b63cc3add 100644
--- a/operator_ui/TAG
+++ b/operator_ui/TAG
@@ -1 +1 @@
-v0.8.0-e10948a
+v0.8.0-2f868c3
From 4174f36b2727fbba5da81af591c24a16d396c802 Mon Sep 17 00:00:00 2001
From: Bartek Tofel
Date: Fri, 3 Nov 2023 12:23:13 +0100
Subject: [PATCH 067/327] added smoke test & load test for log poller (#11110)
* added smoke test & load test for log poller
* read CL nodes logs in parallel and compare them in parallel with EVM node logs (has a big impact on execution, when we emit 100k+ logs)
* add simple config validation
* add smoke tests for backup process and replay
* run replay test for 15m instead of 5m (for debuggin)
* do not use hardcoded postgres values
* added support for chaos experiments (pausing containers) + a smoke test that uses them
* streamline log poller tests
* remove backup poller test -- way to test it reliably in e2e tests
* don't skip replay test
* add go.work* to .gitignore
* add tests that can easier run in CI + some changes after testing with live testnets
* wait for LP to finalise endblock + on demand workflow in GH
* rename on demand workflow
* fix typo in workflow name
---
.github/log_poller_on_demand.yml | 66 +
.gitignore | 3 +-
core/chains/evm/logpoller/log_poller.go | 4 +-
integration-tests/client/chainlink.go | 20 +
integration-tests/client/chainlink_models.go | 14 +
.../contracts/contract_deployer.go | 20 +
.../contracts/contract_models.go | 10 +
integration-tests/contracts/test_contracts.go | 79 ++
integration-tests/docker/cmd/test_env.go | 1 +
integration-tests/docker/test_env/test_env.go | 1 +
.../docker/test_env/test_env_builder.go | 67 +-
integration-tests/go.mod | 8 +-
integration-tests/go.sum | 4 +-
integration-tests/load/log_poller/config.toml | 22 +
.../load/log_poller/log_poller_test.go | 24 +
.../reorg/log_poller_maybe_reorg_test.go | 42 +
integration-tests/smoke/automation_test.go | 3 +-
integration-tests/smoke/log_poller_test.go | 140 ++
.../universal/log_poller/config.go | 247 ++++
integration-tests/universal/log_poller/gun.go | 78 ++
.../universal/log_poller/helpers.go | 1136 +++++++++++++++++
.../universal/log_poller/scenarios.go | 498 ++++++++
22 files changed, 2460 insertions(+), 27 deletions(-)
create mode 100644 .github/log_poller_on_demand.yml
create mode 100644 integration-tests/contracts/test_contracts.go
create mode 100644 integration-tests/load/log_poller/config.toml
create mode 100644 integration-tests/load/log_poller/log_poller_test.go
create mode 100644 integration-tests/reorg/log_poller_maybe_reorg_test.go
create mode 100644 integration-tests/smoke/log_poller_test.go
create mode 100644 integration-tests/universal/log_poller/config.go
create mode 100644 integration-tests/universal/log_poller/gun.go
create mode 100644 integration-tests/universal/log_poller/helpers.go
create mode 100644 integration-tests/universal/log_poller/scenarios.go
diff --git a/.github/log_poller_on_demand.yml b/.github/log_poller_on_demand.yml
new file mode 100644
index 0000000000..856d1e0234
--- /dev/null
+++ b/.github/log_poller_on_demand.yml
@@ -0,0 +1,66 @@
+name: On Demand Log Poller Consistency Test
+on:
+ workflow_dispatch:
+ inputs:
+ contracts:
+ description: Number of test contracts
+ default: "2"
+ required: true
+ eventsPerTx:
+ description: Number of events to emit per transaction
+ default: "10"
+ required: true
+ useFinalityTag:
+ description: Use finality tag
+ default: "false"
+ required: true
+ loadDuration:
+ description: Load duration (e.g. 10s, 10m, 1h)
+ default: "10m"
+ required: true
+ chainlinkImage:
+ description: Chainlink image to use
+ default: "public.ecr.aws/chainlink/chainlink"
+ required: true
+ chainlinkVersion:
+ description: Chainlink version to use
+ default: "v2.7.0-beta0"
+ required: true
+ selectedNetworks:
+ description: Network to use (only Sepolia or Mumbai)
+ default: "Sepolia"
+ required: true
+ fundingKey:
+ description: Private key used to fund the contracts
+ required: true
+ rpcURL:
+ description: RPC URL to use
+ required: true
+ wsURL:
+ description: WS URL to use
+ required: true
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup Go
+ uses: actions/setup-go@v3
+ with:
+ go-version-file: "integration-tests/go.mod"
+ cache: true
+ - name: Show overrides
+ env:
+ CONTRACTS: ${{ inputs.contracts }}
+ EVENTS_PER_TX: ${{ inputs.eventsPerTx }}
+ LOAD_DURATION: ${{ inputs.loadDuration }}
+ USE_FINALITY_TAG: ${{ inputs.useFinalityTag }}
+ CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }}
+ CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }}
+ SELECTED_NETWORKS: ${{ inputs.selectedNetworks }}
+ EVM_KEYS: ${{ inputs.fundingKey }}
+ EVM_HTTP_URLS: ${{ inputs.rpcURL }}
+ EVM_URLS: ${{ inputs.wsURL }}
+ run: |
+ go test -v -timeout 5h -run=TestLogPollerFromEnv integration-tests/reorg/log_poller_maybe_reorg_test.go
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bfd66e2a39..61ebfab0e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,7 +65,7 @@ tests-*.xml
tmp-manifest-*.yaml
ztarrepo.tar.gz
**/test-ledger/*
-__debug_bin
+__debug_bin*
# goreleaser builds
cosign.*
@@ -82,3 +82,4 @@ contracts/yarn.lock
# Ignore DevSpace cache and log folder
.devspace/
+go.work*
\ No newline at end of file
diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go
index 4cd2804d9f..01d6a2aad4 100644
--- a/core/chains/evm/logpoller/log_poller.go
+++ b/core/chains/evm/logpoller/log_poller.go
@@ -466,6 +466,7 @@ func (lp *logPoller) run() {
// Serially process replay requests.
lp.lggr.Infow("Executing replay", "fromBlock", fromBlock, "requested", fromBlockReq)
lp.PollAndSaveLogs(lp.ctx, fromBlock)
+ lp.lggr.Infow("Executing replay finished", "fromBlock", fromBlock, "requested", fromBlockReq)
}
} else {
lp.lggr.Errorw("Error executing replay, could not get fromBlock", "err", err)
@@ -574,13 +575,14 @@ func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context, backupPollerBloc
lastSafeBackfillBlock := latestFinalizedBlockNumber - 1
if lastSafeBackfillBlock >= lp.backupPollerNextBlock {
- lp.lggr.Infow("Backup poller backfilling logs", "start", lp.backupPollerNextBlock, "end", lastSafeBackfillBlock)
+ lp.lggr.Infow("Backup poller started backfilling logs", "start", lp.backupPollerNextBlock, "end", lastSafeBackfillBlock)
if err = lp.backfill(ctx, lp.backupPollerNextBlock, lastSafeBackfillBlock); err != nil {
// If there's an error backfilling, we can just return and retry from the last block saved
// since we don't save any blocks on backfilling. We may re-insert the same logs but thats ok.
lp.lggr.Warnw("Backup poller failed", "err", err)
return
}
+ lp.lggr.Infow("Backup poller finished backfilling", "start", lp.backupPollerNextBlock, "end", lastSafeBackfillBlock)
lp.backupPollerNextBlock = lastSafeBackfillBlock + 1
}
}
diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go
index 8a79cb3ec9..3638fa11c7 100644
--- a/integration-tests/client/chainlink.go
+++ b/integration-tests/client/chainlink.go
@@ -1213,3 +1213,23 @@ func (c *ChainlinkClient) GetForwarders() (*Forwarders, *http.Response, error) {
}
return response, resp.RawResponse, err
}
+
+// Replays log poller from block number
+func (c *ChainlinkClient) ReplayLogPollerFromBlock(fromBlock, evmChainID int64) (*ReplayResponse, *http.Response, error) {
+ specObj := &ReplayResponse{}
+ c.l.Info().Str(NodeURL, c.Config.URL).Int64("From block", fromBlock).Int64("EVM chain ID", evmChainID).Msg("Replaying Log Poller from block")
+ resp, err := c.APIClient.R().
+ SetResult(&specObj).
+ SetQueryParams(map[string]string{
+ "evmChainID": fmt.Sprint(evmChainID),
+ }).
+ SetPathParams(map[string]string{
+ "fromBlock": fmt.Sprint(fromBlock),
+ }).
+ Post("/v2/replay_from_block/{fromBlock}")
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return specObj, resp.RawResponse, err
+}
diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go
index 6013e13e0f..c6d1209d2e 100644
--- a/integration-tests/client/chainlink_models.go
+++ b/integration-tests/client/chainlink_models.go
@@ -9,6 +9,7 @@ import (
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// EIServiceConfig represents External Initiator service config
@@ -1407,3 +1408,16 @@ type ForwarderAttributes struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
+
+type ReplayResponse struct {
+ Data ReplayResponseData `json:"data"`
+}
+
+type ReplayResponseData struct {
+ Attributes ReplayResponseAttributes `json:"attributes"`
+}
+
+type ReplayResponseAttributes struct {
+ Message string `json:"message"`
+ EVMChainID *utils.Big `json:"evmChainID"`
+}
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index e203d8318f..5a3fad256e 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -45,6 +45,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
registry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
+ le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_aggregator_proxy"
@@ -138,6 +139,7 @@ type ContractDeployer interface {
DeployMercuryVerifierProxyContract(accessControllerAddr common.Address) (MercuryVerifierProxy, error)
DeployMercuryFeeManager(linkAddress common.Address, nativeAddress common.Address, proxyAddress common.Address, rewardManagerAddress common.Address) (MercuryFeeManager, error)
DeployMercuryRewardManager(linkAddress common.Address) (MercuryRewardManager, error)
+ DeployLogEmitterContract() (LogEmitter, error)
}
// NewContractDeployer returns an instance of a contract deployer based on the client type
@@ -1613,3 +1615,21 @@ func (e *EthereumContractDeployer) DeployWERC20Mock() (WERC20Mock, error) {
l: e.l,
}, err
}
+
+func (e *EthereumContractDeployer) DeployLogEmitterContract() (LogEmitter, error) {
+ address, _, instance, err := e.client.DeployContract("Log Emitter", func(
+ auth *bind.TransactOpts,
+ backend bind.ContractBackend,
+ ) (common.Address, *types.Transaction, interface{}, error) {
+ return le.DeployLogEmitter(auth, backend)
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &LogEmitterContract{
+ client: e.client,
+ instance: instance.(*le.LogEmitter),
+ address: *address,
+ l: e.l,
+ }, err
+}
diff --git a/integration-tests/contracts/contract_models.go b/integration-tests/contracts/contract_models.go
index 51fce7cb12..4c8d610fa1 100644
--- a/integration-tests/contracts/contract_models.go
+++ b/integration-tests/contracts/contract_models.go
@@ -400,3 +400,13 @@ type WERC20Mock interface {
Transfer(to string, amount *big.Int) error
Mint(account common.Address, amount *big.Int) (*types.Transaction, error)
}
+
+type LogEmitter interface {
+ Address() common.Address
+ EmitLogInts(ints []int) (*types.Transaction, error)
+ EmitLogIntsIndexed(ints []int) (*types.Transaction, error)
+ EmitLogStrings(strings []string) (*types.Transaction, error)
+ EmitLogInt(payload int) (*types.Transaction, error)
+ EmitLogIntIndexed(payload int) (*types.Transaction, error)
+ EmitLogString(strings string) (*types.Transaction, error)
+}
diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go
new file mode 100644
index 0000000000..ccdd2989e4
--- /dev/null
+++ b/integration-tests/contracts/test_contracts.go
@@ -0,0 +1,79 @@
+package contracts
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/rs/zerolog"
+ "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+
+ le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
+)
+
+type LogEmitterContract struct {
+ address common.Address
+ client blockchain.EVMClient
+ instance *le.LogEmitter
+ l zerolog.Logger
+}
+
+func (e *LogEmitterContract) Address() common.Address {
+ return e.address
+}
+
+func (e *LogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) {
+ opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet())
+ if err != nil {
+ return nil, err
+ }
+ bigInts := make([]*big.Int, len(ints))
+ for i, v := range ints {
+ bigInts[i] = big.NewInt(int64(v))
+ }
+ tx, err := e.instance.EmitLog1(opts, bigInts)
+ if err != nil {
+ return nil, err
+ }
+ return tx, e.client.ProcessTransaction(tx)
+}
+
+func (e *LogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) {
+ opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet())
+ if err != nil {
+ return nil, err
+ }
+ bigInts := make([]*big.Int, len(ints))
+ for i, v := range ints {
+ bigInts[i] = big.NewInt(int64(v))
+ }
+ tx, err := e.instance.EmitLog2(opts, bigInts)
+ if err != nil {
+ return nil, err
+ }
+ return tx, e.client.ProcessTransaction(tx)
+}
+
+func (e *LogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) {
+ opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet())
+ if err != nil {
+ return nil, err
+ }
+ tx, err := e.instance.EmitLog3(opts, strings)
+ if err != nil {
+ return nil, err
+ }
+ return tx, e.client.ProcessTransaction(tx)
+}
+
+func (e *LogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) {
+ return e.EmitLogInts([]int{payload})
+}
+
+func (e *LogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) {
+ return e.EmitLogIntsIndexed([]int{payload})
+}
+
+func (e *LogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) {
+ return e.EmitLogStrings([]string{strings})
+}
diff --git a/integration-tests/docker/cmd/test_env.go b/integration-tests/docker/cmd/test_env.go
index 31b7de5dcd..f760f45f8d 100644
--- a/integration-tests/docker/cmd/test_env.go
+++ b/integration-tests/docker/cmd/test_env.go
@@ -50,6 +50,7 @@ func main() {
return nil
},
}
+
startEnvCmd.AddCommand(startFullEnvCmd)
// Set default log level for non-testcontainer code
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index 40ed0d4d53..e067e46090 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -166,6 +166,7 @@ func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error {
if err := cl.Fund(te.EVMClient, amount); err != nil {
return errors.Wrap(err, ErrFundCLNode)
}
+ time.Sleep(5 * time.Second)
}
return te.EVMClient.WaitForEvents()
}
diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go
index d155024050..c07ea76262 100644
--- a/integration-tests/docker/test_env/test_env_builder.go
+++ b/integration-tests/docker/test_env/test_env_builder.go
@@ -19,6 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+ evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
)
type CleanUpType string
@@ -30,22 +31,24 @@ const (
)
type CLTestEnvBuilder struct {
- hasLogWatch bool
- hasGeth bool
- hasKillgrave bool
- hasForwarders bool
- clNodeConfig *chainlink.Config
- secretsConfig string
- nonDevGethNetworks []blockchain.EVMNetwork
- clNodesCount int
- customNodeCsaKeys []string
- defaultNodeCsaKeys []string
- l zerolog.Logger
- t *testing.T
- te *CLClusterTestEnv
- isNonEVM bool
- cleanUpType CleanUpType
- cleanUpCustomFn func()
+ hasLogWatch bool
+ hasGeth bool
+ hasKillgrave bool
+ hasForwarders bool
+ clNodeConfig *chainlink.Config
+ secretsConfig string
+ nonDevGethNetworks []blockchain.EVMNetwork
+ clNodesCount int
+ customNodeCsaKeys []string
+ defaultNodeCsaKeys []string
+ l zerolog.Logger
+ t *testing.T
+ te *CLClusterTestEnv
+ isNonEVM bool
+ cleanUpType CleanUpType
+ cleanUpCustomFn func()
+ chainOptionsFn []ChainOption
+ evmClientNetworkOption []EVMClientNetworkOption
/* funding */
ETHFunds *big.Float
@@ -162,6 +165,24 @@ func (b *CLTestEnvBuilder) WithCustomCleanup(customFn func()) *CLTestEnvBuilder
return b
}
+type ChainOption = func(*evmcfg.Chain) *evmcfg.Chain
+
+func (b *CLTestEnvBuilder) WithChainOptions(opts ...ChainOption) *CLTestEnvBuilder {
+ b.chainOptionsFn = make([]ChainOption, 0, 0)
+ b.chainOptionsFn = append(b.chainOptionsFn, opts...)
+
+ return b
+}
+
+type EVMClientNetworkOption = func(*blockchain.EVMNetwork) *blockchain.EVMNetwork
+
+func (b *CLTestEnvBuilder) EVMClientNetworkOptions(opts ...EVMClientNetworkOption) *CLTestEnvBuilder {
+ b.evmClientNetworkOption = make([]EVMClientNetworkOption, 0, 0)
+ b.evmClientNetworkOption = append(b.evmClientNetworkOption, opts...)
+
+ return b
+}
+
func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
if b.te == nil {
var err error
@@ -245,10 +266,14 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
if err != nil {
return nil, err
}
-
}
if !b.isNonEVM {
+ if b.evmClientNetworkOption != nil && len(b.evmClientNetworkOption) > 0 {
+ for _, fn := range b.evmClientNetworkOption {
+ fn(&networkConfig)
+ }
+ }
bc, err := blockchain.NewEVMClientFromNetwork(networkConfig, b.l)
if err != nil {
return nil, err
@@ -294,6 +319,14 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
}
node.SetChainConfig(cfg, wsUrls, httpUrls, networkConfig, b.hasForwarders)
+
+ if b.chainOptionsFn != nil && len(b.chainOptionsFn) > 0 {
+ for _, fn := range b.chainOptionsFn {
+ for _, evmCfg := range cfg.EVM {
+ fn(&evmCfg.Chain)
+ }
+ }
+ }
}
err := b.te.StartClCluster(cfg, b.clNodesCount, b.secretsConfig)
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 33beae119a..127980a2cb 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -6,6 +6,7 @@ go 1.21
replace github.com/smartcontractkit/chainlink/v2 => ../
require (
+ cosmossdk.io/errors v1.0.0
github.com/K-Phoen/grabana v0.21.17
github.com/cli/go-gh/v2 v2.0.0
github.com/ethereum/go-ethereum v1.12.0
@@ -18,13 +19,15 @@ require (
github.com/pelletier/go-toml/v2 v2.1.0
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.30.0
+ github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.2
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.2-0.20231030212542-5fb562e774a5
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.27
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
+ github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wasp v0.3.0
github.com/spf13/cobra v1.6.1
@@ -49,7 +52,6 @@ require (
cosmossdk.io/api v0.3.1 // indirect
cosmossdk.io/core v0.5.1 // indirect
cosmossdk.io/depinject v1.0.0-alpha.3 // indirect
- cosmossdk.io/errors v1.0.0 // indirect
cosmossdk.io/math v1.0.1 // indirect
dario.cat/mergo v1.0.0 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
@@ -375,7 +377,6 @@ require (
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/russross/blackfriday v1.6.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
- github.com/scylladb/go-reflectx v1.0.1 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/sercand/kuberesolver v2.4.0+incompatible // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
@@ -387,7 +388,6 @@ require (
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
- github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
github.com/smartcontractkit/wsrpc v0.7.2 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 7969e82144..24da946717 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2368,8 +2368,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.2 h1:Ac/wdRDF4L479wpFT3yqn6ujb6kFTn7aq8gj9giyFHM=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.2/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.2-0.20231030212542-5fb562e774a5 h1:4hTf8pvtdtwoaeKFSEYjBZPvDbZ05WgiHsb0TPL6HqQ=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.2-0.20231030212542-5fb562e774a5/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/load/log_poller/config.toml b/integration-tests/load/log_poller/config.toml
new file mode 100644
index 0000000000..2e32800194
--- /dev/null
+++ b/integration-tests/load/log_poller/config.toml
@@ -0,0 +1,22 @@
+[general]
+generator = "looped"
+contracts = 10
+events_per_tx = 10
+
+[chaos]
+experiment_count = 10
+
+[looped]
+[looped.contract]
+execution_count = 300
+
+[looped.fuzz]
+min_emit_wait_time_ms = 100
+max_emit_wait_time_ms = 500
+
+[wasp]
+[wasp.load]
+call_timeout = "3m"
+rate_limit_unit_duration = "2s"
+LPS = 30
+duration = "1m"
\ No newline at end of file
diff --git a/integration-tests/load/log_poller/log_poller_test.go b/integration-tests/load/log_poller/log_poller_test.go
new file mode 100644
index 0000000000..ec67815832
--- /dev/null
+++ b/integration-tests/load/log_poller/log_poller_test.go
@@ -0,0 +1,24 @@
+package logpoller
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+
+ lp_helpers "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
+ "github.com/stretchr/testify/require"
+)
+
+func TestLoadTestLogPoller(t *testing.T) {
+ cfg, err := lp_helpers.ReadConfig(lp_helpers.DefaultConfigFilename)
+ require.NoError(t, err)
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range lp_helpers.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ lp_helpers.ExecuteBasicLogPollerTest(t, cfg)
+}
diff --git a/integration-tests/reorg/log_poller_maybe_reorg_test.go b/integration-tests/reorg/log_poller_maybe_reorg_test.go
new file mode 100644
index 0000000000..4e802bdb09
--- /dev/null
+++ b/integration-tests/reorg/log_poller_maybe_reorg_test.go
@@ -0,0 +1,42 @@
+package reorg
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ logpoller "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
+)
+
+func TestLogPollerFromEnv(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 100,
+ UseFinalityTag: true,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 800,
+ MaxEmitWaitTimeMs: 1200,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+ err := cfg.OverrideFromEnv()
+ if err != nil {
+ t.Errorf("failed to override config from env: %v", err)
+ t.FailNow()
+ }
+
+ logpoller.ExecuteCILogPollerTest(t, &cfg)
+}
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 17373e6a95..9e35b24df1 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -11,9 +11,8 @@ import (
"testing"
"time"
- "github.com/kelseyhightower/envconfig"
-
"github.com/ethereum/go-ethereum/common"
+ "github.com/kelseyhightower/envconfig"
"github.com/onsi/gomega"
"github.com/stretchr/testify/require"
diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go
new file mode 100644
index 0000000000..0df7817f1e
--- /dev/null
+++ b/integration-tests/smoke/log_poller_test.go
@@ -0,0 +1,140 @@
+package smoke
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ logpoller "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
+)
+
+// consistency test with no network disruptions with approximate emission of 1500-1600 logs per second for ~110-120 seconds
+// 6 filters are registered
+func TestLogPollerFewFilters(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 4,
+ UseFinalityTag: false,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ logpoller.ExecuteBasicLogPollerTest(t, &cfg)
+}
+
+// consistency test with no network disruptions with approximate emission of 1000-1100 logs per second for ~110-120 seconds
+// 900 filters are registered
+func TestLogManyFiltersPoller(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 300,
+ EventsPerTx: 3,
+ UseFinalityTag: false,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 30,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ logpoller.ExecuteBasicLogPollerTest(t, &cfg)
+}
+
+// consistency test that introduces random distruptions by pausing either Chainlink or Postgres containers for random interval of 5-20 seconds
+// with approximate emission of 520-550 logs per second for ~110 seconds
+// 6 filters are registered
+func TestLogPollerWithChaos(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 100,
+ UseFinalityTag: false,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ ChaosConfig: &logpoller.ChaosConfig{
+ ExperimentCount: 10,
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ logpoller.ExecuteBasicLogPollerTest(t, &cfg)
+}
+
+// consistency test that registers filters after events were emitted and then triggers replay via API
+// unfortunately there is no way to make sure that logs that are indexed are only picked up by replay
+// and not by backup poller
+// with approximate emission of 24 logs per second for ~110 seconds
+// 6 filters are registered
+func TestLogPollerReplay(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 4,
+ UseFinalityTag: false,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+ consistencyTimeout := "5m"
+
+ logpoller.ExecuteLogPollerReplay(t, &cfg, consistencyTimeout)
+}
diff --git a/integration-tests/universal/log_poller/config.go b/integration-tests/universal/log_poller/config.go
new file mode 100644
index 0000000000..623fa6606e
--- /dev/null
+++ b/integration-tests/universal/log_poller/config.go
@@ -0,0 +1,247 @@
+package logpoller
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+
+ "cosmossdk.io/errors"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/pelletier/go-toml/v2"
+ "github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/chainlink/v2/core/store/models"
+)
+
+const (
+ DefaultConfigFilename = "config.toml"
+
+ ErrReadPerfConfig = "failed to read TOML config for performance tests"
+ ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests"
+)
+
+type GeneratorType = string
+
+const (
+ GeneratorType_WASP = "wasp"
+ GeneratorType_Looped = "looped"
+)
+
+type Config struct {
+ General *General `toml:"general"`
+ ChaosConfig *ChaosConfig `toml:"chaos"`
+ Wasp *WaspConfig `toml:"wasp"`
+ LoopedConfig *LoopedConfig `toml:"looped"`
+}
+
+type LoopedConfig struct {
+ ContractConfig `toml:"contract"`
+ FuzzConfig `toml:"fuzz"`
+}
+
+type ContractConfig struct {
+ ExecutionCount int `toml:"execution_count"`
+}
+
+type FuzzConfig struct {
+ MinEmitWaitTimeMs int `toml:"min_emit_wait_time_ms"`
+ MaxEmitWaitTimeMs int `toml:"max_emit_wait_time_ms"`
+}
+
+type General struct {
+ Generator string `toml:"generator"`
+ EventsToEmit []abi.Event `toml:"-"`
+ Contracts int `toml:"contracts"`
+ EventsPerTx int `toml:"events_per_tx"`
+ UseFinalityTag bool `toml:"use_finality_tag"`
+}
+
+type ChaosConfig struct {
+ ExperimentCount int `toml:"experiment_count"`
+}
+
+type WaspConfig struct {
+ Load *Load `toml:"load"`
+}
+
+type Load struct {
+ RPS int64 `toml:"rps"`
+ LPS int64 `toml:"lps"`
+ RateLimitUnitDuration *models.Duration `toml:"rate_limit_unit_duration"`
+ Duration *models.Duration `toml:"duration"`
+ CallTimeout *models.Duration `toml:"call_timeout"`
+}
+
+func ReadConfig(configName string) (*Config, error) {
+ var cfg *Config
+ d, err := os.ReadFile(configName)
+ if err != nil {
+ return nil, errors.Wrap(err, ErrReadPerfConfig)
+ }
+ err = toml.Unmarshal(d, &cfg)
+ if err != nil {
+ return nil, errors.Wrap(err, ErrUnmarshalPerfConfig)
+ }
+
+ if err := cfg.validate(); err != nil {
+ return nil, err
+ }
+
+ log.Debug().Interface("Config", cfg).Msg("Parsed config")
+ return cfg, nil
+}
+
+func (c *Config) OverrideFromEnv() error {
+ if contr := os.Getenv("CONTRACTS"); contr != "" {
+ c.General.Contracts = mustParseInt(contr)
+ }
+
+ if eventsPerTx := os.Getenv("EVENTS_PER_TX"); eventsPerTx != "" {
+ c.General.EventsPerTx = mustParseInt(eventsPerTx)
+ }
+
+ if useFinalityTag := os.Getenv("USE_FINALITY_TAG"); useFinalityTag != "" {
+ c.General.UseFinalityTag = mustParseBool(useFinalityTag)
+ }
+
+ if duration := os.Getenv("LOAD_DURATION"); duration != "" {
+ d, err := models.ParseDuration(duration)
+ if err != nil {
+ return err
+ }
+
+ if c.General.Generator == GeneratorType_WASP {
+ c.Wasp.Load.Duration = &d
+ } else {
+ // make the looped generator approximately run for desired duration
+ // on average we will emit 1 event per second
+ c.LoopedConfig.FuzzConfig.MinEmitWaitTimeMs = 900
+ c.LoopedConfig.FuzzConfig.MaxEmitWaitTimeMs = 1100
+ c.LoopedConfig.ContractConfig.ExecutionCount = int(d.Duration().Seconds())
+ }
+ }
+
+ return nil
+}
+
+func (c *Config) validate() error {
+ if c.General == nil {
+ return fmt.Errorf("General config is nil")
+ }
+
+ err := c.General.validate()
+ if err != nil {
+ return fmt.Errorf("General config validation failed: %v", err)
+ }
+
+ switch c.General.Generator {
+ case GeneratorType_WASP:
+ if c.Wasp == nil {
+ return fmt.Errorf("Wasp config is nil")
+ }
+ if c.Wasp.Load == nil {
+ return fmt.Errorf("Wasp load config is nil")
+ }
+
+ err = c.Wasp.validate()
+ if err != nil {
+ return fmt.Errorf("Wasp config validation failed: %v", err)
+ }
+ case GeneratorType_Looped:
+ if c.LoopedConfig == nil {
+ return fmt.Errorf("Looped config is nil")
+ }
+
+ err = c.LoopedConfig.validate()
+ if err != nil {
+ return fmt.Errorf("Looped config validation failed: %v", err)
+ }
+ default:
+ return fmt.Errorf("Unknown generator type: %s", c.General.Generator)
+ }
+
+ return nil
+}
+
+func (g *General) validate() error {
+ if g.Generator == "" {
+ return fmt.Errorf("Generator is empty")
+ }
+
+ if g.Contracts == 0 {
+ return fmt.Errorf("Contracts is 0, but must be > 0")
+ }
+
+ if g.EventsPerTx == 0 {
+ return fmt.Errorf("Events_per_tx is 0, but must be > 0")
+ }
+
+ return nil
+}
+
+func (w *WaspConfig) validate() error {
+ if w.Load == nil {
+ return fmt.Errorf("Load config is nil")
+ }
+
+ err := w.Load.validate()
+ if err != nil {
+ return fmt.Errorf("Load config validation failed: %v", err)
+ }
+
+ return nil
+}
+
+func (l *Load) validate() error {
+ if l.RPS == 0 && l.LPS == 0 {
+ return fmt.Errorf("Either RPS or LPS needs to be set")
+ }
+
+ if l.RPS != 0 && l.LPS != 0 {
+ return fmt.Errorf("Only one of RPS or LPS can be set")
+ }
+
+ if l.Duration == nil {
+ return fmt.Errorf("duration is nil")
+ }
+
+ if l.CallTimeout == nil {
+ return fmt.Errorf("call_timeout is nil")
+ }
+ if l.RateLimitUnitDuration == nil {
+ return fmt.Errorf("rate_limit_unit_duration is nil")
+ }
+
+ return nil
+}
+
+func (l *LoopedConfig) validate() error {
+ if l.ExecutionCount == 0 {
+ return fmt.Errorf("execution_count is 0, but must be > 0")
+ }
+
+ if l.MinEmitWaitTimeMs == 0 {
+ return fmt.Errorf("min_emit_wait_time_ms is 0, but must be > 0")
+ }
+
+ if l.MaxEmitWaitTimeMs == 0 {
+ return fmt.Errorf("max_emit_wait_time_ms is 0, but must be > 0")
+ }
+
+ return nil
+}
+
+func mustParseInt(s string) int {
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ panic(err)
+ }
+ return i
+}
+
+func mustParseBool(s string) bool {
+ b, err := strconv.ParseBool(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
diff --git a/integration-tests/universal/log_poller/gun.go b/integration-tests/universal/log_poller/gun.go
new file mode 100644
index 0000000000..11932330a3
--- /dev/null
+++ b/integration-tests/universal/log_poller/gun.go
@@ -0,0 +1,78 @@
+package logpoller
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/rs/zerolog"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ "github.com/smartcontractkit/wasp"
+)
+
+/* LogEmitterGun is a gun that constantly emits logs from a contract */
+type LogEmitterGun struct {
+ contract *contracts.LogEmitter
+ eventsToEmit []abi.Event
+ logger zerolog.Logger
+ eventsPerTx int
+}
+
+type Counter struct {
+ mu *sync.Mutex
+ value int
+}
+
+func NewLogEmitterGun(
+ contract *contracts.LogEmitter,
+ eventsToEmit []abi.Event,
+ eventsPerTx int,
+ logger zerolog.Logger,
+) *LogEmitterGun {
+ return &LogEmitterGun{
+ contract: contract,
+ eventsToEmit: eventsToEmit,
+ eventsPerTx: eventsPerTx,
+ logger: logger,
+ }
+}
+
+func (m *LogEmitterGun) Call(l *wasp.Generator) *wasp.CallResult {
+ localCounter := 0
+ logEmitter := (*m.contract)
+ address := logEmitter.Address()
+ for _, event := range m.eventsToEmit {
+ m.logger.Debug().Str("Emitter address", address.String()).Str("Event type", event.Name).Msg("Emitting log from emitter")
+ var err error
+ switch event.Name {
+ case "Log1":
+ _, err = logEmitter.EmitLogInts(getIntSlice(m.eventsPerTx))
+ case "Log2":
+ _, err = logEmitter.EmitLogIntsIndexed(getIntSlice(m.eventsPerTx))
+ case "Log3":
+ _, err = logEmitter.EmitLogStrings(getStringSlice(m.eventsPerTx))
+ default:
+ err = fmt.Errorf("Unknown event name: %s", event.Name)
+ }
+
+ if err != nil {
+ return &wasp.CallResult{Error: err.Error(), Failed: true}
+ }
+ localCounter += 1
+ }
+
+ // I don't think that will work as expected, I should atomically read the value and save it, so maybe just a mutex?
+ if counter, ok := l.InputSharedData().(*Counter); ok {
+ counter.mu.Lock()
+ defer counter.mu.Unlock()
+ counter.value += localCounter
+ } else {
+ return &wasp.CallResult{
+ Error: "SharedData did not contain a Counter",
+ Failed: true,
+ }
+ }
+
+ return &wasp.CallResult{}
+}
diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go
new file mode 100644
index 0000000000..aa488eb1be
--- /dev/null
+++ b/integration-tests/universal/log_poller/helpers.go
@@ -0,0 +1,1136 @@
+package logpoller
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "math/big"
+ "math/rand"
+ "sort"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+
+ geth "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ geth_types "github.com/ethereum/go-ethereum/core/types"
+ "github.com/rs/zerolog"
+ "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ ctf_blockchain "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink/integration-tests/actions"
+ "github.com/smartcontractkit/chainlink/integration-tests/client"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
+ "github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+ "github.com/smartcontractkit/wasp"
+
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
+ cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/store/models"
+
+ ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ "github.com/stretchr/testify/require"
+
+ "github.com/scylladb/go-reflectx"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
+ utils2 "github.com/smartcontractkit/chainlink/integration-tests/utils"
+ evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
+ lpEvm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
+ le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
+ core_logger "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/smartcontractkit/sqlx"
+)
+
+var (
+ EmitterABI, _ = abi.JSON(strings.NewReader(le.LogEmitterABI))
+ automationUtilsABI = cltypes.MustGetABI(automation_utils_2_1.AutomationUtilsABI)
+ bytes0 = [32]byte{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ } // bytes representation of 0x0000000000000000000000000000000000000000000000000000000000000000
+
+)
+
+var registerSingleTopicFilter = func(registry contracts.KeeperRegistry, upkeepID *big.Int, emitterAddress common.Address, topic common.Hash) error {
+ logTriggerConfigStruct := automation_utils_2_1.LogTriggerConfig{
+ ContractAddress: emitterAddress,
+ FilterSelector: 0,
+ Topic0: topic,
+ Topic1: bytes0,
+ Topic2: bytes0,
+ Topic3: bytes0,
+ }
+ encodedLogTriggerConfig, err := automationUtilsABI.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct)
+ if err != nil {
+ return err
+ }
+
+ err = registry.SetUpkeepTriggerConfig(upkeepID, encodedLogTriggerConfig)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// this is not really possible, log trigger doesn't support multiple topics, even if log poller does
+var registerMultipleTopicsFilter = func(registry contracts.KeeperRegistry, upkeepID *big.Int, emitterAddress common.Address, topics []abi.Event) error {
+ if len(topics) > 4 {
+ return errors.New("Cannot register more than 4 topics")
+ }
+
+ var getTopic = func(topics []abi.Event, i int) common.Hash {
+ if i > len(topics)-1 {
+ return bytes0
+ }
+
+ return topics[i].ID
+ }
+
+ var getFilterSelector = func(topics []abi.Event) (uint8, error) {
+ switch len(topics) {
+ case 0:
+ return 0, errors.New("Cannot register filter with 0 topics")
+ case 1:
+ return 0, nil
+ case 2:
+ return 1, nil
+ case 3:
+ return 3, nil
+ case 4:
+ return 7, nil
+ default:
+ return 0, errors.New("Cannot register filter with more than 4 topics")
+ }
+ }
+
+ filterSelector, err := getFilterSelector(topics)
+ if err != nil {
+ return err
+ }
+
+ logTriggerConfigStruct := automation_utils_2_1.LogTriggerConfig{
+ ContractAddress: emitterAddress,
+ FilterSelector: filterSelector,
+ Topic0: getTopic(topics, 0),
+ Topic1: getTopic(topics, 1),
+ Topic2: getTopic(topics, 2),
+ Topic3: getTopic(topics, 3),
+ }
+ encodedLogTriggerConfig, err := automationUtilsABI.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct)
+ if err != nil {
+ return err
+ }
+
+ err = registry.SetUpkeepTriggerConfig(upkeepID, encodedLogTriggerConfig)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func NewOrm(logger core_logger.SugaredLogger, chainID *big.Int, postgresDb *ctf_test_env.PostgresDb) (*lpEvm.DbORM, *sqlx.DB, error) {
+ dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", "127.0.0.1", postgresDb.ExternalPort, postgresDb.User, postgresDb.Password, postgresDb.DbName)
+ db, err := sqlx.Open("postgres", dsn)
+ if err != nil {
+ return nil, db, err
+ }
+
+ db.MapperFunc(reflectx.CamelToSnakeASCII)
+ return lpEvm.NewORM(chainID, db, logger, pg.NewQConfig(false)), db, nil
+}
+
+type ExpectedFilter struct {
+ emitterAddress common.Address
+ topic common.Hash
+}
+
+func getExpectedFilters(logEmitters []*contracts.LogEmitter, cfg *Config) []ExpectedFilter {
+ expectedFilters := make([]ExpectedFilter, 0)
+ for _, emitter := range logEmitters {
+ for _, event := range cfg.General.EventsToEmit {
+ expectedFilters = append(expectedFilters, ExpectedFilter{
+ emitterAddress: (*emitter).Address(),
+ topic: event.ID,
+ })
+ }
+ }
+
+ return expectedFilters
+}
+
+var nodeHasExpectedFilters = func(expectedFilters []ExpectedFilter, logger core_logger.SugaredLogger, chainID *big.Int, postgresDb *ctf_test_env.PostgresDb) (bool, error) {
+ orm, db, err := NewOrm(logger, chainID, postgresDb)
+ if err != nil {
+ return false, err
+ }
+
+ defer db.Close()
+ knownFilters, err := orm.LoadFilters()
+ if err != nil {
+ return false, err
+ }
+
+ for _, expectedFilter := range expectedFilters {
+ filterFound := false
+ for _, knownFilter := range knownFilters {
+ if bytes.Equal(expectedFilter.emitterAddress.Bytes(), knownFilter.Addresses[0].Bytes()) && bytes.Equal(expectedFilter.topic.Bytes(), knownFilter.EventSigs[0].Bytes()) {
+ filterFound = true
+ break
+ }
+ }
+
+ if !filterFound {
+ return false, fmt.Errorf("No filter found for emitter %s and topic %s", expectedFilter.emitterAddress.String(), expectedFilter.topic.Hex())
+ }
+ }
+
+ return true, nil
+}
+
+var randomWait = func(minMilliseconds, maxMilliseconds int) {
+ rand.New(rand.NewSource(time.Now().UnixNano()))
+ randomMilliseconds := rand.Intn(maxMilliseconds-minMilliseconds+1) + minMilliseconds
+ time.Sleep(time.Duration(randomMilliseconds) * time.Millisecond)
+}
+
+type LogEmitterChannel struct {
+ logsEmitted int
+ err error
+ currentIndex int
+}
+
+func getIntSlice(length int) []int {
+ result := make([]int, length)
+ for i := 0; i < length; i++ {
+ result[i] = i
+ }
+
+ return result
+}
+
+func getStringSlice(length int) []string {
+ result := make([]string, length)
+ for i := 0; i < length; i++ {
+ result[i] = "amazing event"
+ }
+
+ return result
+}
+
+var emitEvents = func(ctx context.Context, l zerolog.Logger, logEmitter *contracts.LogEmitter, cfg *Config, wg *sync.WaitGroup, results chan LogEmitterChannel) {
+ address := (*logEmitter).Address().String()
+ localCounter := 0
+ select {
+ case <-ctx.Done():
+ l.Warn().Str("Emitter address", address).Msg("Context cancelled, not emitting events")
+ return
+ default:
+ defer wg.Done()
+ for i := 0; i < cfg.LoopedConfig.ExecutionCount; i++ {
+ for _, event := range cfg.General.EventsToEmit {
+ l.Debug().Str("Emitter address", address).Str("Event type", event.Name).Str("index", fmt.Sprintf("%d/%d", (i+1), cfg.LoopedConfig.ExecutionCount)).Msg("Emitting log from emitter")
+ var err error
+ switch event.Name {
+ case "Log1":
+ _, err = (*logEmitter).EmitLogInts(getIntSlice(cfg.General.EventsPerTx))
+ case "Log2":
+ _, err = (*logEmitter).EmitLogIntsIndexed(getIntSlice(cfg.General.EventsPerTx))
+ case "Log3":
+ _, err = (*logEmitter).EmitLogStrings(getStringSlice(cfg.General.EventsPerTx))
+ default:
+ err = fmt.Errorf("Unknown event name: %s", event.Name)
+ }
+
+ if err != nil {
+ results <- LogEmitterChannel{
+ logsEmitted: 0,
+ err: err,
+ }
+ return
+ }
+ localCounter += cfg.General.EventsPerTx
+
+ randomWait(cfg.LoopedConfig.FuzzConfig.MinEmitWaitTimeMs, cfg.LoopedConfig.FuzzConfig.MaxEmitWaitTimeMs)
+ }
+
+ if (i+1)%10 == 0 {
+ l.Info().Str("Emitter address", address).Str("Index", fmt.Sprintf("%d/%d", i+1, cfg.LoopedConfig.ExecutionCount)).Msg("Emitted all three events")
+ }
+ }
+
+ l.Info().Str("Emitter address", address).Int("Total logs emitted", localCounter).Msg("Finished emitting events")
+
+ results <- LogEmitterChannel{
+ logsEmitted: localCounter,
+ err: nil,
+ }
+ }
+}
+
+var waitForEndBlockInLogPoller = func(endBlock int64, chainID *big.Int, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) {
+ for i := 1; i < len(nodes.Nodes); i++ {
+ clNode := nodes.Nodes[i]
+ orm, db, err := NewOrm(coreLogger, chainID, clNode.PostgresDb)
+ if err != nil {
+ return false, err
+ }
+
+ defer db.Close()
+ block, err := orm.SelectBlockByNumber(endBlock)
+ if err != nil {
+ return false, err
+ }
+
+ if block == nil {
+ return false, nil
+ }
+ }
+
+ return true, nil
+}
+
+var chainHasFinalisedEndBlock = func(l zerolog.Logger, evmClient ctf_blockchain.EVMClient, endBlock int64) (bool, error) {
+ effectiveEndBlock := endBlock + 1
+ lastFinalisedBlockHeader, err := evmClient.GetLatestFinalizedBlockHeader(context.Background())
+ if err != nil {
+ return false, err
+ }
+
+ l.Info().Int64("Last finalised block header", lastFinalisedBlockHeader.Number.Int64()).Int64("End block", effectiveEndBlock).Int64("Blocks left till end block", effectiveEndBlock-lastFinalisedBlockHeader.Number.Int64()).Msg("Waiting for the finalized block to move beyond end block")
+
+ return lastFinalisedBlockHeader.Number.Int64() > effectiveEndBlock, nil
+}
+
+var logPollerHasFinalisedEndBlock = func(endBlock int64, chainID *big.Int, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) {
+ wg := &sync.WaitGroup{}
+
+ type boolQueryResult struct {
+ nodeName string
+ hasFinalised bool
+ err error
+ }
+
+ endBlockCh := make(chan boolQueryResult, len(nodes.Nodes)-1)
+ ctx, cancelFn := context.WithCancel(context.Background())
+
+ for i := 1; i < len(nodes.Nodes); i++ {
+ wg.Add(1)
+
+ go func(clNode *test_env.ClNode, r chan boolQueryResult) {
+ defer wg.Done()
+ select {
+ case <-ctx.Done():
+ return
+ default:
+ orm, db, err := NewOrm(coreLogger, chainID, clNode.PostgresDb)
+ if err != nil {
+ r <- boolQueryResult{
+ nodeName: clNode.ContainerName,
+ hasFinalised: false,
+ err: err,
+ }
+ }
+
+ defer db.Close()
+
+ latestBlock, err := orm.SelectLatestBlock()
+ if err != nil {
+ r <- boolQueryResult{
+ nodeName: clNode.ContainerName,
+ hasFinalised: false,
+ err: err,
+ }
+ }
+
+ r <- boolQueryResult{
+ nodeName: clNode.ContainerName,
+ hasFinalised: latestBlock.FinalizedBlockNumber > endBlock,
+ err: nil,
+ }
+
+ }
+ }(nodes.Nodes[i], endBlockCh)
+ }
+
+ var err error
+ allFinalisedCh := make(chan bool, 1)
+
+ go func() {
+ foundMap := make(map[string]bool, 0)
+ for r := range endBlockCh {
+ if r.err != nil {
+ err = r.err
+ cancelFn()
+ return
+ }
+
+ foundMap[r.nodeName] = r.hasFinalised
+ if r.hasFinalised {
+ l.Info().Str("Node name", r.nodeName).Msg("CL node has finalised end block")
+ } else {
+ l.Warn().Str("Node name", r.nodeName).Msg("CL node has not finalised end block yet")
+ }
+
+ if len(foundMap) == len(nodes.Nodes)-1 {
+ allFinalised := true
+ for _, v := range foundMap {
+ if !v {
+ allFinalised = false
+ break
+ }
+ }
+
+ allFinalisedCh <- allFinalised
+ return
+ }
+ }
+ }()
+
+ wg.Wait()
+ close(endBlockCh)
+
+ return <-allFinalisedCh, err
+}
+
+var clNodesHaveExpectedLogCount = func(startBlock, endBlock int64, chainID *big.Int, expectedLogCount int, expectedFilters []ExpectedFilter, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) {
+ wg := &sync.WaitGroup{}
+
+ type logQueryResult struct {
+ nodeName string
+ logCount int
+ hasExpectedCount bool
+ err error
+ }
+
+ queryCh := make(chan logQueryResult, len(nodes.Nodes)-1)
+ ctx, cancelFn := context.WithCancel(context.Background())
+
+ for i := 1; i < len(nodes.Nodes); i++ {
+ wg.Add(1)
+
+ go func(clNode *test_env.ClNode, r chan logQueryResult) {
+ defer wg.Done()
+ select {
+ case <-ctx.Done():
+ return
+ default:
+ orm, db, err := NewOrm(coreLogger, chainID, clNode.PostgresDb)
+ if err != nil {
+ r <- logQueryResult{
+ nodeName: clNode.ContainerName,
+ logCount: 0,
+ hasExpectedCount: false,
+ err: err,
+ }
+ }
+
+ defer db.Close()
+ foundLogsCount := 0
+
+ for _, filter := range expectedFilters {
+ logs, err := orm.SelectLogs(startBlock, endBlock, filter.emitterAddress, filter.topic)
+ if err != nil {
+ r <- logQueryResult{
+ nodeName: clNode.ContainerName,
+ logCount: 0,
+ hasExpectedCount: false,
+ err: err,
+ }
+ }
+
+ foundLogsCount += len(logs)
+ }
+
+ r <- logQueryResult{
+ nodeName: clNode.ContainerName,
+ logCount: foundLogsCount,
+ hasExpectedCount: foundLogsCount >= expectedLogCount,
+ err: err,
+ }
+ }
+ }(nodes.Nodes[i], queryCh)
+ }
+
+ var err error
+ allFoundCh := make(chan bool, 1)
+
+ go func() {
+ foundMap := make(map[string]bool, 0)
+ for r := range queryCh {
+ if r.err != nil {
+ err = r.err
+ cancelFn()
+ return
+ }
+
+ foundMap[r.nodeName] = r.hasExpectedCount
+ if r.hasExpectedCount {
+ l.Info().Str("Node name", r.nodeName).Int("Logs count", r.logCount).Msg("Expected log count found in CL node")
+ } else {
+ l.Warn().Str("Node name", r.nodeName).Str("Found/Expected logs", fmt.Sprintf("%d/%d", r.logCount, expectedLogCount)).Int("Missing logs", expectedLogCount-r.logCount).Msg("Too low log count found in CL node")
+ }
+
+ if len(foundMap) == len(nodes.Nodes)-1 {
+ allFound := true
+ for _, v := range foundMap {
+ if !v {
+ allFound = false
+ break
+ }
+ }
+
+ allFoundCh <- allFound
+ return
+ }
+ }
+ }()
+
+ wg.Wait()
+ close(queryCh)
+
+ return <-allFoundCh, err
+}
+
+type MissingLogs map[string][]geth_types.Log
+
+func (m *MissingLogs) IsEmpty() bool {
+ for _, v := range *m {
+ if len(v) > 0 {
+ return false
+ }
+ }
+
+ return true
+}
+
+var getMissingLogs = func(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient ctf_blockchain.EVMClient, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *Config) (MissingLogs, error) {
+ wg := &sync.WaitGroup{}
+
+ type dbQueryResult struct {
+ err error
+ nodeName string
+ logs []logpoller.Log
+ }
+
+ ctx, cancelFn := context.WithCancel(context.Background())
+ resultCh := make(chan dbQueryResult, len(clnodeCluster.Nodes)-1)
+
+ for i := 1; i < len(clnodeCluster.Nodes); i++ {
+ wg.Add(1)
+
+ go func(ctx context.Context, i int, r chan dbQueryResult) {
+ defer wg.Done()
+ select {
+ case <-ctx.Done():
+ l.Warn().Msg("Context cancelled. Terminating fetching logs from log poller's DB")
+ return
+ default:
+ nodeName := clnodeCluster.Nodes[i].ContainerName
+
+ l.Info().Str("Node name", nodeName).Msg("Fetching log poller logs")
+ orm, db, err := NewOrm(coreLogger, evmClient.GetChainID(), clnodeCluster.Nodes[i].PostgresDb)
+ if err != nil {
+ r <- dbQueryResult{
+ err: err,
+ nodeName: nodeName,
+ logs: []logpoller.Log{},
+ }
+ }
+
+ defer db.Close()
+ logs := make([]logpoller.Log, 0)
+
+ for j := 0; j < len(logEmitters); j++ {
+ address := (*logEmitters[j]).Address()
+
+ for _, event := range cfg.General.EventsToEmit {
+ l.Debug().Str("Event name", event.Name).Str("Emitter address", address.String()).Msg("Fetching single emitter's logs")
+ result, err := orm.SelectLogs(startBlock, endBlock, address, event.ID)
+ if err != nil {
+ r <- dbQueryResult{
+ err: err,
+ nodeName: nodeName,
+ logs: []logpoller.Log{},
+ }
+ }
+
+ sort.Slice(result, func(i, j int) bool {
+ return result[i].BlockNumber < result[j].BlockNumber
+ })
+
+ logs = append(logs, result...)
+
+ l.Debug().Str("Event name", event.Name).Str("Emitter address", address.String()).Int("Log count", len(result)).Msg("Logs found per node")
+ }
+ }
+
+ l.Warn().Int("Count", len(logs)).Str("Node name", nodeName).Msg("Fetched log poller logs")
+
+ r <- dbQueryResult{
+ err: nil,
+ nodeName: nodeName,
+ logs: logs,
+ }
+ }
+ }(ctx, i, resultCh)
+ }
+
+ allLogPollerLogs := make(map[string][]logpoller.Log, 0)
+ missingLogs := map[string][]geth_types.Log{}
+ var dbError error
+
+ go func() {
+ for r := range resultCh {
+ if r.err != nil {
+ l.Err(r.err).Str("Node name", r.nodeName).Msg("Error fetching logs from log poller's DB")
+ dbError = r.err
+ cancelFn()
+ return
+ }
+ // use channel for aggregation and then for := range over it after closing resultCh?
+ allLogPollerLogs[r.nodeName] = r.logs
+ }
+ }()
+
+ wg.Wait()
+ close(resultCh)
+
+ if dbError != nil {
+ return nil, dbError
+ }
+
+ allLogsInEVMNode, err := getEVMLogs(startBlock, endBlock, logEmitters, evmClient, l, cfg)
+ if err != nil {
+ return nil, err
+ }
+
+ wg = &sync.WaitGroup{}
+
+ type missingLogResult struct {
+ nodeName string
+ logs []geth_types.Log
+ }
+
+ l.Info().Msg("Started comparison of logs from EVM node and CL nodes. This may take a while if there's a lot of logs")
+ missingCh := make(chan missingLogResult, len(clnodeCluster.Nodes)-1)
+ evmLogCount := len(allLogsInEVMNode)
+ for i := 1; i < len(clnodeCluster.Nodes); i++ {
+ wg.Add(1)
+
+ go func(i int, result chan missingLogResult) {
+ defer wg.Done()
+ nodeName := clnodeCluster.Nodes[i].ContainerName
+ l.Info().Str("Node name", nodeName).Str("Progress", fmt.Sprintf("0/%d", evmLogCount)).Msg("Comparing single CL node's logs with EVM logs")
+
+ missingLogs := make([]geth_types.Log, 0)
+ for i, evmLog := range allLogsInEVMNode {
+ logFound := false
+ for _, logPollerLog := range allLogPollerLogs[nodeName] {
+ if logPollerLog.BlockNumber == int64(evmLog.BlockNumber) && logPollerLog.TxHash == evmLog.TxHash && bytes.Equal(logPollerLog.Data, evmLog.Data) && logPollerLog.LogIndex == int64(evmLog.Index) &&
+ logPollerLog.Address == evmLog.Address && logPollerLog.BlockHash == evmLog.BlockHash && bytes.Equal(logPollerLog.Topics[0][:], evmLog.Topics[0].Bytes()) {
+ logFound = true
+ continue
+ }
+ }
+
+ if i%10000 == 0 && i != 0 {
+ l.Info().Str("Node name", nodeName).Str("Progress", fmt.Sprintf("%d/%d", i, evmLogCount)).Msg("Comparing single CL node's logs with EVM logs")
+ }
+
+ if !logFound {
+ missingLogs = append(missingLogs, evmLog)
+ }
+ }
+
+ if len(missingLogs) > 0 {
+ l.Warn().Int("Count", len(missingLogs)).Str("Node name", nodeName).Msg("Some EMV logs were missing from CL node")
+ } else {
+ l.Info().Str("Node name", nodeName).Msg("All EVM logs were found in CL node")
+ }
+
+ result <- missingLogResult{
+ nodeName: nodeName,
+ logs: missingLogs,
+ }
+ }(i, missingCh)
+ }
+
+ wg.Wait()
+ close(missingCh)
+
+ for v := range missingCh {
+ if len(v.logs) > 0 {
+ missingLogs[v.nodeName] = v.logs
+ }
+ }
+
+ expectedTotalLogsEmitted := getExpectedLogCount(cfg)
+ if int64(len(allLogsInEVMNode)) != expectedTotalLogsEmitted {
+ l.Warn().Str("Actual/Expected", fmt.Sprintf("%d/%d", expectedTotalLogsEmitted, len(allLogsInEVMNode))).Msg("Some of the test logs were not found in EVM node. This is a bug in the test")
+ }
+
+ return missingLogs, nil
+}
+
+var printMissingLogsByType = func(missingLogs map[string][]geth_types.Log, l zerolog.Logger, cfg *Config) {
+ var findHumanName = func(topic common.Hash) string {
+ for _, event := range cfg.General.EventsToEmit {
+ if event.ID == topic {
+ return event.Name
+ }
+ }
+
+ return "Unknown event"
+ }
+
+ missingByType := make(map[string]int)
+ for _, logs := range missingLogs {
+ for _, v := range logs {
+ humanName := findHumanName(v.Topics[0])
+ if _, ok := missingByType[humanName]; ok {
+ missingByType[humanName] += 1
+ } else {
+ missingByType[humanName] = 1
+ }
+ }
+ }
+
+ for k, v := range missingByType {
+ l.Warn().Str("Event name", k).Int("Missing count", v).Msg("Missing logs by type")
+ }
+}
+
+var getEVMLogs = func(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient ctf_blockchain.EVMClient, l zerolog.Logger, cfg *Config) ([]geth_types.Log, error) {
+ allLogsInEVMNode := make([]geth_types.Log, 0)
+ for j := 0; j < len(logEmitters); j++ {
+ address := (*logEmitters[j]).Address()
+ for _, event := range cfg.General.EventsToEmit {
+ l.Debug().Str("Event name", event.Name).Str("Emitter address", address.String()).Msg("Fetching logs from EVM node")
+ logsInEVMNode, err := evmClient.FilterLogs(context.Background(), geth.FilterQuery{
+ Addresses: []common.Address{(address)},
+ Topics: [][]common.Hash{{event.ID}},
+ FromBlock: big.NewInt(startBlock),
+ ToBlock: big.NewInt(endBlock),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ sort.Slice(logsInEVMNode, func(i, j int) bool {
+ return logsInEVMNode[i].BlockNumber < logsInEVMNode[j].BlockNumber
+ })
+
+ allLogsInEVMNode = append(allLogsInEVMNode, logsInEVMNode...)
+ l.Debug().Str("Event name", event.Name).Str("Emitter address", address.String()).Int("Log count", len(logsInEVMNode)).Msg("Logs found in EVM node")
+ }
+ }
+
+ l.Warn().Int("Count", len(allLogsInEVMNode)).Msg("Logs in EVM node")
+
+ return allLogsInEVMNode, nil
+}
+
+func executeGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmitter) (int, error) {
+ if cfg.General.Generator == GeneratorType_WASP {
+ return runWaspGenerator(t, cfg, logEmitters)
+ }
+
+ return runLoopedGenerator(t, cfg, logEmitters)
+}
+
+func runWaspGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmitter) (int, error) {
+ l := logging.GetTestLogger(t)
+
+ var RPSprime int64
+
+ // if LPS is set, we need to calculate based on countract count and events per transaction
+ if cfg.Wasp.Load.LPS > 0 {
+ RPSprime = cfg.Wasp.Load.LPS / int64(cfg.General.Contracts) / int64(cfg.General.EventsPerTx) / int64(len(cfg.General.EventsToEmit))
+
+ if RPSprime < 1 {
+ return 0, fmt.Errorf("Invalid load configuration, effective RPS would have been zero. Adjust LPS, contracts count, events per tx or events to emit")
+ }
+ }
+
+ // if RPS is set simply split it between contracts
+ if cfg.Wasp.Load.RPS > 0 {
+ RPSprime = cfg.Wasp.Load.RPS / int64(cfg.General.Contracts)
+ }
+
+ counter := &Counter{
+ mu: &sync.Mutex{},
+ value: 0,
+ }
+
+ p := wasp.NewProfile()
+
+ for _, logEmitter := range logEmitters {
+ g, err := wasp.NewGenerator(&wasp.Config{
+ T: t,
+ LoadType: wasp.RPS,
+ GenName: fmt.Sprintf("log_poller_gen_%s", (*logEmitter).Address().String()),
+ RateLimitUnitDuration: cfg.Wasp.Load.RateLimitUnitDuration.Duration(),
+ CallTimeout: cfg.Wasp.Load.CallTimeout.Duration(),
+ Schedule: wasp.Plain(
+ RPSprime,
+ cfg.Wasp.Load.Duration.Duration(),
+ ),
+ Gun: NewLogEmitterGun(
+ logEmitter,
+ cfg.General.EventsToEmit,
+ cfg.General.EventsPerTx,
+ l,
+ ),
+ SharedData: counter,
+ })
+ p.Add(g, err)
+ }
+
+ _, err := p.Run(true)
+
+ if err != nil {
+ return 0, err
+ }
+
+ return counter.value, nil
+}
+
+func runLoopedGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmitter) (int, error) {
+ l := logging.GetTestLogger(t)
+
+ // Start emitting events in parallel, each contract is emitting events in a separate goroutine
+ // We will stop as soon as we encounter an error
+ wg := &sync.WaitGroup{}
+ emitterCh := make(chan LogEmitterChannel, len(logEmitters))
+
+ ctx, cancelFn := context.WithCancel(context.Background())
+ defer cancelFn()
+
+ for i := 0; i < len(logEmitters); i++ {
+ wg.Add(1)
+ go emitEvents(ctx, l, logEmitters[i], cfg, wg, emitterCh)
+ }
+
+ var emitErr error
+ total := 0
+
+ aggrChan := make(chan int, len(logEmitters))
+
+ go func() {
+ for emitter := range emitterCh {
+ if emitter.err != nil {
+ emitErr = emitter.err
+ cancelFn()
+ return
+ }
+ aggrChan <- emitter.logsEmitted
+ }
+ }()
+
+ wg.Wait()
+ close(emitterCh)
+
+ for i := 0; i < len(logEmitters); i++ {
+ total += <-aggrChan
+ }
+
+ if emitErr != nil {
+ return 0, emitErr
+ }
+
+ return int(total), nil
+}
+
+func getExpectedLogCount(cfg *Config) int64 {
+ if cfg.General.Generator == GeneratorType_WASP {
+ if cfg.Wasp.Load.RPS != 0 {
+ return cfg.Wasp.Load.RPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds()) * int64(cfg.General.EventsPerTx)
+ } else {
+ return cfg.Wasp.Load.LPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds())
+ }
+ }
+
+ return int64(len(cfg.General.EventsToEmit) * cfg.LoopedConfig.ExecutionCount * cfg.General.Contracts * cfg.General.EventsPerTx)
+}
+
+var chaosPauseSyncFn = func(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv) error {
+ rand.New(rand.NewSource(time.Now().UnixNano()))
+ randomBool := rand.Intn(2) == 0
+
+ randomNode := testEnv.ClCluster.Nodes[rand.Intn(len(testEnv.ClCluster.Nodes)-1)+1]
+ var component ctf_test_env.EnvComponent
+
+ if randomBool {
+ component = randomNode.EnvComponent
+ } else {
+ component = randomNode.PostgresDb.EnvComponent
+ }
+
+ pauseTimeSec := rand.Intn(20-5) + 5
+ l.Info().Str("Container", component.ContainerName).Int("Pause time", pauseTimeSec).Msg("Pausing component")
+ pauseTimeDur := time.Duration(pauseTimeSec) * time.Second
+ err := component.ChaosPause(l, pauseTimeDur)
+ l.Info().Str("Container", component.ContainerName).Msg("Component unpaused")
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+var executeChaosExperiment = func(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, cfg *Config, errorCh chan error) {
+ if cfg.ChaosConfig == nil || cfg.ChaosConfig.ExperimentCount == 0 {
+ errorCh <- nil
+ return
+ }
+
+ chaosChan := make(chan error, cfg.ChaosConfig.ExperimentCount)
+
+ wg := &sync.WaitGroup{}
+
+ go func() {
+ // if we wanted to have more than 1 container paused, we'd need to make sure we aren't trying to pause an already paused one
+ guardChan := make(chan struct{}, 1)
+
+ for i := 0; i < cfg.ChaosConfig.ExperimentCount; i++ {
+ wg.Add(1)
+ guardChan <- struct{}{}
+ go func() {
+ defer func() {
+ <-guardChan
+ wg.Done()
+ l.Info().Str("Current/Total", fmt.Sprintf("%d/%d", i, cfg.ChaosConfig.ExperimentCount)).Msg("Done with experiment")
+ }()
+ chaosChan <- chaosPauseSyncFn(l, testEnv)
+ }()
+ }
+
+ wg.Wait()
+
+ close(chaosChan)
+ }()
+
+ go func() {
+ for {
+ select {
+ case err, ok := <-chaosChan:
+ if !ok {
+ l.Info().Msg("All chaos experiments finished")
+ errorCh <- nil
+ return
+ } else {
+ if err != nil {
+ l.Err(err).Msg("Error encountered during chaos experiment")
+ errorCh <- err
+ return
+ }
+ }
+ }
+ }
+ }()
+}
+
+var GetFinalityDepth = func(chainId int64) (int64, error) {
+ var finalityDepth int64
+ switch chainId {
+ // Ethereum Sepolia
+ case 11155111:
+ finalityDepth = 50
+ // Polygon Mumbai
+ case 80001:
+ finalityDepth = 500
+ // Simulated network
+ case 1337:
+ finalityDepth = 10
+ default:
+ return 0, fmt.Errorf("No known finality depth for chain %d", chainId)
+ }
+
+ return finalityDepth, nil
+}
+
+var GetEndBlockToWaitFor = func(endBlock, chainId int64, cfg *Config) (int64, error) {
+ if cfg.General.UseFinalityTag {
+ return endBlock + 1, nil
+ }
+
+ finalityDepth, err := GetFinalityDepth(chainId)
+ if err != nil {
+ return 0, err
+ }
+
+ return endBlock + finalityDepth, nil
+}
+
+const (
+ automationDefaultUpkeepGasLimit = uint32(2500000)
+ automationDefaultLinkFunds = int64(9e18)
+ automationDefaultUpkeepsToDeploy = 10
+ automationExpectedData = "abcdef"
+ defaultAmountOfUpkeeps = 2
+)
+
+var (
+ defaultOCRRegistryConfig = contracts.KeeperRegistrySettings{
+ PaymentPremiumPPB: uint32(200000000),
+ FlatFeeMicroLINK: uint32(0),
+ BlockCountPerTurn: big.NewInt(10),
+ CheckGasLimit: uint32(2500000),
+ StalenessSeconds: big.NewInt(90000),
+ GasCeilingMultiplier: uint16(1),
+ MinUpkeepSpend: big.NewInt(0),
+ MaxPerformGas: uint32(5000000),
+ FallbackGasPrice: big.NewInt(2e11),
+ FallbackLinkPrice: big.NewInt(2e18),
+ MaxCheckDataSize: uint32(5000),
+ MaxPerformDataSize: uint32(5000),
+ }
+
+ automationDefaultRegistryConfig = contracts.KeeperRegistrySettings{
+ PaymentPremiumPPB: uint32(200000000),
+ FlatFeeMicroLINK: uint32(0),
+ BlockCountPerTurn: big.NewInt(10),
+ CheckGasLimit: uint32(2500000),
+ StalenessSeconds: big.NewInt(90000),
+ GasCeilingMultiplier: uint16(1),
+ MinUpkeepSpend: big.NewInt(0),
+ MaxPerformGas: uint32(5000000),
+ FallbackGasPrice: big.NewInt(2e11),
+ FallbackLinkPrice: big.NewInt(2e18),
+ MaxCheckDataSize: uint32(5000),
+ MaxPerformDataSize: uint32(5000),
+ }
+)
+
+func setupLogPollerTestDocker(
+ t *testing.T,
+ testName string,
+ registryVersion ethereum.KeeperRegistryVersion,
+ registryConfig contracts.KeeperRegistrySettings,
+ upkeepsNeeded int,
+ lpPollingInterval time.Duration,
+ finalityTagEnabled bool,
+) (
+ blockchain.EVMClient,
+ []*client.ChainlinkClient,
+ contracts.ContractDeployer,
+ contracts.LinkToken,
+ contracts.KeeperRegistry,
+ contracts.KeeperRegistrar,
+ *test_env.CLClusterTestEnv,
+) {
+ l := logging.GetTestLogger(t)
+ // Add registry version to config
+ registryConfig.RegistryVersion = registryVersion
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
+
+ finalityDepth, err := GetFinalityDepth(network.ChainID)
+ require.NoError(t, err, "Error getting finality depth")
+
+ // build the node config
+ clNodeConfig := node.NewConfig(node.NewBaseConfig())
+ syncInterval := models.MustMakeDuration(5 * time.Minute)
+ clNodeConfig.Feature.LogPoller = it_utils.Ptr[bool](true)
+ clNodeConfig.OCR2.Enabled = it_utils.Ptr[bool](true)
+ clNodeConfig.Keeper.TurnLookBack = it_utils.Ptr[int64](int64(0))
+ clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval
+ clNodeConfig.Keeper.Registry.PerformGasOverhead = it_utils.Ptr[uint32](uint32(150000))
+ clNodeConfig.P2P.V2.Enabled = it_utils.Ptr[bool](true)
+ clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"}
+ clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"}
+
+ //launch the environment
+ var env *test_env.CLClusterTestEnv
+ chainlinkNodeFunding := 0.5
+ l.Debug().Msgf("Funding amount: %f", chainlinkNodeFunding)
+ clNodesCount := 5
+
+ var logPolllerSettingsFn = func(chain *evmcfg.Chain) *evmcfg.Chain {
+ chain.LogPollInterval = models.MustNewDuration(lpPollingInterval)
+ chain.FinalityDepth = utils2.Ptr[uint32](uint32(finalityDepth))
+ chain.FinalityTagEnabled = utils2.Ptr[bool](finalityTagEnabled)
+ return chain
+ }
+
+ var evmClientSettingsFn = func(network *blockchain.EVMNetwork) *blockchain.EVMNetwork {
+ network.FinalityDepth = uint64(finalityDepth)
+ network.FinalityTag = finalityTagEnabled
+ return network
+ }
+
+ env, err = test_env.NewCLTestEnvBuilder().
+ WithTestLogger(t).
+ WithGeth().
+ WithCLNodes(clNodesCount).
+ WithCLNodeConfig(clNodeConfig).
+ WithFunding(big.NewFloat(chainlinkNodeFunding)).
+ WithChainOptions(logPolllerSettingsFn).
+ EVMClientNetworkOptions(evmClientSettingsFn).
+ WithStandardCleanup().
+ Build()
+ require.NoError(t, err, "Error deploying test environment")
+
+ env.ParallelTransactions(true)
+ nodeClients := env.ClCluster.NodeAPIs()
+ workerNodes := nodeClients[1:]
+
+ var linkToken contracts.LinkToken
+
+ switch network.ChainID {
+ // Simulated
+ case 1337:
+ linkToken, err = env.ContractDeployer.DeployLinkTokenContract()
+ // Ethereum Sepolia
+ case 11155111:
+ linkToken, err = env.ContractLoader.LoadLINKToken("0x779877A7B0D9E8603169DdbD7836e478b4624789")
+ // Polygon Mumbai
+ case 80001:
+ linkToken, err = env.ContractLoader.LoadLINKToken("0x326C977E6efc84E512bB9C30f76E30c160eD06FB")
+ default:
+ panic("Not implemented")
+ }
+ require.NoError(t, err, "Error loading/deploying LINK token")
+
+ linkBalance, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(linkToken.Address()))
+ require.NoError(t, err, "Error getting LINK balance")
+
+ l.Info().Str("Balance", big.NewInt(0).Div(linkBalance, big.NewInt(1e18)).String()).Msg("LINK balance")
+ minLinkBalanceSingleNode := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(9))
+ minLinkBalance := big.NewInt(0).Mul(minLinkBalanceSingleNode, big.NewInt(int64(upkeepsNeeded)))
+ if minLinkBalance.Cmp(linkBalance) < 0 {
+ require.FailNowf(t, "Not enough LINK", "Not enough LINK to run the test. Need at least %s", big.NewInt(0).Div(minLinkBalance, big.NewInt(1e18)).String())
+ }
+
+ registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar(
+ t,
+ registryVersion,
+ registryConfig,
+ linkToken,
+ env.ContractDeployer,
+ env.EVMClient,
+ )
+
+ // Fund the registry with LINK
+ err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(defaultAmountOfUpkeeps))))
+ require.NoError(t, err, "Funding keeper registry contract shouldn't fail")
+
+ err = actions.CreateOCRKeeperJobsLocal(l, nodeClients, registry.Address(), network.ChainID, 0, registryVersion)
+ require.NoError(t, err, "Error creating OCR Keeper Jobs")
+ ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(l, workerNodes, registryConfig, registrar.Address(), 30*time.Second, registry.RegistryOwnerAddress())
+ require.NoError(t, err, "Error building OCR config vars")
+ err = registry.SetConfig(automationDefaultRegistryConfig, ocrConfig)
+ require.NoError(t, err, "Registry config should be set successfully")
+ require.NoError(t, env.EVMClient.WaitForEvents(), "Waiting for config to be set")
+
+ return env.EVMClient, nodeClients, env.ContractDeployer, linkToken, registry, registrar, env
+}
diff --git a/integration-tests/universal/log_poller/scenarios.go b/integration-tests/universal/log_poller/scenarios.go
new file mode 100644
index 0000000000..d14a3bcb2a
--- /dev/null
+++ b/integration-tests/universal/log_poller/scenarios.go
@@ -0,0 +1,498 @@
+package logpoller
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/onsi/gomega"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink/integration-tests/actions"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
+ core_logger "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/stretchr/testify/require"
+)
+
+func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
+ l := logging.GetTestLogger(t)
+ coreLogger := core_logger.TestLogger(t) //needed by ORM ¯\_(ツ)_/¯
+
+ if cfg.General.EventsToEmit == nil || len(cfg.General.EventsToEmit) == 0 {
+ l.Warn().Msg("No events to emit specified, using all events from log emitter contract")
+ for _, event := range EmitterABI.Events {
+ cfg.General.EventsToEmit = append(cfg.General.EventsToEmit, event)
+ }
+ }
+
+ l.Info().Msg("Starting basic log poller test")
+
+ var (
+ err error
+ testName = "basic-log-poller"
+ upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit)
+ )
+
+ chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupLogPollerTestDocker(
+ t, testName, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(500*time.Millisecond), cfg.General.UseFinalityTag,
+ )
+
+ _, upkeepIDs := actions.DeployConsumers(
+ t,
+ registry,
+ registrar,
+ linkToken,
+ contractDeployer,
+ chainClient,
+ upKeepsNeeded,
+ big.NewInt(automationDefaultLinkFunds),
+ automationDefaultUpkeepGasLimit,
+ true,
+ false,
+ )
+
+ // Deploy Log Emitter contracts
+ logEmitters := make([]*contracts.LogEmitter, 0)
+ for i := 0; i < cfg.General.Contracts; i++ {
+ logEmitter, err := testEnv.ContractDeployer.DeployLogEmitterContract()
+ logEmitters = append(logEmitters, &logEmitter)
+ require.NoError(t, err, "Error deploying log emitter contract")
+ l.Info().Str("Contract address", logEmitter.Address().Hex()).Msg("Log emitter contract deployed")
+ time.Sleep(200 * time.Millisecond)
+ }
+
+ // Register log triggered upkeep for each combination of log emitter contract and event signature (topic)
+ // We need to register a separate upkeep for each event signature, because log trigger doesn't support multiple topics (even if log poller does)
+ for i := 0; i < len(upkeepIDs); i++ {
+ emitterAddress := (*logEmitters[i%cfg.General.Contracts]).Address()
+ upkeepID := upkeepIDs[i]
+ topicId := cfg.General.EventsToEmit[i%len(cfg.General.EventsToEmit)].ID
+
+ l.Info().Int("Upkeep id", int(upkeepID.Int64())).Str("Emitter address", emitterAddress.String()).Str("Topic", topicId.Hex()).Msg("Registering log trigger for log emitter")
+ err = registerSingleTopicFilter(registry, upkeepID, emitterAddress, topicId)
+ randomWait(50, 200)
+ require.NoError(t, err, "Error registering log trigger for log emitter")
+ }
+
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Error encountered when waiting for setting trigger config for upkeeps")
+
+ // Make sure that all nodes have expected filters registered before starting to emit events
+ expectedFilters := getExpectedFilters(logEmitters, cfg)
+ gom := gomega.NewGomegaWithT(t)
+ gom.Eventually(func(g gomega.Gomega) {
+ for i := 1; i < len(testEnv.ClCluster.Nodes); i++ {
+ nodeName := testEnv.ClCluster.Nodes[i].ContainerName
+ l.Info().Str("Node name", nodeName).Msg("Fetching filters from log poller's DB")
+
+ hasFilters, err := nodeHasExpectedFilters(expectedFilters, coreLogger, testEnv.EVMClient.GetChainID(), testEnv.ClCluster.Nodes[i].PostgresDb)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if node has expected filters. Retrying...")
+ return
+ }
+
+ g.Expect(hasFilters).To(gomega.BeTrue(), "Not all expected filters were found in the DB")
+ }
+ }, "30s", "1s").Should(gomega.Succeed())
+ l.Info().Msg("All nodes have expected filters registered")
+ l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
+
+ // Save block number before starting to emit events, so that we can later use it when querying logs
+ sb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+ startBlock := int64(sb)
+
+ l.Info().Msg("STARTING EVENT EMISSION")
+ startTime := time.Now()
+
+ // Start chaos experimnents by randomly pausing random containers (Chainlink nodes or their DBs)
+ chaosDoneCh := make(chan error, 1)
+ go func() {
+ executeChaosExperiment(l, testEnv, cfg, chaosDoneCh)
+ }()
+
+ totalLogsEmitted, err := executeGenerator(t, cfg, logEmitters)
+ endTime := time.Now()
+ require.NoError(t, err, "Error executing event generator")
+
+ expectedLogsEmitted := getExpectedLogCount(cfg)
+ duration := int(endTime.Sub(startTime).Seconds())
+ l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
+
+ // Save block number after finishing to emit events, so that we can later use it when querying logs
+ eb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+
+ endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
+ require.NoError(t, err, "Error getting end block to wait for")
+
+ l.Info().Msg("Waiting before proceeding with test until all chaos experiments finish")
+ chaosError := <-chaosDoneCh
+ require.NoError(t, chaosError, "Error encountered during chaos experiment")
+
+ // Wait until last block in which events were emitted has been finalised
+ // how long should we wait here until all logs are processed? wait for block X to be processed by all nodes?
+ waitDuration := "15m"
+ l.Warn().Str("Duration", waitDuration).Msg("Waiting for logs to be processed by all nodes and for chain to advance beyond finality")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ hasAdvanced, err := chainHasFinalisedEndBlock(l, testEnv.EVMClient, endBlock)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if chain has advanced beyond finality. Retrying...")
+ }
+ g.Expect(hasAdvanced).To(gomega.BeTrue(), "Chain has not advanced beyond finality")
+ }, waitDuration, "30s").Should(gomega.Succeed())
+
+ l.Warn().Str("Duration", "1m").Msg("Waiting for all CL nodes to have end block finalised")
+ gom.Eventually(func(g gomega.Gomega) {
+ hasFinalised, err := logPollerHasFinalisedEndBlock(endBlock, testEnv.EVMClient.GetChainID(), l, coreLogger, testEnv.ClCluster)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if nodes have finalised end block. Retrying...")
+ }
+ g.Expect(hasFinalised).To(gomega.BeTrue(), "Some nodes have not finalised end block")
+ }, "1m", "30s").Should(gomega.Succeed())
+
+ gom.Eventually(func(g gomega.Gomega) {
+ logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), totalLogsEmitted, expectedFilters, l, coreLogger, testEnv.ClCluster)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if CL nodes have expected log count. Retrying...")
+ }
+ g.Expect(logCountMatches).To(gomega.BeTrue(), "Not all CL nodes have expected log count")
+ }, waitDuration, "5s").Should(gomega.Succeed())
+
+ // Wait until all CL nodes have exactly the same logs emitted by test contracts as the EVM node has
+ logConsistencyWaitDuration := "1m"
+ l.Warn().Str("Duration", logConsistencyWaitDuration).Msg("Waiting for CL nodes to have all the logs that EVM node has")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ missingLogs, err := getMissingLogs(startBlock, endBlock, logEmitters, testEnv.EVMClient, testEnv.ClCluster, l, coreLogger, cfg)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error getting missing logs. Retrying...")
+ }
+
+ if !missingLogs.IsEmpty() {
+ printMissingLogsByType(missingLogs, l, cfg)
+ }
+ g.Expect(missingLogs.IsEmpty()).To(gomega.BeTrue(), "Some CL nodes were missing logs")
+ }, logConsistencyWaitDuration, "5s").Should(gomega.Succeed())
+}
+
+func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string) {
+ l := logging.GetTestLogger(t)
+ coreLogger := core_logger.TestLogger(t) //needed by ORM ¯\_(ツ)_/¯
+
+ if cfg.General.EventsToEmit == nil || len(cfg.General.EventsToEmit) == 0 {
+ l.Warn().Msg("No events to emit specified, using all events from log emitter contract")
+ for _, event := range EmitterABI.Events {
+ cfg.General.EventsToEmit = append(cfg.General.EventsToEmit, event)
+ }
+ }
+
+ l.Info().Msg("Starting replay log poller test")
+
+ var (
+ err error
+ testName = "replay-log-poller"
+ upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit)
+ )
+
+ // we set blockBackfillDepth to 0, to make sure nothing will be backfilled and won't interfere with our test
+ chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupLogPollerTestDocker(
+ t, testName, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(1000*time.Millisecond), cfg.General.UseFinalityTag)
+
+ _, upkeepIDs := actions.DeployConsumers(
+ t,
+ registry,
+ registrar,
+ linkToken,
+ contractDeployer,
+ chainClient,
+ upKeepsNeeded,
+ big.NewInt(automationDefaultLinkFunds),
+ automationDefaultUpkeepGasLimit,
+ true,
+ false,
+ )
+
+ // Deploy Log Emitter contracts
+ logEmitters := make([]*contracts.LogEmitter, 0)
+ for i := 0; i < cfg.General.Contracts; i++ {
+ logEmitter, err := testEnv.ContractDeployer.DeployLogEmitterContract()
+ logEmitters = append(logEmitters, &logEmitter)
+ require.NoError(t, err, "Error deploying log emitter contract")
+ l.Info().Str("Contract address", logEmitter.Address().Hex()).Msg("Log emitter contract deployed")
+ time.Sleep(200 * time.Millisecond)
+ }
+
+ //wait for contracts to be uploaded to chain, TODO: could make this wait fluent
+ time.Sleep(5 * time.Second)
+
+ // Save block number before starting to emit events, so that we can later use it when querying logs
+ sb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+ startBlock := int64(sb)
+
+ l.Info().Msg("STARTING EVENT EMISSION")
+ startTime := time.Now()
+ totalLogsEmitted, err := executeGenerator(t, cfg, logEmitters)
+ endTime := time.Now()
+ require.NoError(t, err, "Error executing event generator")
+ expectedLogsEmitted := getExpectedLogCount(cfg)
+ duration := int(endTime.Sub(startTime).Seconds())
+ l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
+
+ // Save block number after finishing to emit events, so that we can later use it when querying logs
+ eb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+
+ endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
+ require.NoError(t, err, "Error getting end block to wait for")
+
+ // Lets make sure no logs are in DB yet
+ expectedFilters := getExpectedFilters(logEmitters, cfg)
+ logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), 0, expectedFilters, l, coreLogger, testEnv.ClCluster)
+ require.NoError(t, err, "Error checking if CL nodes have expected log count")
+ require.True(t, logCountMatches, "Some CL nodes already had logs in DB")
+ l.Info().Msg("No logs were saved by CL nodes yet, as expected. Proceeding.")
+
+ // Register log triggered upkeep for each combination of log emitter contract and event signature (topic)
+ // We need to register a separate upkeep for each event signature, because log trigger doesn't support multiple topics (even if log poller does)
+ for i := 0; i < len(upkeepIDs); i++ {
+ emitterAddress := (*logEmitters[i%cfg.General.Contracts]).Address()
+ upkeepID := upkeepIDs[i]
+ topicId := cfg.General.EventsToEmit[i%len(cfg.General.EventsToEmit)].ID
+
+ l.Info().Int("Upkeep id", int(upkeepID.Int64())).Str("Emitter address", emitterAddress.String()).Str("Topic", topicId.Hex()).Msg("Registering log trigger for log emitter")
+ err = registerSingleTopicFilter(registry, upkeepID, emitterAddress, topicId)
+ require.NoError(t, err, "Error registering log trigger for log emitter")
+ }
+
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Error encountered when waiting for setting trigger config for upkeeps")
+
+ // Make sure that all nodes have expected filters registered before starting to emit events
+ gom := gomega.NewGomegaWithT(t)
+ gom.Eventually(func(g gomega.Gomega) {
+ for i := 1; i < len(testEnv.ClCluster.Nodes); i++ {
+ nodeName := testEnv.ClCluster.Nodes[i].ContainerName
+ l.Info().Str("Node name", nodeName).Msg("Fetching filters from log poller's DB")
+
+ hasFilters, err := nodeHasExpectedFilters(expectedFilters, coreLogger, testEnv.EVMClient.GetChainID(), testEnv.ClCluster.Nodes[i].PostgresDb)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if node has expected filters. Retrying...")
+ return
+ }
+
+ g.Expect(hasFilters).To(gomega.BeTrue(), "Not all expected filters were found in the DB")
+ }
+ }, "30s", "1s").Should(gomega.Succeed())
+ l.Info().Msg("All nodes have expected filters registered")
+ l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
+
+ l.Warn().Str("Duration", "1m").Msg("Waiting for all CL nodes to have end block finalised")
+ gom.Eventually(func(g gomega.Gomega) {
+ hasFinalised, err := logPollerHasFinalisedEndBlock(endBlock, testEnv.EVMClient.GetChainID(), l, coreLogger, testEnv.ClCluster)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if nodes have finalised end block. Retrying...")
+ }
+ g.Expect(hasFinalised).To(gomega.BeTrue(), "Some nodes have not finalised end block")
+ }, "1m", "30s").Should(gomega.Succeed())
+
+ // Trigger replay
+ l.Info().Msg("Triggering log poller's replay")
+ for i := 1; i < len(testEnv.ClCluster.Nodes); i++ {
+ nodeName := testEnv.ClCluster.Nodes[i].ContainerName
+ response, _, err := testEnv.ClCluster.Nodes[i].API.ReplayLogPollerFromBlock(startBlock, testEnv.EVMClient.GetChainID().Int64())
+ require.NoError(t, err, "Error triggering log poller's replay on node %s", nodeName)
+ require.Equal(t, "Replay started", response.Data.Attributes.Message, "Unexpected response message from log poller's replay")
+ }
+
+ l.Warn().Str("Duration", consistencyTimeout).Msg("Waiting for logs to be processed by all nodes and for chain to advance beyond finality")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), totalLogsEmitted, expectedFilters, l, coreLogger, testEnv.ClCluster)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if CL nodes have expected log count. Retrying...")
+ }
+ g.Expect(logCountMatches).To(gomega.BeTrue(), "Not all CL nodes have expected log count")
+ }, consistencyTimeout, "30s").Should(gomega.Succeed())
+
+ // Wait until all CL nodes have exactly the same logs emitted by test contracts as the EVM node has
+ l.Warn().Str("Duration", consistencyTimeout).Msg("Waiting for CL nodes to have all the logs that EVM node has")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ missingLogs, err := getMissingLogs(startBlock, endBlock, logEmitters, testEnv.EVMClient, testEnv.ClCluster, l, coreLogger, cfg)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error getting missing logs. Retrying...")
+ }
+
+ if !missingLogs.IsEmpty() {
+ printMissingLogsByType(missingLogs, l, cfg)
+ }
+ g.Expect(missingLogs.IsEmpty()).To(gomega.BeTrue(), "Some CL nodes were missing logs")
+ }, consistencyTimeout, "10s").Should(gomega.Succeed())
+}
+
+type FinalityBlockFn = func(chainId int64, endBlock int64) (int64, error)
+
+func ExecuteCILogPollerTest(t *testing.T, cfg *Config) {
+ l := logging.GetTestLogger(t)
+ coreLogger := core_logger.TestLogger(t) //needed by ORM ¯\_(ツ)_/¯
+
+ if cfg.General.EventsToEmit == nil || len(cfg.General.EventsToEmit) == 0 {
+ l.Warn().Msg("No events to emit specified, using all events from log emitter contract")
+ for _, event := range EmitterABI.Events {
+ cfg.General.EventsToEmit = append(cfg.General.EventsToEmit, event)
+ }
+ }
+
+ l.Info().Msg("Starting CI log poller test")
+
+ var (
+ err error
+ testName = "ci-log-poller"
+ upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit)
+ )
+
+ chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupLogPollerTestDocker(
+ t, testName, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(1000*time.Millisecond), cfg.General.UseFinalityTag,
+ )
+
+ _, upkeepIDs := actions.DeployConsumers(
+ t,
+ registry,
+ registrar,
+ linkToken,
+ contractDeployer,
+ chainClient,
+ upKeepsNeeded,
+ big.NewInt(automationDefaultLinkFunds),
+ automationDefaultUpkeepGasLimit,
+ true,
+ false,
+ )
+
+ // Deploy Log Emitter contracts
+ logEmitters := make([]*contracts.LogEmitter, 0)
+ for i := 0; i < cfg.General.Contracts; i++ {
+ logEmitter, err := testEnv.ContractDeployer.DeployLogEmitterContract()
+ logEmitters = append(logEmitters, &logEmitter)
+ require.NoError(t, err, "Error deploying log emitter contract")
+ l.Info().Str("Contract address", logEmitter.Address().Hex()).Msg("Log emitter contract deployed")
+ time.Sleep(200 * time.Millisecond)
+ }
+
+ // Register log triggered upkeep for each combination of log emitter contract and event signature (topic)
+ // We need to register a separate upkeep for each event signature, because log trigger doesn't support multiple topics (even if log poller does)
+ for i := 0; i < len(upkeepIDs); i++ {
+ emitterAddress := (*logEmitters[i%cfg.General.Contracts]).Address()
+ upkeepID := upkeepIDs[i]
+ topicId := cfg.General.EventsToEmit[i%len(cfg.General.EventsToEmit)].ID
+
+ l.Info().Int("Upkeep id", int(upkeepID.Int64())).Str("Emitter address", emitterAddress.String()).Str("Topic", topicId.Hex()).Msg("Registering log trigger for log emitter")
+ err = registerSingleTopicFilter(registry, upkeepID, emitterAddress, topicId)
+ randomWait(50, 200)
+ require.NoError(t, err, "Error registering log trigger for log emitter")
+ }
+
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Error encountered when waiting for setting trigger config for upkeeps")
+
+ // Make sure that all nodes have expected filters registered before starting to emit events
+ expectedFilters := getExpectedFilters(logEmitters, cfg)
+ gom := gomega.NewGomegaWithT(t)
+ gom.Eventually(func(g gomega.Gomega) {
+ for i := 1; i < len(testEnv.ClCluster.Nodes); i++ {
+ nodeName := testEnv.ClCluster.Nodes[i].ContainerName
+ l.Info().Str("Node name", nodeName).Msg("Fetching filters from log poller's DB")
+
+ hasFilters, err := nodeHasExpectedFilters(expectedFilters, coreLogger, testEnv.EVMClient.GetChainID(), testEnv.ClCluster.Nodes[i].PostgresDb)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if node has expected filters. Retrying...")
+ return
+ }
+
+ g.Expect(hasFilters).To(gomega.BeTrue(), "Not all expected filters were found in the DB")
+ }
+ }, "1m", "1s").Should(gomega.Succeed())
+ l.Info().Msg("All nodes have expected filters registered")
+ l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
+
+ // Save block number before starting to emit events, so that we can later use it when querying logs
+ sb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+ startBlock := int64(sb)
+
+ l.Info().Msg("STARTING EVENT EMISSION")
+ startTime := time.Now()
+
+ // Start chaos experimnents by randomly pausing random containers (Chainlink nodes or their DBs)
+ chaosDoneCh := make(chan error, 1)
+ go func() {
+ executeChaosExperiment(l, testEnv, cfg, chaosDoneCh)
+ }()
+
+ totalLogsEmitted, err := executeGenerator(t, cfg, logEmitters)
+ endTime := time.Now()
+ require.NoError(t, err, "Error executing event generator")
+
+ expectedLogsEmitted := getExpectedLogCount(cfg)
+ duration := int(endTime.Sub(startTime).Seconds())
+ l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
+
+ // Save block number after finishing to emit events, so that we can later use it when querying logs
+ eb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+
+ endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
+ require.NoError(t, err, "Error getting end block to wait for")
+
+ l.Info().Msg("Waiting before proceeding with test until all chaos experiments finish")
+ chaosError := <-chaosDoneCh
+ require.NoError(t, chaosError, "Error encountered during chaos experiment")
+
+ // Wait until last block in which events were emitted has been finalised (with buffer)
+ waitDuration := "45m"
+ l.Warn().Str("Duration", waitDuration).Msg("Waiting for chain to advance beyond finality")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ hasAdvanced, err := chainHasFinalisedEndBlock(l, testEnv.EVMClient, endBlock)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if chain has advanced beyond finality. Retrying...")
+ }
+ g.Expect(hasAdvanced).To(gomega.BeTrue(), "Chain has not advanced beyond finality")
+ }, waitDuration, "30s").Should(gomega.Succeed())
+
+ l.Warn().Str("Duration", waitDuration).Msg("Waiting for all CL nodes to have end block finalised")
+ gom.Eventually(func(g gomega.Gomega) {
+ hasFinalised, err := logPollerHasFinalisedEndBlock(endBlock, testEnv.EVMClient.GetChainID(), l, coreLogger, testEnv.ClCluster)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if nodes have finalised end block. Retrying...")
+ }
+ g.Expect(hasFinalised).To(gomega.BeTrue(), "Some nodes have not finalised end block")
+ }, waitDuration, "30s").Should(gomega.Succeed())
+
+ // Wait until all CL nodes have exactly the same logs emitted by test contracts as the EVM node has
+ logConsistencyWaitDuration := "10m"
+ l.Warn().Str("Duration", logConsistencyWaitDuration).Msg("Waiting for CL nodes to have all the logs that EVM node has")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ missingLogs, err := getMissingLogs(startBlock, endBlock, logEmitters, testEnv.EVMClient, testEnv.ClCluster, l, coreLogger, cfg)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error getting missing logs. Retrying...")
+ }
+
+ if !missingLogs.IsEmpty() {
+ printMissingLogsByType(missingLogs, l, cfg)
+ }
+ g.Expect(missingLogs.IsEmpty()).To(gomega.BeTrue(), "Some CL nodes were missing logs")
+ }, logConsistencyWaitDuration, "20s").Should(gomega.Succeed())
+
+ evmLogs, _ := getEVMLogs(startBlock, endBlock, logEmitters, testEnv.EVMClient, l, cfg)
+
+ if totalLogsEmitted != len(evmLogs) {
+ l.Warn().Int("Total logs emitted", totalLogsEmitted).Int("Total logs in EVM", len(evmLogs)).Msg("Test passed, but total logs emitted does not match total logs in EVM")
+ }
+}
From 305356206be809671fd497345d3851028ab60d9f Mon Sep 17 00:00:00 2001
From: Cedric
Date: Fri, 3 Nov 2023 12:27:54 +0000
Subject: [PATCH 068/327] [BCF-2750] Reorder telemetry params (#11147)
---
core/services/functions/listener_test.go | 2 +-
core/services/ocr/delegate.go | 4 ++--
core/services/ocr2/delegate.go | 22 +++++++++----------
.../ocr2/plugins/generic/telemetry_adapter.go | 2 +-
.../plugins/generic/telemetry_adapter_test.go | 2 +-
core/services/ocrcommon/telemetry_test.go | 8 +++----
core/services/telemetry/common.go | 2 +-
core/services/telemetry/ingress.go | 14 ++++++------
core/services/telemetry/ingress_batch.go | 14 ++++++------
core/services/telemetry/ingress_batch_test.go | 2 +-
core/services/telemetry/ingress_test.go | 2 +-
core/services/telemetry/manager.go | 6 ++---
core/services/telemetry/manager_test.go | 18 +++++++--------
core/services/telemetry/noop.go | 2 +-
14 files changed, 50 insertions(+), 50 deletions(-)
diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go
index 007a2a9168..3b7ed46988 100644
--- a/core/services/functions/listener_test.go
+++ b/core/services/functions/listener_test.go
@@ -125,7 +125,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe
ingressClient := sync_mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
- monEndpoint := ingressAgent.GenMonitoringEndpoint(contractAddress, synchronization.FunctionsRequests, "test-network", "test-chainID")
+ monEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", contractAddress, synchronization.FunctionsRequests)
s4Storage := s4_mocks.NewStorage(t)
client := chain.Client()
diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go
index b761690485..bbed43c151 100644
--- a/core/services/ocr/delegate.go
+++ b/core/services/ocr/delegate.go
@@ -297,7 +297,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) (services []job.ServiceCtx, err e
enhancedTelemChan := make(chan ocrcommon.EnhancedTelemetryData, 100)
if ocrcommon.ShouldCollectEnhancedTelemetry(&jb) {
- enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, enhancedTelemChan, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(concreteSpec.ContractAddress.String(), synchronization.EnhancedEA, "EVM", chain.ID().String()), lggr.Named("EnhancedTelemetry"))
+ enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, enhancedTelemChan, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint("EVM", chain.ID().String(), concreteSpec.ContractAddress.String(), synchronization.EnhancedEA), lggr.Named("EnhancedTelemetry"))
services = append(services, enhancedTelemService)
}
@@ -319,7 +319,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) (services []job.ServiceCtx, err e
Logger: ocrLogger,
V1Bootstrappers: v1BootstrapPeers,
V2Bootstrappers: v2Bootstrappers,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(concreteSpec.ContractAddress.String(), synchronization.OCR, "EVM", chain.ID().String()),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint("EVM", chain.ID().String(), concreteSpec.ContractAddress.String(), synchronization.OCR),
ConfigOverrider: configOverrider,
})
if err != nil {
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index e822fd5d8f..39a8c84d6b 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -564,10 +564,10 @@ func (d *Delegate) newServicesGenericPlugin(
srvs = append(srvs, provider)
oracleEndpoint := d.monitoringEndpointGen.GenMonitoringEndpoint(
- spec.ContractID,
- synchronization.TelemetryType(cconf.TelemetryType),
rid.Network,
rid.ChainID,
+ spec.ContractID,
+ synchronization.TelemetryType(cconf.TelemetryType),
)
oracleArgs := libocr2.OCR2OracleArgs{
BinaryNetworkEndpointFactory: d.peerWrapper.Peer2,
@@ -686,7 +686,7 @@ func (d *Delegate) newServicesMercury(
Database: ocrDB,
LocalConfig: lc,
Logger: ocrLogger,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.FeedID.String(), synchronization.OCR3Mercury, rid.Network, rid.ChainID),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), synchronization.OCR3Mercury),
OffchainConfigDigester: mercuryProvider.OffchainConfigDigester(),
OffchainKeyring: kb,
OnchainKeyring: kb,
@@ -697,7 +697,7 @@ func (d *Delegate) newServicesMercury(
mercuryServices, err2 := mercury.NewServices(jb, mercuryProvider, d.pipelineRunner, runResults, lggr, oracleArgsNoPlugin, d.cfg.JobPipeline(), chEnhancedTelem, chain, d.mercuryORM, (mercuryutils.FeedID)(*spec.FeedID))
if ocrcommon.ShouldCollectEnhancedTelemetryMercury(jb) {
- enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, chEnhancedTelem, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(spec.FeedID.String(), synchronization.EnhancedEAMercury, rid.Network, rid.ChainID), lggr.Named("EnhancedTelemetryMercury"))
+ enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, chEnhancedTelem, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), synchronization.EnhancedEAMercury), lggr.Named("EnhancedTelemetryMercury"))
mercuryServices = append(mercuryServices, enhancedTelemService)
}
@@ -728,7 +728,7 @@ func (d *Delegate) newServicesMedian(
Database: ocrDB,
LocalConfig: lc,
Logger: ocrLogger,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.OCR2Median, rid.Network, rid.ChainID),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2Median),
OffchainKeyring: kb,
OnchainKeyring: kb,
}
@@ -744,7 +744,7 @@ func (d *Delegate) newServicesMedian(
medianServices, err2 := median.NewMedianServices(ctx, jb, d.isNewlyCreatedJob, relayer, d.pipelineRunner, runResults, lggr, oracleArgsNoPlugin, mConfig, enhancedTelemChan, errorLog)
if ocrcommon.ShouldCollectEnhancedTelemetry(&jb) {
- enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, enhancedTelemChan, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.EnhancedEA, rid.Network, rid.ChainID), lggr.Named("EnhancedTelemetry"))
+ enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, enhancedTelemChan, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.EnhancedEA), lggr.Named("EnhancedTelemetry"))
medianServices = append(medianServices, enhancedTelemService)
}
@@ -965,7 +965,7 @@ func (d *Delegate) newServicesOCR2VRF(
VRFContractTransmitter: vrfProvider.ContractTransmitter(),
VRFDatabase: ocrDB,
VRFLocalConfig: lc,
- VRFMonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.OCR2VRF, rid.Network, rid.ChainID),
+ VRFMonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2VRF),
DKGContractConfigTracker: dkgProvider.ContractConfigTracker(),
DKGOffchainConfigDigester: dkgProvider.OffchainConfigDigester(),
DKGContract: dkgpkg.NewOnchainContract(dkgContract, &altbn_128.G2{}),
@@ -1104,7 +1104,7 @@ func (d *Delegate) newServicesOCR2Keepers21(
ContractConfigTracker: keeperProvider.ContractConfigTracker(),
KeepersDatabase: ocrDB,
Logger: ocrLogger,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.OCR2Automation, rid.Network, rid.ChainID),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2Automation),
OffchainConfigDigester: keeperProvider.OffchainConfigDigester(),
OffchainKeyring: kb,
OnchainKeyring: services.Keyring(),
@@ -1249,7 +1249,7 @@ func (d *Delegate) newServicesOCR2Keepers20(
KeepersDatabase: ocrDB,
LocalConfig: lc,
Logger: ocrLogger,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.OCR2Automation, rid.Network, rid.ChainID),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2Automation),
OffchainConfigDigester: keeperProvider.OffchainConfigDigester(),
OffchainKeyring: kb,
OnchainKeyring: kb,
@@ -1358,7 +1358,7 @@ func (d *Delegate) newServicesOCR2Functions(
Database: functionsOcrDB,
LocalConfig: lc,
Logger: ocrLogger,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.OCR2Functions, rid.Network, rid.ChainID),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2Functions),
OffchainConfigDigester: functionsProvider.OffchainConfigDigester(),
OffchainKeyring: kb,
OnchainKeyring: kb,
@@ -1422,7 +1422,7 @@ func (d *Delegate) newServicesOCR2Functions(
ContractID: spec.ContractID,
Logger: lggr,
MailMon: d.mailMon,
- URLsMonEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.FunctionsRequests, rid.Network, rid.ChainID),
+ URLsMonEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.FunctionsRequests),
EthKeystore: d.ethKs,
ThresholdKeyShare: thresholdKeyShare,
LogPollerWrapper: functionsProvider.LogPollerWrapper(),
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter.go b/core/services/ocr2/plugins/generic/telemetry_adapter.go
index e7f87dcd46..51d94f5cfe 100644
--- a/core/services/ocr2/plugins/generic/telemetry_adapter.go
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter.go
@@ -52,7 +52,7 @@ func (t *TelemetryAdapter) getOrCreateEndpoint(network string, chainID string, c
key := [4]string{network, chainID, contractID, telemetryType}
e, ok := t.endpoints[key]
if !ok {
- e = t.endpointGenerator.GenMonitoringEndpoint(contractID, synchronization.TelemetryType(telemetryType), network, chainID)
+ e = t.endpointGenerator.GenMonitoringEndpoint(network, chainID, contractID, synchronization.TelemetryType(telemetryType))
t.endpoints[key] = e
}
return e, nil
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
index 9c42b0f85d..e137343f2b 100644
--- a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
@@ -24,7 +24,7 @@ func (m *mockEndpoint) SendLog(payload []byte) { m.payload = payload }
type mockGenerator struct{}
-func (m *mockGenerator) GenMonitoringEndpoint(contractID string, telemetryType synchronization.TelemetryType, network string, chainID string) commontypes.MonitoringEndpoint {
+func (m *mockGenerator) GenMonitoringEndpoint(network string, chainID string, contractID string, telemetryType synchronization.TelemetryType) commontypes.MonitoringEndpoint {
return &mockEndpoint{
network: network,
chainID: chainID,
diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go
index e6a798780b..9e3dedce8a 100644
--- a/core/services/ocrcommon/telemetry_test.go
+++ b/core/services/ocrcommon/telemetry_test.go
@@ -189,7 +189,7 @@ func TestSendEATelemetry(t *testing.T) {
wg := sync.WaitGroup{}
ingressClient := mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
- monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("0xa", synchronization.EnhancedEA, "test-network", "test-chainID")
+ monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.EnhancedEA)
var sentMessage []byte
ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) {
@@ -305,7 +305,7 @@ func TestCollectAndSend(t *testing.T) {
wg := sync.WaitGroup{}
ingressClient := mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
- monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("0xa", synchronization.EnhancedEA, "test-network", "test-chainID")
+ monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.EnhancedEA)
ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) {
wg.Done()
})
@@ -548,7 +548,7 @@ func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) {
wg := sync.WaitGroup{}
ingressClient := mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
- monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("0xa", synchronization.EnhancedEAMercury, "test-network", "test-chainID")
+ monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.EnhancedEAMercury)
var sentMessage []byte
ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) {
@@ -664,7 +664,7 @@ func TestCollectMercuryEnhancedTelemetryV2(t *testing.T) {
wg := sync.WaitGroup{}
ingressClient := mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient)
- monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("0xa", synchronization.EnhancedEAMercury, "test-network", "test-chainID")
+ monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.EnhancedEAMercury)
var sentMessage []byte
ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) {
diff --git a/core/services/telemetry/common.go b/core/services/telemetry/common.go
index 5a3f6706f7..37a92f16c6 100644
--- a/core/services/telemetry/common.go
+++ b/core/services/telemetry/common.go
@@ -7,5 +7,5 @@ import (
)
type MonitoringEndpointGenerator interface {
- GenMonitoringEndpoint(contractID string, telemType synchronization.TelemetryType, network string, chainID string) ocrtypes.MonitoringEndpoint
+ GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) ocrtypes.MonitoringEndpoint
}
diff --git a/core/services/telemetry/ingress.go b/core/services/telemetry/ingress.go
index 637fa0dd3b..266155095b 100644
--- a/core/services/telemetry/ingress.go
+++ b/core/services/telemetry/ingress.go
@@ -18,25 +18,25 @@ func NewIngressAgentWrapper(telemetryIngressClient synchronization.TelemetryServ
return &IngressAgentWrapper{telemetryIngressClient}
}
-func (t *IngressAgentWrapper) GenMonitoringEndpoint(contractID string, telemType synchronization.TelemetryType, network string, chainID string) ocrtypes.MonitoringEndpoint {
- return NewIngressAgent(t.telemetryIngressClient, contractID, telemType, network, chainID)
+func (t *IngressAgentWrapper) GenMonitoringEndpoint(network, chainID string, contractID string, telemType synchronization.TelemetryType) ocrtypes.MonitoringEndpoint {
+ return NewIngressAgent(t.telemetryIngressClient, network, chainID, contractID, telemType)
}
type IngressAgent struct {
telemetryIngressClient synchronization.TelemetryService
- contractID string
- telemType synchronization.TelemetryType
network string
chainID string
+ contractID string
+ telemType synchronization.TelemetryType
}
-func NewIngressAgent(telemetryIngressClient synchronization.TelemetryService, contractID string, telemType synchronization.TelemetryType, network string, chainID string) *IngressAgent {
+func NewIngressAgent(telemetryIngressClient synchronization.TelemetryService, network string, chainID string, contractID string, telemType synchronization.TelemetryType) *IngressAgent {
return &IngressAgent{
telemetryIngressClient,
- contractID,
- telemType,
network,
chainID,
+ contractID,
+ telemType,
}
}
diff --git a/core/services/telemetry/ingress_batch.go b/core/services/telemetry/ingress_batch.go
index df86085359..bb08c76d7e 100644
--- a/core/services/telemetry/ingress_batch.go
+++ b/core/services/telemetry/ingress_batch.go
@@ -21,27 +21,27 @@ func NewIngressAgentBatchWrapper(telemetryIngressBatchClient synchronization.Tel
}
// GenMonitoringEndpoint returns a new ingress batch agent instantiated with the batch client and a contractID
-func (t *IngressAgentBatchWrapper) GenMonitoringEndpoint(contractID string, telemType synchronization.TelemetryType, network string, chainID string) ocrtypes.MonitoringEndpoint {
- return NewIngressAgentBatch(t.telemetryIngressBatchClient, contractID, telemType, network, chainID)
+func (t *IngressAgentBatchWrapper) GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) ocrtypes.MonitoringEndpoint {
+ return NewIngressAgentBatch(t.telemetryIngressBatchClient, network, chainID, contractID, telemType)
}
// IngressAgentBatch allows for sending batch telemetry for a given contractID
type IngressAgentBatch struct {
telemetryIngressBatchClient synchronization.TelemetryService
- contractID string
- telemType synchronization.TelemetryType
network string
chainID string
+ contractID string
+ telemType synchronization.TelemetryType
}
// NewIngressAgentBatch creates a new IngressAgentBatch with the given batch client and contractID
-func NewIngressAgentBatch(telemetryIngressBatchClient synchronization.TelemetryService, contractID string, telemType synchronization.TelemetryType, network string, chainID string) *IngressAgentBatch {
+func NewIngressAgentBatch(telemetryIngressBatchClient synchronization.TelemetryService, network string, chainID string, contractID string, telemType synchronization.TelemetryType) *IngressAgentBatch {
return &IngressAgentBatch{
telemetryIngressBatchClient,
- contractID,
- telemType,
network,
chainID,
+ contractID,
+ telemType,
}
}
diff --git a/core/services/telemetry/ingress_batch_test.go b/core/services/telemetry/ingress_batch_test.go
index 3923b569fe..91e6a07ad7 100644
--- a/core/services/telemetry/ingress_batch_test.go
+++ b/core/services/telemetry/ingress_batch_test.go
@@ -14,7 +14,7 @@ import (
func TestIngressAgentBatch(t *testing.T) {
telemetryBatchClient := mocks.NewTelemetryService(t)
ingressAgentBatch := telemetry.NewIngressAgentWrapper(telemetryBatchClient)
- monitoringEndpoint := ingressAgentBatch.GenMonitoringEndpoint("0xa", synchronization.OCR, "test-network", "test-chainID")
+ monitoringEndpoint := ingressAgentBatch.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.OCR)
// Handle the Send call and store the telem
var telemPayload synchronization.TelemPayload
diff --git a/core/services/telemetry/ingress_test.go b/core/services/telemetry/ingress_test.go
index 31028f2f60..7e83384dc6 100644
--- a/core/services/telemetry/ingress_test.go
+++ b/core/services/telemetry/ingress_test.go
@@ -14,7 +14,7 @@ import (
func TestIngressAgent(t *testing.T) {
telemetryClient := mocks.NewTelemetryService(t)
ingressAgent := telemetry.NewIngressAgentWrapper(telemetryClient)
- monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("0xa", synchronization.OCR, "test-network", "test-chainID")
+ monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.OCR)
// Handle the Send call and store the telem
var telemPayload synchronization.TelemPayload
diff --git a/core/services/telemetry/manager.go b/core/services/telemetry/manager.go
index 2931ec71a1..cc14a956c1 100644
--- a/core/services/telemetry/manager.go
+++ b/core/services/telemetry/manager.go
@@ -150,7 +150,7 @@ func (m *Manager) HealthReport() map[string]error {
}
// GenMonitoringEndpoint creates a new monitoring endpoints based on the existing available endpoints defined in the core config TOML, if no endpoint for the network and chainID exists, a NOOP agent will be used and the telemetry will not be sent
-func (m *Manager) GenMonitoringEndpoint(contractID string, telemType synchronization.TelemetryType, network string, chainID string) commontypes.MonitoringEndpoint {
+func (m *Manager) GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) commontypes.MonitoringEndpoint {
e, found := m.getEndpoint(network, chainID)
@@ -160,10 +160,10 @@ func (m *Manager) GenMonitoringEndpoint(contractID string, telemType synchroniza
}
if m.useBatchSend {
- return NewIngressAgentBatch(e.client, contractID, telemType, network, chainID)
+ return NewIngressAgentBatch(e.client, network, chainID, contractID, telemType)
}
- return NewIngressAgent(e.client, contractID, telemType, network, chainID)
+ return NewIngressAgent(e.client, network, chainID, contractID, telemType)
}
diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go
index 69746625dd..2d51d9f449 100644
--- a/core/services/telemetry/manager_test.go
+++ b/core/services/telemetry/manager_test.go
@@ -56,14 +56,14 @@ func TestManagerAgents(t *testing.T) {
tm := NewManager(tic, ks, lggr)
require.Equal(t, "*synchronization.telemetryIngressBatchClient", reflect.TypeOf(tm.endpoints[0].client).String())
- me := tm.GenMonitoringEndpoint("", "", "network-1", "network-1-chainID-1")
+ me := tm.GenMonitoringEndpoint("network-1", "network-1-chainID-1", "", "")
require.Equal(t, "*telemetry.IngressAgentBatch", reflect.TypeOf(me).String())
tic = setupMockConfig(t, false)
tic.On("Endpoints").Return([]config.TelemetryIngressEndpoint{te})
tm = NewManager(tic, ks, lggr)
require.Equal(t, "*synchronization.telemetryIngressClient", reflect.TypeOf(tm.endpoints[0].client).String())
- me = tm.GenMonitoringEndpoint("", "", "network-1", "network-1-chainID-1")
+ me = tm.GenMonitoringEndpoint("network-1", "network-1-chainID-1", "", "")
require.Equal(t, "*telemetry.IngressAgent", reflect.TypeOf(me).String())
}
@@ -254,17 +254,17 @@ func TestCorrectEndpointRouting(t *testing.T) {
}
//Unknown networks or chainID
- noopEndpoint := tm.GenMonitoringEndpoint("some-contractID", "some-type", "unknown-network", "unknown-chainID")
+ noopEndpoint := tm.GenMonitoringEndpoint("unknown-network", "unknown-chainID", "some-contractID", "some-type")
require.Equal(t, "*telemetry.NoopAgent", reflect.TypeOf(noopEndpoint).String())
require.Equal(t, 1, obsLogs.Len())
require.Contains(t, obsLogs.TakeAll()[0].Message, "no telemetry endpoint found")
- noopEndpoint = tm.GenMonitoringEndpoint("some-contractID", "some-type", "network-1", "unknown-chainID")
+ noopEndpoint = tm.GenMonitoringEndpoint("network-1", "unknown-chainID", "some-contractID", "some-type")
require.Equal(t, "*telemetry.NoopAgent", reflect.TypeOf(noopEndpoint).String())
require.Equal(t, 1, obsLogs.Len())
require.Contains(t, obsLogs.TakeAll()[0].Message, "no telemetry endpoint found")
- noopEndpoint = tm.GenMonitoringEndpoint("some-contractID", "some-type", "network-2", "network-1-chainID-1")
+ noopEndpoint = tm.GenMonitoringEndpoint("network-2", "network-1-chainID-1", "some-contractID", "some-type")
require.Equal(t, "*telemetry.NoopAgent", reflect.TypeOf(noopEndpoint).String())
require.Equal(t, 1, obsLogs.Len())
require.Contains(t, obsLogs.TakeAll()[0].Message, "no telemetry endpoint found")
@@ -274,10 +274,10 @@ func TestCorrectEndpointRouting(t *testing.T) {
telemType := fmt.Sprintf("TelemType_%s", e.chainID)
contractID := fmt.Sprintf("contractID_%s", e.chainID)
me := tm.GenMonitoringEndpoint(
- contractID,
- synchronization.TelemetryType(telemType),
e.network,
e.chainID,
+ contractID,
+ synchronization.TelemetryType(telemType),
)
me.SendLog([]byte(e.chainID))
require.Equal(t, 0, obsLogs.Len())
@@ -316,7 +316,7 @@ func TestLegacyMode(t *testing.T) {
})
tm.endpoints[0].client = clientMock
- e := tm.GenMonitoringEndpoint("some-contractID", "some-type", "unknown-network", "unknown-chainID")
+ e := tm.GenMonitoringEndpoint("unknown-network", "unknown-chainID", "some-contractID", "some-type")
require.Equal(t, "*telemetry.IngressAgentBatch", reflect.TypeOf(e).String())
e.SendLog([]byte("endpoint-1-message-1"))
@@ -324,7 +324,7 @@ func TestLegacyMode(t *testing.T) {
e.SendLog([]byte("endpoint-1-message-3"))
require.Len(t, clientSent, 3)
- e2 := tm.GenMonitoringEndpoint("another-contractID", "another-type", "another-unknown-network", "another-unknown-chainID")
+ e2 := tm.GenMonitoringEndpoint("another-unknown-network", "another-unknown-chainID", "another-contractID", "another-type")
require.Equal(t, "*telemetry.IngressAgentBatch", reflect.TypeOf(e).String())
e2.SendLog([]byte("endpoint-2-message-1"))
diff --git a/core/services/telemetry/noop.go b/core/services/telemetry/noop.go
index cbeb038708..4da8868c8f 100644
--- a/core/services/telemetry/noop.go
+++ b/core/services/telemetry/noop.go
@@ -16,6 +16,6 @@ func (t *NoopAgent) SendLog(log []byte) {
}
// GenMonitoringEndpoint creates a monitoring endpoint for telemetry
-func (t *NoopAgent) GenMonitoringEndpoint(contractID string, telemType synchronization.TelemetryType, network string, chainID string) ocrtypes.MonitoringEndpoint {
+func (t *NoopAgent) GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) ocrtypes.MonitoringEndpoint {
return t
}
From 04ba364831eee6541c976cf8ea60c8eac09a0e5a Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Fri, 3 Nov 2023 09:07:11 -0400
Subject: [PATCH 069/327] Toggle Simulated Test Runs (#11157)
* Toggle Simulated Test Runs
* Debug inputs
* Figured it out
* Skip notify
---
.github/workflows/integration-tests.yml | 15 ++++++++++-----
integration-tests/soak/ocr_test.go | 1 +
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 785c48da40..0456c5f9d4 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -10,12 +10,16 @@ on:
- "*"
workflow_dispatch:
inputs:
+ simulatedNetwork:
+ description: "Run Simulated Network Tests"
+ required: false
+ type: boolean
+ default: true
liveNetwork:
- description: "Run Live Testnet Tests"
+ description: "Run Live Network Tests"
required: false
type: boolean
-
# Only run 1 of this workflow at a time per PR
concurrency:
group: integration-tests-chainlink-${{ github.ref }}
@@ -58,6 +62,7 @@ jobs:
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
this-job-name: Check Paths That Require Tests To Run
continue-on-error: true
+
outputs:
src: ${{ steps.changes.outputs.src }}
build-chainlink:
@@ -176,7 +181,7 @@ jobs:
echo "MATRIX_JSON=${COMBINED_ARRAY}" >> $GITHUB_ENV
eth-smoke-tests-matrix-automation:
- if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }}
+ if: ${{ !(contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') || (github.event_name == 'workflow_dispatch' && !inputs.simulatedNetwork)) }}
environment: integration
permissions:
checks: write
@@ -246,7 +251,7 @@ jobs:
continue-on-error: true
eth-smoke-tests-matrix:
- if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }}
+ if: ${{ !(contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') || (github.event_name == 'workflow_dispatch' && !inputs.simulatedNetwork)) }}
environment: integration
permissions:
checks: write
@@ -971,7 +976,7 @@ jobs:
testnet-smoke-tests-notify:
name: Live Testnet Start Slack Thread
- if: ${{ always() && needs.testnet-smoke-tests-matrix.result != 'skipped' && needs.testnet-smoke-tests-matrix.result != 'cancelled' }}
+ if: ${{ always() && needs.testnet-smoke-tests-matrix.result != 'skipped' && needs.testnet-smoke-tests-matrix.result != 'cancelled' && github.event_name != 'workflow_dispatch' }}
environment: integration
outputs:
thread_ts: ${{ steps.slack.outputs.thread_ts }}
diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go
index b2375f13ac..9973c23808 100644
--- a/integration-tests/soak/ocr_test.go
+++ b/integration-tests/soak/ocr_test.go
@@ -16,6 +16,7 @@ func TestOCRSoak(t *testing.T) {
// Use this variable to pass in any custom EVM specific TOML values to your Chainlink nodes
customNetworkTOML := ``
// Uncomment below for debugging TOML issues on the node
+ // network := networks.MustGetSelectedNetworksFromEnv()[0]
// fmt.Println("Using Chainlink TOML\n---------------------")
// fmt.Println(client.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network))
// fmt.Println("---------------------")
From 2b8ba05471a4c0f8fa1d30b7f47579f86a95efcf Mon Sep 17 00:00:00 2001
From: Chunkai Yang
Date: Fri, 3 Nov 2023 09:35:15 -0400
Subject: [PATCH 070/327] Make solc output folder per contract (#11126)
* update generation output path to be folder per contract
* lint bash script
* mass update go generate wrapper path
* regen wrappers and db
* fix not-updated wrappers
* fix more wrappers
---
contracts/scripts/native_solc_compile_all_6 | 11 +-
contracts/scripts/native_solc_compile_all_7 | 11 +-
.../native_solc_compile_all_automation | 13 +-
.../native_solc_compile_all_events_mock | 11 +-
.../scripts/native_solc_compile_all_feeds | 11 +-
.../scripts/native_solc_compile_all_llo-feeds | 11 +-
.../scripts/native_solc_compile_all_logpoller | 11 +-
.../scripts/native_solc_compile_all_ocr2vrf | 13 +-
.../native_solc_compile_all_operatorforwarder | 13 +-
.../scripts/native_solc_compile_all_shared | 11 +-
.../native_solc_compile_all_transmission | 11 +-
contracts/scripts/native_solc_compile_all_vrf | 25 +-
...rapper-dependency-versions-do-not-edit.txt | 226 +++++++++---------
core/gethwrappers/go_generate.go | 218 ++++++++---------
...rapper-dependency-versions-do-not-edit.txt | 12 +-
core/gethwrappers/llo-feeds/go_generate.go | 12 +-
...rapper-dependency-versions-do-not-edit.txt | 8 +-
core/gethwrappers/shared/go_generate.go | 8 +-
...rapper-dependency-versions-do-not-edit.txt | 12 +-
core/gethwrappers/transmission/go_generate.go | 12 +-
20 files changed, 350 insertions(+), 310 deletions(-)
diff --git a/contracts/scripts/native_solc_compile_all_6 b/contracts/scripts/native_solc_compile_all_6
index 7f8f4fa695..f7bd60d678 100755
--- a/contracts/scripts/native_solc_compile_all_6
+++ b/contracts/scripts/native_solc_compile_all_6
@@ -12,7 +12,7 @@ OPTIMIZE_RUNS=1000000
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
+python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt
solc-select install $SOLC_VERSION
solc-select use $SOLC_VERSION
@@ -20,10 +20,13 @@ export SOLC_VERSION=$SOLC_VERSION
compileContract () {
+ local contract
+ contract=$(basename "$1" ".sol")
+
solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v0.6 \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.6 \
- $ROOT/contracts/src/v0.6/$1
+ -o "$ROOT"/contracts/solc/v0.6/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.6 \
+ "$ROOT"/contracts/src/v0.6/"$1"
}
compileContract Flags.sol
diff --git a/contracts/scripts/native_solc_compile_all_7 b/contracts/scripts/native_solc_compile_all_7
index b2d76b3cb5..fd64d9ffce 100755
--- a/contracts/scripts/native_solc_compile_all_7
+++ b/contracts/scripts/native_solc_compile_all_7
@@ -12,7 +12,7 @@ OPTIMIZE_RUNS=1000000
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
+python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt
solc-select install $SOLC_VERSION
solc-select use $SOLC_VERSION
@@ -20,10 +20,13 @@ export SOLC_VERSION=$SOLC_VERSION
compileContract () {
+ local contract
+ contract=$(basename "$1" ".sol")
+
solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v0.7 \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.7 \
- $ROOT/contracts/src/v0.7/$1
+ -o "$ROOT"/contracts/solc/v0.7/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.7 \
+ "$ROOT"/contracts/src/v0.7/"$1"
}
compileContract tests/MultiWordConsumer.sol
diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation
index 414453c848..beb557de12 100755
--- a/contracts/scripts/native_solc_compile_all_automation
+++ b/contracts/scripts/native_solc_compile_all_automation
@@ -12,7 +12,7 @@ OPTIMIZE_RUNS=1000000
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
+python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt
solc-select install $SOLC_VERSION
solc-select use $SOLC_VERSION
@@ -20,10 +20,13 @@ export SOLC_VERSION=$SOLC_VERSION
compileContract () {
- solc @openzeppelin/=$ROOT/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8,$ROOT/contracts/node_modules\
- $ROOT/contracts/src/v0.8/$1
+ local contract
+ contract=$(basename "$1" ".sol")
+
+ solc @openzeppelin/="$ROOT"/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8,"$ROOT"/contracts/node_modules\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
compileContract automation/upkeeps/CronUpkeepFactory.sol
diff --git a/contracts/scripts/native_solc_compile_all_events_mock b/contracts/scripts/native_solc_compile_all_events_mock
index 993530e2fa..68e8bdfa6a 100755
--- a/contracts/scripts/native_solc_compile_all_events_mock
+++ b/contracts/scripts/native_solc_compile_all_events_mock
@@ -12,17 +12,20 @@ OPTIMIZE_RUNS=1000000
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
+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 $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8\
- $ROOT/contracts/src/v0.8/$1
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
# This script is used to compile the contracts for the Events Mocks used in the tests.
diff --git a/contracts/scripts/native_solc_compile_all_feeds b/contracts/scripts/native_solc_compile_all_feeds
index 2bbd9fe869..eac5a6b70c 100755
--- a/contracts/scripts/native_solc_compile_all_feeds
+++ b/contracts/scripts/native_solc_compile_all_feeds
@@ -12,7 +12,7 @@ OPTIMIZE_RUNS=1000000
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
+python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt
solc-select install $SOLC_VERSION
solc-select use $SOLC_VERSION
@@ -20,10 +20,13 @@ export SOLC_VERSION=$SOLC_VERSION
compileContract () {
+ local contract
+ contract=$(basename "$1" ".sol")
+
solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8\
- $ROOT/contracts/src/v0.8/$1
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
# Aggregators
diff --git a/contracts/scripts/native_solc_compile_all_llo-feeds b/contracts/scripts/native_solc_compile_all_llo-feeds
index 27ef714ec1..2caa6fb98d 100755
--- a/contracts/scripts/native_solc_compile_all_llo-feeds
+++ b/contracts/scripts/native_solc_compile_all_llo-feeds
@@ -11,7 +11,7 @@ OPTIMIZE_RUNS=1000000
SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
-python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt
+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
@@ -19,10 +19,13 @@ export SOLC_VERSION=$SOLC_VERSION
ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )"
compileContract () {
+ local contract
+ contract=$(basename "$1" ".sol")
+
solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8\
- $ROOT/contracts/src/v0.8/$1
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
compileContract llo-feeds/Verifier.sol
diff --git a/contracts/scripts/native_solc_compile_all_logpoller b/contracts/scripts/native_solc_compile_all_logpoller
index 91a0606dba..b6ac51eced 100755
--- a/contracts/scripts/native_solc_compile_all_logpoller
+++ b/contracts/scripts/native_solc_compile_all_logpoller
@@ -11,7 +11,7 @@ OPTIMIZE_RUNS=1000000
SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
-python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt
+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
@@ -19,10 +19,13 @@ export SOLC_VERSION=$SOLC_VERSION
ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )"
compileContract () {
+ local contract
+ contract=$(basename "$1" ".sol")
+
solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8\
- $ROOT/contracts/src/v0.8/$1
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
diff --git a/contracts/scripts/native_solc_compile_all_ocr2vrf b/contracts/scripts/native_solc_compile_all_ocr2vrf
index 42478d7ebc..755edd34f5 100755
--- a/contracts/scripts/native_solc_compile_all_ocr2vrf
+++ b/contracts/scripts/native_solc_compile_all_ocr2vrf
@@ -16,7 +16,7 @@ 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
+python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt
solc-select install $SOLC_VERSION
solc-select use $SOLC_VERSION
@@ -24,11 +24,14 @@ export SOLC_VERSION=$SOLC_VERSION
compileContract () {
- solc --overwrite --optimize --optimize-runs $2 --metadata-hash none \
- -o $ROOT/contracts/solc/v0.8.19 \
+ 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
+ --allow-paths "$ROOT"/../$FOLDER/contracts \
+ "$ROOT"/"$1"
}
# OCR2VRF
diff --git a/contracts/scripts/native_solc_compile_all_operatorforwarder b/contracts/scripts/native_solc_compile_all_operatorforwarder
index 3bc5cb9249..2d45599481 100755
--- a/contracts/scripts/native_solc_compile_all_operatorforwarder
+++ b/contracts/scripts/native_solc_compile_all_operatorforwarder
@@ -11,17 +11,20 @@ OPTIMIZE_RUNS=1000000
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
+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 () {
- solc @openzeppelin/=$ROOT/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8,$ROOT/contracts/node_modules\
- $ROOT/contracts/src/v0.8/$1
+ local contract
+ contract=$(basename "$1" ".sol")
+
+ solc @openzeppelin/="$ROOT"/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8,"$ROOT"/contracts/node_modules\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
# Contracts
diff --git a/contracts/scripts/native_solc_compile_all_shared b/contracts/scripts/native_solc_compile_all_shared
index db421f45e0..9178237b8a 100755
--- a/contracts/scripts/native_solc_compile_all_shared
+++ b/contracts/scripts/native_solc_compile_all_shared
@@ -11,7 +11,7 @@ OPTIMIZE_RUNS=1000000
SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
-python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt
+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
@@ -19,10 +19,13 @@ export SOLC_VERSION=$SOLC_VERSION
ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )"
compileContract () {
+ local contract
+ contract=$(basename "$1" ".sol")
+
solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8\
- $ROOT/contracts/src/v0.8/$1
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
compileContract shared/token/ERC677/BurnMintERC677.sol
diff --git a/contracts/scripts/native_solc_compile_all_transmission b/contracts/scripts/native_solc_compile_all_transmission
index e08f38e2ba..281fa7aea7 100755
--- a/contracts/scripts/native_solc_compile_all_transmission
+++ b/contracts/scripts/native_solc_compile_all_transmission
@@ -11,17 +11,20 @@ OPTIMIZE_RUNS=1000000
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
+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 $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8\
- $ROOT/contracts/src/v0.8/$1
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
# Contracts
diff --git a/contracts/scripts/native_solc_compile_all_vrf b/contracts/scripts/native_solc_compile_all_vrf
index 80adba8e6f..4eed35cf5b 100755
--- a/contracts/scripts/native_solc_compile_all_vrf
+++ b/contracts/scripts/native_solc_compile_all_vrf
@@ -11,24 +11,30 @@ OPTIMIZE_RUNS=1000000
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
+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 () {
- solc @openzeppelin/=$ROOT/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8,$ROOT/contracts/node_modules\
- $ROOT/contracts/src/v0.8/$1
+ local contract
+ contract=$(basename "$1" ".sol")
+
+ solc @openzeppelin/="$ROOT"/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8,"$ROOT"/contracts/node_modules\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
compileContractAltOpts () {
- solc @openzeppelin/=$ROOT/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs $2 --metadata-hash none \
- -o $ROOT/contracts/solc/v$SOLC_VERSION \
- --abi --bin --allow-paths $ROOT/contracts/src/v0.8,$ROOT/contracts/node_modules\
- $ROOT/contracts/src/v0.8/$1
+ local contract
+ contract=$(basename "$1" ".sol")
+
+ solc @openzeppelin/="$ROOT"/contracts/node_modules/@openzeppelin/ --overwrite --optimize --optimize-runs "$2" --metadata-hash none \
+ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
+ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8,"$ROOT"/contracts/node_modules\
+ "$ROOT"/contracts/src/v0.8/"$1"
}
# VRF
@@ -73,6 +79,7 @@ compileContract vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol
compileContract vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol
compileContract vrf/dev/libraries/VRFV2PlusClient.sol
compileContract vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol
+compileContract vrf/dev/BlockhashStore.sol
compileContract vrf/dev/TrustedBlockhashStore.sol
compileContract vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol
compileContractAltOpts vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol 5
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 0d0bb388f2..a14b461fa7 100644
--- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -1,116 +1,116 @@
GETH_VERSION: 1.12.0
-KeeperConsumer: ../../contracts/solc/v0.8.16/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer.bin 53d7902867ce421641ffa9de63204b89ab9dc157b93f0beb9ac08c6450365a70
-KeeperConsumerPerformance: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90
-PerformDataChecker: ../../contracts/solc/v0.8.16/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73
-UpkeepCounter: ../../contracts/solc/v0.8.16/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter.bin 77f000229a501f638dd2dc439859257f632894c728b31e68aea4f6d6c52f1b71
-UpkeepPerformCounterRestrictive: ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive.bin 20955b21acceb58355fa287b29194a73edf5937067ba7140667301017cb2b24c
-VRFv2Consumer: ../../contracts/solc/v0.8.6/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer.bin 12368b3b5e06392440143a13b94c0ea2f79c4c897becc3b060982559e10ace40
-aggregator_v2v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface.bin 95e8814b408bb05bf21742ef580d98698b7db6a9bac6a35c3de12b23aec4ee28
-aggregator_v3_interface: ../../contracts/solc/v0.8.6/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV3Interface.bin 351b55d3b0f04af67db6dfb5c92f1c64479400ca1fec77afc20bc0ce65cb49ab
-authorized_forwarder: ../../contracts/solc/v0.8.19/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder.bin 8ea76c883d460f8353a45a493f2aebeb5a2d9a7b4619d1bc4fff5fb590bb3e10
-authorized_receiver: ../../contracts/solc/v0.8.19/AuthorizedReceiver.abi ../../contracts/solc/v0.8.19/AuthorizedReceiver.bin 18e8969ba3234b027e1b16c11a783aca58d0ea5c2361010ec597f134b7bf1c4f
-automation_consumer_benchmark: ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark.bin f52c76f1aaed4be541d82d97189d70f5aa027fc9838037dd7a7d21910c8c488e
-automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic.bin 15ae0c367297955fdab4b552dbb10e1f2be80a8fde0efec4a4d398693e9d72b5
-automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42
-automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1.bin 331bfa79685aee6ddf63b64c0747abee556c454cae3fb8175edff425b615d8aa
-batch_blockhash_store: ../../contracts/solc/v0.8.6/BatchBlockhashStore.abi ../../contracts/solc/v0.8.6/BatchBlockhashStore.bin 14356c48ef70f66ef74f22f644450dbf3b2a147c1b68deaa7e7d1eb8ffab15db
-batch_vrf_coordinator_v2: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2.bin d0a54963260d8c1f1bbd984b758285e6027cfb5a7e42701bcb562ab123219332
-batch_vrf_coordinator_v2plus: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus.bin 7bb76ae241cf1b37b41920830b836cb99f1ad33efd7435ca2398ff6cd2fe5d48
-blockhash_store: ../../contracts/solc/v0.8.6/BlockhashStore.abi ../../contracts/solc/v0.8.6/BlockhashStore.bin 12b0662f1636a341c8863bdec7a20f2ddd97c3a4fd1a7ae353fe316609face4e
-chain_specific_util_helper: ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper.bin 5f10664e31abc768f4a37901cae7a3bef90146180f97303e5a1bde5a08d84595
-consumer_wrapper: ../../contracts/solc/v0.7/Consumer.abi ../../contracts/solc/v0.7/Consumer.bin 894d1cbd920dccbd36d92918c1037c6ded34f66f417ccb18ec3f33c64ef83ec5
-cron_upkeep_factory_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory.abi - dacb0f8cdf54ae9d2781c5e720fc314b32ed5e58eddccff512c75d6067292cd7
-cron_upkeep_wrapper: ../../contracts/solc/v0.8.6/CronUpkeep.abi - 362fcfcf30a6ab3acff83095ea4b2b9056dd5e9dcb94bc5411aae58995d22709
-dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol.bin 583a448170b13abf7ed64e406e8177d78c9e55ab44efd141eee60de23a71ee3b
-flags_wrapper: ../../contracts/solc/v0.6/Flags.abi ../../contracts/solc/v0.6/Flags.bin 2034d1b562ca37a63068851915e3703980276e8d5f7db6db8a3351a49d69fc4a
-flux_aggregator_wrapper: ../../contracts/solc/v0.6/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator.bin a3b0a6396c4aa3b5ee39b3c4bd45efc89789d4859379a8a92caca3a0496c5794
-functions_billing_registry_events_mock: ../../contracts/solc/v0.8.6/FunctionsBillingRegistryEventsMock.abi ../../contracts/solc/v0.8.6/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
-functions_oracle_events_mock: ../../contracts/solc/v0.8.6/FunctionsOracleEventsMock.abi ../../contracts/solc/v0.8.6/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
-gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723
-gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8
-i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster.bin 6501bb9bcf5048bab2737b00685c6984a24867e234ddf5b60a65904eee9a4ebc
-i_log_automation: ../../contracts/solc/v0.8.16/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation.bin 296beccb6af655d6fc3a6e676b244831cce2da6688d3afc4f21f8738ae59e03e
-keeper_consumer_performance_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90
-keeper_consumer_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer.bin 53d7902867ce421641ffa9de63204b89ab9dc157b93f0beb9ac08c6450365a70
-keeper_registrar_wrapper1_2: ../../contracts/solc/v0.8.6/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar.bin e49b2f8b23da17af1ed2209b8ae0968cc04350554d636711e6c24a3ad3118692
-keeper_registrar_wrapper1_2_mock: ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock.bin 5b155a7cb3def309fd7525de1d7cd364ebf8491bdc3060eac08ea0ff55ab29bc
-keeper_registrar_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistrar2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistrar2_0.bin 647f125c2f0dafabcdc545cb77b15dc2ec3ea9429357806813179b1fd555c2d2
-keeper_registry_logic1_3: ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3.bin 903f8b9c8e25425ca6d0b81b89e339d695a83630bfbfa24a6f3b38869676bc5a
-keeper_registry_logic2_0: ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0.bin d69d2bc8e4844293dbc2d45abcddc50b84c88554ecccfa4fa77c0ca45ec80871
-keeper_registry_logic_a_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1.bin 77481ab75c9aa86a62a7b2a708599b5ea1a6346ed1c0def6d4826e7ae523f1ee
-keeper_registry_logic_b_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1.bin 467d10741a04601b136553a2b1c6ab37f2a65d809366faf03180a22ff26be215
-keeper_registry_wrapper1_1: ../../contracts/solc/v0.7/KeeperRegistry1_1.abi ../../contracts/solc/v0.7/KeeperRegistry1_1.bin 6ce079f2738f015f7374673a2816e8e9787143d00b780ea7652c8aa9ad9e1e20
-keeper_registry_wrapper1_1_mock: ../../contracts/solc/v0.7/KeeperRegistry1_1Mock.abi ../../contracts/solc/v0.7/KeeperRegistry1_1Mock.bin 98ddb3680e86359de3b5d17e648253ba29a84703f087a1b52237824003a8c6df
-keeper_registry_wrapper1_2: ../../contracts/solc/v0.8.6/KeeperRegistry1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2.bin a40ff877dd7c280f984cbbb2b428e160662b0c295e881d5f778f941c0088ca22
-keeper_registry_wrapper1_3: ../../contracts/solc/v0.8.6/KeeperRegistry1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_3.bin d4dc760b767ae274ee25c4a604ea371e1fa603a7b6421b69efb2088ad9e8abb3
-keeper_registry_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0.bin c32dea7d5ef66b7c58ddc84ddf69aa44df1b3ae8601fbc271c95be4ff5853056
-keeper_registry_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistry2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistry2_1.bin 604e4a0cd980c713929b523b999462a3aa0ed06f96ff563a4c8566cf59c8445b
-keepers_vrf_consumer: ../../contracts/solc/v0.8.6/KeepersVRFConsumer.abi ../../contracts/solc/v0.8.6/KeepersVRFConsumer.bin fa75572e689c9e84705c63e8dbe1b7b8aa1a8fe82d66356c4873d024bb9166e8
-log_emitter: ../../contracts/solc/v0.8.19/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter.bin 244ba13730c036de0b02beef4e3d9c9a96946ce353c27f366baecc7f5be5a6fd
-log_triggered_streams_lookup_wrapper: ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup.bin f8da43a927c1a66238a9f4fd5d5dd7e280e361daa0444da1f7f79498ace901e1
-log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter.bin 42426bbb83f96dfbe55fc576d6c65020eaeed690e2289cf99b0c4aa810a5f4ec
-mock_aggregator_proxy: ../../contracts/solc/v0.8.6/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy.bin b16c108f3dd384c342ddff5e94da7c0a8d39d1be5e3d8f2cf61ecc7f0e50ff42
-mock_ethlink_aggregator_wrapper: ../../contracts/solc/v0.6/MockETHLINKAggregator.abi ../../contracts/solc/v0.6/MockETHLINKAggregator.bin 1c52c24f797b8482aa12b8251dcea1c072827bd5b3426b822621261944b99ca0
-mock_gas_aggregator_wrapper: ../../contracts/solc/v0.6/MockGASAggregator.abi ../../contracts/solc/v0.6/MockGASAggregator.bin bacbb1ea4dc6beac0db8a13ca5c75e2fd61b903d70feea9b3b1c8b10fe8df4f3
-multiwordconsumer_wrapper: ../../contracts/solc/v0.7/MultiWordConsumer.abi ../../contracts/solc/v0.7/MultiWordConsumer.bin 6e68abdf614e3ed0f5066c1b5f9d7c1199f1e7c5c5251fe8a471344a59afc6ba
+KeeperConsumer: ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.bin 53d7902867ce421641ffa9de63204b89ab9dc157b93f0beb9ac08c6450365a70
+KeeperConsumerPerformance: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90
+PerformDataChecker: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73
+UpkeepCounter: ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.bin 77f000229a501f638dd2dc439859257f632894c728b31e68aea4f6d6c52f1b71
+UpkeepPerformCounterRestrictive: ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin 20955b21acceb58355fa287b29194a73edf5937067ba7140667301017cb2b24c
+VRFv2Consumer: ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.bin 12368b3b5e06392440143a13b94c0ea2f79c4c897becc3b060982559e10ace40
+aggregator_v2v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.bin 95e8814b408bb05bf21742ef580d98698b7db6a9bac6a35c3de12b23aec4ee28
+aggregator_v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.bin 351b55d3b0f04af67db6dfb5c92f1c64479400ca1fec77afc20bc0ce65cb49ab
+authorized_forwarder: ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin 8ea76c883d460f8353a45a493f2aebeb5a2d9a7b4619d1bc4fff5fb590bb3e10
+authorized_receiver: ../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.abi ../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.bin 18e8969ba3234b027e1b16c11a783aca58d0ea5c2361010ec597f134b7bf1c4f
+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_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 331bfa79685aee6ddf63b64c0747abee556c454cae3fb8175edff425b615d8aa
+batch_blockhash_store: ../../contracts/solc/v0.8.6/BatchBlockhashStore/BatchBlockhashStore.abi ../../contracts/solc/v0.8.6/BatchBlockhashStore/BatchBlockhashStore.bin 14356c48ef70f66ef74f22f644450dbf3b2a147c1b68deaa7e7d1eb8ffab15db
+batch_vrf_coordinator_v2: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/BatchVRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/BatchVRFCoordinatorV2.bin d0a54963260d8c1f1bbd984b758285e6027cfb5a7e42701bcb562ab123219332
+batch_vrf_coordinator_v2plus: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.bin 7bb76ae241cf1b37b41920830b836cb99f1ad33efd7435ca2398ff6cd2fe5d48
+blockhash_store: ../../contracts/solc/v0.8.6/BlockhashStore/BlockhashStore.abi ../../contracts/solc/v0.8.6/BlockhashStore/BlockhashStore.bin 12b0662f1636a341c8863bdec7a20f2ddd97c3a4fd1a7ae353fe316609face4e
+chain_specific_util_helper: ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.bin 5f10664e31abc768f4a37901cae7a3bef90146180f97303e5a1bde5a08d84595
+consumer_wrapper: ../../contracts/solc/v0.7/Consumer/Consumer.abi ../../contracts/solc/v0.7/Consumer/Consumer.bin 894d1cbd920dccbd36d92918c1037c6ded34f66f417ccb18ec3f33c64ef83ec5
+cron_upkeep_factory_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - dacb0f8cdf54ae9d2781c5e720fc314b32ed5e58eddccff512c75d6067292cd7
+cron_upkeep_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeep.abi - 362fcfcf30a6ab3acff83095ea4b2b9056dd5e9dcb94bc5411aae58995d22709
+dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.bin 583a448170b13abf7ed64e406e8177d78c9e55ab44efd141eee60de23a71ee3b
+flags_wrapper: ../../contracts/solc/v0.6/Flags/Flags.abi ../../contracts/solc/v0.6/Flags/Flags.bin 2034d1b562ca37a63068851915e3703980276e8d5f7db6db8a3351a49d69fc4a
+flux_aggregator_wrapper: ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.bin a3b0a6396c4aa3b5ee39b3c4bd45efc89789d4859379a8a92caca3a0496c5794
+functions_billing_registry_events_mock: ../../contracts/solc/v0.8.6/FunctionsBillingRegistryEventsMock/FunctionsBillingRegistryEventsMock.abi ../../contracts/solc/v0.8.6/FunctionsBillingRegistryEventsMock/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
+functions_oracle_events_mock: ../../contracts/solc/v0.8.6/FunctionsOracleEventsMock/FunctionsOracleEventsMock.abi ../../contracts/solc/v0.8.6/FunctionsOracleEventsMock/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
+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_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin 6501bb9bcf5048bab2737b00685c6984a24867e234ddf5b60a65904eee9a4ebc
+i_log_automation: ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.bin 296beccb6af655d6fc3a6e676b244831cce2da6688d3afc4f21f8738ae59e03e
+keeper_consumer_performance_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90
+keeper_consumer_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.bin 53d7902867ce421641ffa9de63204b89ab9dc157b93f0beb9ac08c6450365a70
+keeper_registrar_wrapper1_2: ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.bin e49b2f8b23da17af1ed2209b8ae0968cc04350554d636711e6c24a3ad3118692
+keeper_registrar_wrapper1_2_mock: ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.bin 5b155a7cb3def309fd7525de1d7cd364ebf8491bdc3060eac08ea0ff55ab29bc
+keeper_registrar_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistrar2_0/KeeperRegistrar2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistrar2_0/KeeperRegistrar2_0.bin 647f125c2f0dafabcdc545cb77b15dc2ec3ea9429357806813179b1fd555c2d2
+keeper_registry_logic1_3: ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3/KeeperRegistryLogic1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3/KeeperRegistryLogic1_3.bin 903f8b9c8e25425ca6d0b81b89e339d695a83630bfbfa24a6f3b38869676bc5a
+keeper_registry_logic2_0: ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0/KeeperRegistryLogic2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0/KeeperRegistryLogic2_0.bin d69d2bc8e4844293dbc2d45abcddc50b84c88554ecccfa4fa77c0ca45ec80871
+keeper_registry_logic_a_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1/KeeperRegistryLogicA2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1/KeeperRegistryLogicA2_1.bin 77481ab75c9aa86a62a7b2a708599b5ea1a6346ed1c0def6d4826e7ae523f1ee
+keeper_registry_logic_b_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1/KeeperRegistryLogicB2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1/KeeperRegistryLogicB2_1.bin 467d10741a04601b136553a2b1c6ab37f2a65d809366faf03180a22ff26be215
+keeper_registry_wrapper1_1: ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.abi ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.bin 6ce079f2738f015f7374673a2816e8e9787143d00b780ea7652c8aa9ad9e1e20
+keeper_registry_wrapper1_1_mock: ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.abi ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.bin 98ddb3680e86359de3b5d17e648253ba29a84703f087a1b52237824003a8c6df
+keeper_registry_wrapper1_2: ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.bin a40ff877dd7c280f984cbbb2b428e160662b0c295e881d5f778f941c0088ca22
+keeper_registry_wrapper1_3: ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.bin d4dc760b767ae274ee25c4a604ea371e1fa603a7b6421b69efb2088ad9e8abb3
+keeper_registry_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.bin c32dea7d5ef66b7c58ddc84ddf69aa44df1b3ae8601fbc271c95be4ff5853056
+keeper_registry_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.bin 604e4a0cd980c713929b523b999462a3aa0ed06f96ff563a4c8566cf59c8445b
+keepers_vrf_consumer: ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.abi ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.bin fa75572e689c9e84705c63e8dbe1b7b8aa1a8fe82d66356c4873d024bb9166e8
+log_emitter: ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.bin 244ba13730c036de0b02beef4e3d9c9a96946ce353c27f366baecc7f5be5a6fd
+log_triggered_streams_lookup_wrapper: ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin f8da43a927c1a66238a9f4fd5d5dd7e280e361daa0444da1f7f79498ace901e1
+log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin 42426bbb83f96dfbe55fc576d6c65020eaeed690e2289cf99b0c4aa810a5f4ec
+mock_aggregator_proxy: ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin b16c108f3dd384c342ddff5e94da7c0a8d39d1be5e3d8f2cf61ecc7f0e50ff42
+mock_ethlink_aggregator_wrapper: ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.abi ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.bin 1c52c24f797b8482aa12b8251dcea1c072827bd5b3426b822621261944b99ca0
+mock_gas_aggregator_wrapper: ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.abi ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.bin bacbb1ea4dc6beac0db8a13ca5c75e2fd61b903d70feea9b3b1c8b10fe8df4f3
+multiwordconsumer_wrapper: ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.abi ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.bin 6e68abdf614e3ed0f5066c1b5f9d7c1199f1e7c5c5251fe8a471344a59afc6ba
offchain_aggregator_wrapper: OffchainAggregator/OffchainAggregator.abi - 5c8d6562e94166d4790f1ee6e4321d359d9f7262e6c5452a712b1f1c896f45cf
-operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory.bin 0fdfacf8879537b854875608dfca41c6221c342174417112acaa67dfcadafddc
-operator_wrapper: ../../contracts/solc/v0.8.19/Operator.abi ../../contracts/solc/v0.8.19/Operator.bin d7abd0e67f30a3a4c9c04c896124391306fa364fcf579fa6df04dbf912b48568
-oracle_wrapper: ../../contracts/solc/v0.6/Oracle.abi ../../contracts/solc/v0.6/Oracle.bin 7af2fbac22a6e8c2847e8e685a5400cac5101d72ddf5365213beb79e4dede43a
-perform_data_checker_wrapper: ../../contracts/solc/v0.8.16/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73
-solidity_vrf_consumer_interface: ../../contracts/solc/v0.6/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer.bin ecc99378aa798014de9db42b2eb81320778b0663dbe208008dad75ccdc1d4366
-solidity_vrf_consumer_interface_v08: ../../contracts/solc/v0.8.6/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer.bin b14f9136b15e3dc9d6154d5700f3ed4cf88ddc4f70f20c3bb57fc46050904c8f
-solidity_vrf_coordinator_interface: ../../contracts/solc/v0.6/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator.bin a23d3c395156804788c7f6fbda2994e8f7184304c0f0c9f2c4ddeaf073d346d2
-solidity_vrf_request_id: ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper.bin 383b59e861732c1911ddb7b002c6158608496ce889979296527215fd0366b318
-solidity_vrf_request_id_v08: ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper.bin f2559015d6f3e5d285c57b011be9b2300632e93dd6c4524e58202d6200f09edc
-solidity_vrf_v08_verifier_wrapper: ../../contracts/solc/v0.8.6/VRFTestHelper.abi ../../contracts/solc/v0.8.6/VRFTestHelper.bin f37f8b21a81c113085c6137835a2246db6ebda07da455c4f2b5c7ec60c725c3b
-solidity_vrf_verifier_wrapper: ../../contracts/solc/v0.6/VRFTestHelper.abi ../../contracts/solc/v0.6/VRFTestHelper.bin 44c2b67d8d2990ab580453deb29d63508c6147a3dc49908a1db563bef06e6474
-solidity_vrf_wrapper: ../../contracts/solc/v0.6/VRF.abi ../../contracts/solc/v0.6/VRF.bin 04ede5b83c06ba5b76ef99c081c72928007d8a7aaefcf21449a46a07cbd4bfc2
-streams_lookup_compatible_interface: ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface.abi ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface.bin feb92cc666df21ea04ab9d7a588a513847b01b2f66fc167d06ab28ef2b17e015
-streams_lookup_upkeep_wrapper: ../../contracts/solc/v0.8.16/StreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/StreamsLookupUpkeep.bin b1a598963cacac51ed4706538d0f142bdc0d94b9a4b13e2d402131cdf05c9bcf
-test_api_consumer_wrapper: ../../contracts/solc/v0.6/TestAPIConsumer.abi ../../contracts/solc/v0.6/TestAPIConsumer.bin ed10893cb18894c18e275302329c955f14ea2de37ee044f84aa1e067ac5ea71e
-trusted_blockhash_store: ../../contracts/solc/v0.8.6/TrustedBlockhashStore.abi ../../contracts/solc/v0.8.6/TrustedBlockhashStore.bin 98cb0dc06c15af5dcd3b53bdfc98e7ed2489edc96a42203294ac2fc0efdda02b
-type_and_version_interface_wrapper: ../../contracts/solc/v0.8.6/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/TypeAndVersionInterface.bin bc9c3a6e73e3ebd5b58754df0deeb3b33f4bb404d5709bb904aed51d32f4b45e
-upkeep_counter_wrapper: ../../contracts/solc/v0.8.16/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter.bin 77f000229a501f638dd2dc439859257f632894c728b31e68aea4f6d6c52f1b71
-upkeep_perform_counter_restrictive_wrapper: ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive.bin 20955b21acceb58355fa287b29194a73edf5937067ba7140667301017cb2b24c
-upkeep_transcoder: ../../contracts/solc/v0.8.6/UpkeepTranscoder.abi ../../contracts/solc/v0.8.6/UpkeepTranscoder.bin 336c92a981597be26508455f81a908a0784a817b129a59686c5b2c4afcba730a
-verifiable_load_log_trigger_upkeep_wrapper: ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep.bin fb674ba44c0e8f3b385cd10b2f7dea5cd07b5f38df08066747e8b1542e152557
-verifiable_load_streams_lookup_upkeep_wrapper: ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep.bin 785f68c44bfff070505eaa65e38a1af94046e5f9afc1189bcf2c8cfcd1102d66
-verifiable_load_upkeep_wrapper: ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep.bin a3e02c43756ea91e7ce4b81e48c11648f1d12f6663c236780147e41dfa36ebee
-vrf_consumer_v2: ../../contracts/solc/v0.8.6/VRFConsumerV2.abi ../../contracts/solc/v0.8.6/VRFConsumerV2.bin 9ef258bf8e9f8d880fd229ceb145593d91e24fc89366baa0bf19169c5787d15f
-vrf_consumer_v2_plus_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample.bin 3155c611e4d6882e9324b6e975033b31356776ea8b031ca63d63da37589d583b
-vrf_consumer_v2_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample.bin f1790a9a2f2a04c730593e483459709cb89e897f8a19d7a3ac0cfe6a97265e6e
-vrf_coordinator_mock: ../../contracts/solc/v0.8.6/VRFCoordinatorMock.abi ../../contracts/solc/v0.8.6/VRFCoordinatorMock.bin 5c495cf8df1f46d8736b9150cdf174cce358cb8352f60f0d5bb9581e23920501
-vrf_coordinator_v2: ../../contracts/solc/v0.8.6/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2.bin 295f35ce282060317dfd01f45959f5a2b05ba26913e422fbd4fb6bf90b107006
-vrf_coordinator_v2_5: ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5.bin b0e7c42a30b36d9d31fa9a3f26bad7937152e3dddee5bd8dd3d121390c879ab6
-vrf_coordinator_v2_plus_v2_example: ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example.bin 4a5b86701983b1b65f0a8dfa116b3f6d75f8f706fa274004b57bdf5992e4cec3
+operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin 0fdfacf8879537b854875608dfca41c6221c342174417112acaa67dfcadafddc
+operator_wrapper: ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin d7abd0e67f30a3a4c9c04c896124391306fa364fcf579fa6df04dbf912b48568
+oracle_wrapper: ../../contracts/solc/v0.6/Oracle/Oracle.abi ../../contracts/solc/v0.6/Oracle/Oracle.bin 7af2fbac22a6e8c2847e8e685a5400cac5101d72ddf5365213beb79e4dede43a
+perform_data_checker_wrapper: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73
+solidity_vrf_consumer_interface: ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.bin ecc99378aa798014de9db42b2eb81320778b0663dbe208008dad75ccdc1d4366
+solidity_vrf_consumer_interface_v08: ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.bin b14f9136b15e3dc9d6154d5700f3ed4cf88ddc4f70f20c3bb57fc46050904c8f
+solidity_vrf_coordinator_interface: ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.bin a23d3c395156804788c7f6fbda2994e8f7184304c0f0c9f2c4ddeaf073d346d2
+solidity_vrf_request_id: ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin 383b59e861732c1911ddb7b002c6158608496ce889979296527215fd0366b318
+solidity_vrf_request_id_v08: ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin f2559015d6f3e5d285c57b011be9b2300632e93dd6c4524e58202d6200f09edc
+solidity_vrf_v08_verifier_wrapper: ../../contracts/solc/v0.8.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.8.6/VRFTestHelper/VRFTestHelper.bin f37f8b21a81c113085c6137835a2246db6ebda07da455c4f2b5c7ec60c725c3b
+solidity_vrf_verifier_wrapper: ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.bin 44c2b67d8d2990ab580453deb29d63508c6147a3dc49908a1db563bef06e6474
+solidity_vrf_wrapper: ../../contracts/solc/v0.6/VRF/VRF.abi ../../contracts/solc/v0.6/VRF/VRF.bin 04ede5b83c06ba5b76ef99c081c72928007d8a7aaefcf21449a46a07cbd4bfc2
+streams_lookup_compatible_interface: ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.abi ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.bin feb92cc666df21ea04ab9d7a588a513847b01b2f66fc167d06ab28ef2b17e015
+streams_lookup_upkeep_wrapper: ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.bin b1a598963cacac51ed4706538d0f142bdc0d94b9a4b13e2d402131cdf05c9bcf
+test_api_consumer_wrapper: ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.abi ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.bin ed10893cb18894c18e275302329c955f14ea2de37ee044f84aa1e067ac5ea71e
+trusted_blockhash_store: ../../contracts/solc/v0.8.6/TrustedBlockhashStore/TrustedBlockhashStore.abi ../../contracts/solc/v0.8.6/TrustedBlockhashStore/TrustedBlockhashStore.bin 98cb0dc06c15af5dcd3b53bdfc98e7ed2489edc96a42203294ac2fc0efdda02b
+type_and_version_interface_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.bin bc9c3a6e73e3ebd5b58754df0deeb3b33f4bb404d5709bb904aed51d32f4b45e
+upkeep_counter_wrapper: ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.bin 77f000229a501f638dd2dc439859257f632894c728b31e68aea4f6d6c52f1b71
+upkeep_perform_counter_restrictive_wrapper: ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin 20955b21acceb58355fa287b29194a73edf5937067ba7140667301017cb2b24c
+upkeep_transcoder: ../../contracts/solc/v0.8.6/UpkeepTranscoder/UpkeepTranscoder.abi ../../contracts/solc/v0.8.6/UpkeepTranscoder/UpkeepTranscoder.bin 336c92a981597be26508455f81a908a0784a817b129a59686c5b2c4afcba730a
+verifiable_load_log_trigger_upkeep_wrapper: ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep/VerifiableLoadLogTriggerUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep/VerifiableLoadLogTriggerUpkeep.bin fb674ba44c0e8f3b385cd10b2f7dea5cd07b5f38df08066747e8b1542e152557
+verifiable_load_streams_lookup_upkeep_wrapper: ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep/VerifiableLoadStreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep/VerifiableLoadStreamsLookupUpkeep.bin 785f68c44bfff070505eaa65e38a1af94046e5f9afc1189bcf2c8cfcd1102d66
+verifiable_load_upkeep_wrapper: ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep/VerifiableLoadUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep/VerifiableLoadUpkeep.bin a3e02c43756ea91e7ce4b81e48c11648f1d12f6663c236780147e41dfa36ebee
+vrf_consumer_v2: ../../contracts/solc/v0.8.6/VRFConsumerV2/VRFConsumerV2.abi ../../contracts/solc/v0.8.6/VRFConsumerV2/VRFConsumerV2.bin 9ef258bf8e9f8d880fd229ceb145593d91e24fc89366baa0bf19169c5787d15f
+vrf_consumer_v2_plus_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample/VRFConsumerV2PlusUpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample/VRFConsumerV2PlusUpgradeableExample.bin 3155c611e4d6882e9324b6e975033b31356776ea8b031ca63d63da37589d583b
+vrf_consumer_v2_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.bin f1790a9a2f2a04c730593e483459709cb89e897f8a19d7a3ac0cfe6a97265e6e
+vrf_coordinator_mock: ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.abi ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.bin 5c495cf8df1f46d8736b9150cdf174cce358cb8352f60f0d5bb9581e23920501
+vrf_coordinator_v2: ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.bin 295f35ce282060317dfd01f45959f5a2b05ba26913e422fbd4fb6bf90b107006
+vrf_coordinator_v2_5: ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.bin b0e7c42a30b36d9d31fa9a3f26bad7937152e3dddee5bd8dd3d121390c879ab6
+vrf_coordinator_v2_plus_v2_example: ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.bin 4a5b86701983b1b65f0a8dfa116b3f6d75f8f706fa274004b57bdf5992e4cec3
vrf_coordinator_v2plus: ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus.bin e4409bbe361258273458a5c99408b3d7f0cc57a2560dee91c0596cc6d6f738be
-vrf_coordinator_v2plus_interface: ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal.abi ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal.bin 834a2ce0e83276372a0e1446593fd89798f4cf6dc95d4be0113e99fadf61558b
-vrf_external_sub_owner_example: ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample.bin 14f888eb313930b50233a6f01ea31eba0206b7f41a41f6311670da8bb8a26963
-vrf_load_test_external_sub_owner: ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner.abi ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner.bin 2097faa70265e420036cc8a3efb1f1e0836ad2d7323b295b9a26a125dbbe6c7d
-vrf_load_test_ownerless_consumer: ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer.abi ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer.bin 74f914843cbc70b9c3079c3e1c709382ce415225e8bb40113e7ac018bfcb0f5c
-vrf_load_test_with_metrics: ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics.bin 8ab9de5816fbdf93a2865e2711b85a39a6fc9c413a4b336578c485be1158d430
-vrf_malicious_consumer_v2: ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2.bin 9755fa8ffc7f5f0b337d5d413d77b0c9f6cd6f68c31727d49acdf9d4a51bc522
-vrf_malicious_consumer_v2_plus: ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus.bin e2a72638e11da807b6533d037e7e5aaeed695efd5035777b8e20d2f8973a574c
-vrf_owner: ../../contracts/solc/v0.8.6/VRFOwner.abi ../../contracts/solc/v0.8.6/VRFOwner.bin eccfae5ee295b5850e22f61240c469f79752b8d9a3bac5d64aec7ac8def2f6cb
-vrf_owner_test_consumer: ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer.bin 0537bbe96c5a8bbd44d0a65fbb7e51f6a9f9e75f4673225845ac1ba33f4e7974
-vrf_ownerless_consumer_example: ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample.abi ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample.bin 9893b3805863273917fb282eed32274e32aa3d5c2a67a911510133e1218132be
-vrf_single_consumer_example: ../../contracts/solc/v0.8.6/VRFSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFSingleConsumerExample.bin 892a5ed35da2e933f7fd7835cd6f7f70ef3aa63a9c03a22c5b1fd026711b0ece
-vrf_v2_consumer_wrapper: ../../contracts/solc/v0.8.6/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer.bin 12368b3b5e06392440143a13b94c0ea2f79c4c897becc3b060982559e10ace40
-vrf_v2plus_load_test_with_metrics: ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics.bin 0a89cb7ed9dfb42f91e559b03dc351ccdbe14d281a7ab71c63bd3f47eeed7711
-vrf_v2plus_single_consumer: ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample.bin 6226d05afa1664033b182bfbdde11d5dfb1d4c8e3eb0bd0448c8bfb76f5b96e4
-vrf_v2plus_sub_owner: ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample.bin 7541f986571b8a5671a256edc27ae9b8df9bcdff45ac3b96e5609bbfcc320e4e
-vrf_v2plus_upgraded_version: ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion.bin c0793d86fb6e45342c4424184fe241c16da960c0b4de76816364b933344d0756
-vrfv2_proxy_admin: ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin.abi ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin.bin 402b1103087ffe1aa598854a8f8b38f8cd3de2e3aaa86369e28017a9157f4980
-vrfv2_reverting_example: ../../contracts/solc/v0.8.6/VRFV2RevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2RevertingExample.bin 1ae46f80351d428bd85ba58b9041b2a608a1845300d79a8fed83edf96606de87
-vrfv2_transparent_upgradeable_proxy: ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy.abi ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy.bin fe1a8e6852fbd06d91f64315c5cede86d340891f5b5cc981fb5b86563f7eac3f
-vrfv2_wrapper: ../../contracts/solc/v0.8.6/VRFV2Wrapper.abi ../../contracts/solc/v0.8.6/VRFV2Wrapper.bin d5e9a982325d2d4f517c4f2bc818795f61555408ef4b38fb59b923d144970e38
-vrfv2_wrapper_consumer_example: ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample.bin 3c5c9f1c501e697a7e77e959b48767e2a0bb1372393fd7686f7aaef3eb794231
-vrfv2_wrapper_interface: ../../contracts/solc/v0.8.6/VRFV2WrapperInterface.abi ../../contracts/solc/v0.8.6/VRFV2WrapperInterface.bin ff8560169de171a68b360b7438d13863682d07040d984fd0fb096b2379421003
-vrfv2plus_client: ../../contracts/solc/v0.8.6/VRFV2PlusClient.abi ../../contracts/solc/v0.8.6/VRFV2PlusClient.bin 3ffbfa4971a7e5f46051a26b1722613f265d89ea1867547ecec58500953a9501
-vrfv2plus_consumer_example: ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample.bin 2c480a6d7955d33a00690fdd943486d95802e48a03f3cc243df314448e4ddb2c
-vrfv2plus_malicious_migrator: ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator.abi ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator.bin 80dbc98be5e42246960c889d29488f978d3db0127e95e9b295352c481d8c9b07
-vrfv2plus_reverting_example: ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample.bin 6c9053a94f90b8151964d3311310478b57744fbbd153e8ee742ed570e1e49798
-vrfv2plus_wrapper: ../../contracts/solc/v0.8.6/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapper.bin 934bafba386b934f491827e535306726069f4cafef9125079ea88abf0d808877
-vrfv2plus_wrapper_consumer_example: ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample.bin a14c4c6e2299cd963a8f0ed069e61dd135af5aad4c13a94f6ea7e086eced7191
-vrfv2plus_wrapper_load_test_consumer: ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer.bin 55e3bd534045125fb6579a201ab766185e9b0fac5737b4f37897bb69c9f599fa
+vrf_coordinator_v2plus_interface: ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.abi ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.bin 834a2ce0e83276372a0e1446593fd89798f4cf6dc95d4be0113e99fadf61558b
+vrf_external_sub_owner_example: ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.bin 14f888eb313930b50233a6f01ea31eba0206b7f41a41f6311670da8bb8a26963
+vrf_load_test_external_sub_owner: ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.abi ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.bin 2097faa70265e420036cc8a3efb1f1e0836ad2d7323b295b9a26a125dbbe6c7d
+vrf_load_test_ownerless_consumer: ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer/VRFLoadTestOwnerlessConsumer.abi ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer/VRFLoadTestOwnerlessConsumer.bin 74f914843cbc70b9c3079c3e1c709382ce415225e8bb40113e7ac018bfcb0f5c
+vrf_load_test_with_metrics: ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics/VRFV2LoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics/VRFV2LoadTestWithMetrics.bin 8ab9de5816fbdf93a2865e2711b85a39a6fc9c413a4b336578c485be1158d430
+vrf_malicious_consumer_v2: ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2/VRFMaliciousConsumerV2.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2/VRFMaliciousConsumerV2.bin 9755fa8ffc7f5f0b337d5d413d77b0c9f6cd6f68c31727d49acdf9d4a51bc522
+vrf_malicious_consumer_v2_plus: ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus/VRFMaliciousConsumerV2Plus.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus/VRFMaliciousConsumerV2Plus.bin e2a72638e11da807b6533d037e7e5aaeed695efd5035777b8e20d2f8973a574c
+vrf_owner: ../../contracts/solc/v0.8.6/VRFOwner/VRFOwner.abi ../../contracts/solc/v0.8.6/VRFOwner/VRFOwner.bin eccfae5ee295b5850e22f61240c469f79752b8d9a3bac5d64aec7ac8def2f6cb
+vrf_owner_test_consumer: ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer/VRFV2OwnerTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer/VRFV2OwnerTestConsumer.bin 0537bbe96c5a8bbd44d0a65fbb7e51f6a9f9e75f4673225845ac1ba33f4e7974
+vrf_ownerless_consumer_example: ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample/VRFOwnerlessConsumerExample.abi ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample/VRFOwnerlessConsumerExample.bin 9893b3805863273917fb282eed32274e32aa3d5c2a67a911510133e1218132be
+vrf_single_consumer_example: ../../contracts/solc/v0.8.6/VRFSingleConsumerExample/VRFSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFSingleConsumerExample/VRFSingleConsumerExample.bin 892a5ed35da2e933f7fd7835cd6f7f70ef3aa63a9c03a22c5b1fd026711b0ece
+vrf_v2_consumer_wrapper: ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.bin 12368b3b5e06392440143a13b94c0ea2f79c4c897becc3b060982559e10ace40
+vrf_v2plus_load_test_with_metrics: ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.bin 0a89cb7ed9dfb42f91e559b03dc351ccdbe14d281a7ab71c63bd3f47eeed7711
+vrf_v2plus_single_consumer: ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.bin 6226d05afa1664033b182bfbdde11d5dfb1d4c8e3eb0bd0448c8bfb76f5b96e4
+vrf_v2plus_sub_owner: ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.bin 7541f986571b8a5671a256edc27ae9b8df9bcdff45ac3b96e5609bbfcc320e4e
+vrf_v2plus_upgraded_version: ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.bin c0793d86fb6e45342c4424184fe241c16da960c0b4de76816364b933344d0756
+vrfv2_proxy_admin: ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.abi ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.bin 402b1103087ffe1aa598854a8f8b38f8cd3de2e3aaa86369e28017a9157f4980
+vrfv2_reverting_example: ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.bin 1ae46f80351d428bd85ba58b9041b2a608a1845300d79a8fed83edf96606de87
+vrfv2_transparent_upgradeable_proxy: ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.abi ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.bin fe1a8e6852fbd06d91f64315c5cede86d340891f5b5cc981fb5b86563f7eac3f
+vrfv2_wrapper: ../../contracts/solc/v0.8.6/VRFV2Wrapper/VRFV2Wrapper.abi ../../contracts/solc/v0.8.6/VRFV2Wrapper/VRFV2Wrapper.bin d5e9a982325d2d4f517c4f2bc818795f61555408ef4b38fb59b923d144970e38
+vrfv2_wrapper_consumer_example: ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample/VRFV2WrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample/VRFV2WrapperConsumerExample.bin 3c5c9f1c501e697a7e77e959b48767e2a0bb1372393fd7686f7aaef3eb794231
+vrfv2_wrapper_interface: ../../contracts/solc/v0.8.6/VRFV2WrapperInterface/VRFV2WrapperInterface.abi ../../contracts/solc/v0.8.6/VRFV2WrapperInterface/VRFV2WrapperInterface.bin ff8560169de171a68b360b7438d13863682d07040d984fd0fb096b2379421003
+vrfv2plus_client: ../../contracts/solc/v0.8.6/VRFV2PlusClient/VRFV2PlusClient.abi ../../contracts/solc/v0.8.6/VRFV2PlusClient/VRFV2PlusClient.bin 3ffbfa4971a7e5f46051a26b1722613f265d89ea1867547ecec58500953a9501
+vrfv2plus_consumer_example: ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample/VRFV2PlusConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample/VRFV2PlusConsumerExample.bin 2c480a6d7955d33a00690fdd943486d95802e48a03f3cc243df314448e4ddb2c
+vrfv2plus_malicious_migrator: ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator/VRFV2PlusMaliciousMigrator.abi ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator/VRFV2PlusMaliciousMigrator.bin 80dbc98be5e42246960c889d29488f978d3db0127e95e9b295352c481d8c9b07
+vrfv2plus_reverting_example: ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample/VRFV2PlusRevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample/VRFV2PlusRevertingExample.bin 6c9053a94f90b8151964d3311310478b57744fbbd153e8ee742ed570e1e49798
+vrfv2plus_wrapper: ../../contracts/solc/v0.8.6/VRFV2PlusWrapper/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapper/VRFV2PlusWrapper.bin 934bafba386b934f491827e535306726069f4cafef9125079ea88abf0d808877
+vrfv2plus_wrapper_consumer_example: ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.bin a14c4c6e2299cd963a8f0ed069e61dd135af5aad4c13a94f6ea7e086eced7191
+vrfv2plus_wrapper_load_test_consumer: ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.bin 55e3bd534045125fb6579a201ab766185e9b0fac5737b4f37897bb69c9f599fa
diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go
index 67090d16c6..3965c15908 100644
--- a/core/gethwrappers/go_generate.go
+++ b/core/gethwrappers/go_generate.go
@@ -5,139 +5,139 @@ package gethwrappers
// Make sure solidity compiler artifacts are up-to-date. Only output stdout on failure.
//go:generate ./generation/compile_contracts.sh
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator.bin FluxAggregator flux_aggregator_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRF.abi ../../contracts/solc/v0.6/VRF.bin VRF solidity_vrf_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFTestHelper.abi ../../contracts/solc/v0.6/VRFTestHelper.bin VRFTestHelper solidity_vrf_verifier_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator.bin VRFCoordinator solidity_vrf_coordinator_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer.bin VRFConsumer solidity_vrf_consumer_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper.bin VRFRequestIDBaseTestHelper solidity_vrf_request_id
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/Flags.abi ../../contracts/solc/v0.6/Flags.bin Flags flags_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/Oracle.abi ../../contracts/solc/v0.6/Oracle.bin Oracle oracle_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/TestAPIConsumer.abi ../../contracts/solc/v0.6/TestAPIConsumer.bin TestAPIConsumer test_api_consumer_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/MockETHLINKAggregator.abi ../../contracts/solc/v0.6/MockETHLINKAggregator.bin MockETHLINKAggregator mock_ethlink_aggregator_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/MockGASAggregator.abi ../../contracts/solc/v0.6/MockGASAggregator.bin MockGASAggregator mock_gas_aggregator_wrapper
-
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/Consumer.abi ../../contracts/solc/v0.7/Consumer.bin Consumer consumer_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/MultiWordConsumer.abi ../../contracts/solc/v0.7/MultiWordConsumer.bin MultiWordConsumer multiwordconsumer_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/Operator.abi ../../contracts/solc/v0.8.19/Operator.bin Operator operator_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory.bin OperatorFactory operator_factory
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder.bin AuthorizedForwarder authorized_forwarder
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/AuthorizedReceiver.abi ../../contracts/solc/v0.8.19/AuthorizedReceiver.bin AuthorizedReceiver authorized_receiver
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.bin FluxAggregator flux_aggregator_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRF/VRF.abi ../../contracts/solc/v0.6/VRF/VRF.bin VRF solidity_vrf_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.bin VRFTestHelper solidity_vrf_verifier_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.bin VRFCoordinator solidity_vrf_coordinator_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.bin VRFConsumer solidity_vrf_consumer_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin VRFRequestIDBaseTestHelper solidity_vrf_request_id
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/Flags/Flags.abi ../../contracts/solc/v0.6/Flags/Flags.bin Flags flags_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/Oracle/Oracle.abi ../../contracts/solc/v0.6/Oracle/Oracle.bin Oracle oracle_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.abi ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.bin TestAPIConsumer test_api_consumer_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.abi ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.bin MockETHLINKAggregator mock_ethlink_aggregator_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.abi ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.bin MockGASAggregator mock_gas_aggregator_wrapper
+
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/Consumer/Consumer.abi ../../contracts/solc/v0.7/Consumer/Consumer.bin Consumer consumer_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.abi ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.bin MultiWordConsumer multiwordconsumer_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin Operator operator_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin OperatorFactory operator_factory
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin AuthorizedForwarder authorized_forwarder
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.abi ../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.bin AuthorizedReceiver authorized_receiver
//go:generate go run ./generation/generate/wrap.go OffchainAggregator/OffchainAggregator.abi - OffchainAggregator offchain_aggregator_wrapper
// Automation
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/KeeperRegistry1_1.abi ../../contracts/solc/v0.7/KeeperRegistry1_1.bin KeeperRegistry keeper_registry_wrapper1_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/KeeperRegistry1_1Mock.abi ../../contracts/solc/v0.7/KeeperRegistry1_1Mock.bin KeeperRegistryMock keeper_registry_wrapper1_1_mock
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.7/UpkeepPerformCounterRestrictive.bin UpkeepPerformCounterRestrictive upkeep_perform_counter_restrictive_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/UpkeepCounter.abi ../../contracts/solc/v0.7/UpkeepCounter.bin UpkeepCounter upkeep_counter_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/CronUpkeepFactory.abi - CronUpkeepFactory cron_upkeep_factory_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/CronUpkeep.abi - CronUpkeep cron_upkeep_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar.bin KeeperRegistrar keeper_registrar_wrapper1_2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock.bin KeeperRegistrarMock keeper_registrar_wrapper1_2_mock
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2.bin KeeperRegistry keeper_registry_wrapper1_2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/TypeAndVersionInterface.bin TypeAndVersionInterface type_and_version_interface_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin KeeperRegistryCheckUpkeepGasUsageWrapper gas_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin KeeperRegistryCheckUpkeepGasUsageWrapperMock gas_wrapper_mock
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_3.bin KeeperRegistry keeper_registry_wrapper1_3
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3.bin KeeperRegistryLogic keeper_registry_logic1_3
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistrar2_0.bin KeeperRegistrar keeper_registrar_wrapper2_0
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0.bin KeeperRegistry keeper_registry_wrapper2_0
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0.bin KeeperRegistryLogic keeper_registry_logic2_0
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/UpkeepTranscoder.abi ../../contracts/solc/v0.8.6/UpkeepTranscoder.bin UpkeepTranscoder upkeep_transcoder
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep.bin VerifiableLoadUpkeep verifiable_load_upkeep_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep.bin VerifiableLoadStreamsLookupUpkeep verifiable_load_streams_lookup_upkeep_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep.bin VerifiableLoadLogTriggerUpkeep verifiable_load_log_trigger_upkeep_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/StreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/StreamsLookupUpkeep.bin StreamsLookupUpkeep streams_lookup_upkeep_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface.abi ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface.bin StreamsLookupCompatibleInterface streams_lookup_compatible_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark.bin AutomationConsumerBenchmark automation_consumer_benchmark
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1.bin AutomationRegistrar automation_registrar_wrapper2_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperRegistry2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistry2_1.bin KeeperRegistry keeper_registry_wrapper_2_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1.bin KeeperRegistryLogicA keeper_registry_logic_a_wrapper_2_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1.bin KeeperRegistryLogicB keeper_registry_logic_b_wrapper_2_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster.bin IKeeperRegistryMaster i_keeper_registry_master_wrapper_2_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation.bin ILogAutomation i_log_automation
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1.bin AutomationUtils automation_utils_2_1
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic.bin AutomationForwarderLogic automation_forwarder_logic
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter.bin LogUpkeepCounter log_upkeep_counter_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup.bin LogTriggeredStreamsLookup log_triggered_streams_lookup_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol.bin DummyProtocol dummy_protocol_wrapper
-
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer.bin KeeperConsumer keeper_consumer_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance.bin KeeperConsumerPerformance keeper_consumer_performance_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker.bin PerformDataChecker perform_data_checker_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter.bin UpkeepCounter upkeep_counter_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive.bin UpkeepPerformCounterRestrictive upkeep_perform_counter_restrictive_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.abi ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.bin KeeperRegistry keeper_registry_wrapper1_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.abi ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.bin KeeperRegistryMock keeper_registry_wrapper1_1_mock
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.7/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin UpkeepPerformCounterRestrictive upkeep_perform_counter_restrictive_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.7/UpkeepCounter/UpkeepCounter.bin UpkeepCounter upkeep_counter_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - CronUpkeepFactory cron_upkeep_factory_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeep.abi - CronUpkeep cron_upkeep_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.bin KeeperRegistrar keeper_registrar_wrapper1_2
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.bin KeeperRegistrarMock keeper_registrar_wrapper1_2_mock
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.bin KeeperRegistry keeper_registry_wrapper1_2
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.bin TypeAndVersionInterface type_and_version_interface_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin KeeperRegistryCheckUpkeepGasUsageWrapper gas_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin KeeperRegistryCheckUpkeepGasUsageWrapperMock gas_wrapper_mock
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.bin KeeperRegistry keeper_registry_wrapper1_3
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3/KeeperRegistryLogic1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3/KeeperRegistryLogic1_3.bin KeeperRegistryLogic keeper_registry_logic1_3
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar2_0/KeeperRegistrar2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistrar2_0/KeeperRegistrar2_0.bin KeeperRegistrar keeper_registrar_wrapper2_0
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.bin KeeperRegistry keeper_registry_wrapper2_0
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0/KeeperRegistryLogic2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0/KeeperRegistryLogic2_0.bin KeeperRegistryLogic keeper_registry_logic2_0
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/UpkeepTranscoder/UpkeepTranscoder.abi ../../contracts/solc/v0.8.6/UpkeepTranscoder/UpkeepTranscoder.bin UpkeepTranscoder upkeep_transcoder
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep/VerifiableLoadUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadUpkeep/VerifiableLoadUpkeep.bin VerifiableLoadUpkeep verifiable_load_upkeep_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep/VerifiableLoadStreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadStreamsLookupUpkeep/VerifiableLoadStreamsLookupUpkeep.bin VerifiableLoadStreamsLookupUpkeep verifiable_load_streams_lookup_upkeep_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep/VerifiableLoadLogTriggerUpkeep.abi ../../contracts/solc/v0.8.16/VerifiableLoadLogTriggerUpkeep/VerifiableLoadLogTriggerUpkeep.bin VerifiableLoadLogTriggerUpkeep verifiable_load_log_trigger_upkeep_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.bin StreamsLookupUpkeep streams_lookup_upkeep_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.abi ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.bin StreamsLookupCompatibleInterface streams_lookup_compatible_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.bin AutomationConsumerBenchmark automation_consumer_benchmark
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin AutomationRegistrar automation_registrar_wrapper2_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.bin KeeperRegistry keeper_registry_wrapper_2_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1/KeeperRegistryLogicA2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1/KeeperRegistryLogicA2_1.bin KeeperRegistryLogicA keeper_registry_logic_a_wrapper_2_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1/KeeperRegistryLogicB2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1/KeeperRegistryLogicB2_1.bin KeeperRegistryLogicB keeper_registry_logic_b_wrapper_2_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin IKeeperRegistryMaster i_keeper_registry_master_wrapper_2_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.bin ILogAutomation i_log_automation
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin AutomationUtils automation_utils_2_1
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin AutomationForwarderLogic automation_forwarder_logic
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin LogUpkeepCounter log_upkeep_counter_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin LogTriggeredStreamsLookup log_triggered_streams_lookup_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.bin DummyProtocol dummy_protocol_wrapper
+
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.bin KeeperConsumer keeper_consumer_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.bin KeeperConsumerPerformance keeper_consumer_performance_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin PerformDataChecker perform_data_checker_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.bin UpkeepCounter upkeep_counter_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin UpkeepPerformCounterRestrictive upkeep_perform_counter_restrictive_wrapper
// v0.8.6 VRFConsumer
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorMock.abi ../../contracts/solc/v0.8.6/VRFCoordinatorMock.bin VRFCoordinatorMock vrf_coordinator_mock
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer.bin VRFConsumer solidity_vrf_consumer_interface_v08
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper.bin VRFRequestIDBaseTestHelper solidity_vrf_request_id_v08
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample.abi ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample.bin VRFOwnerlessConsumerExample vrf_ownerless_consumer_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer.abi ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer.bin VRFLoadTestOwnerlessConsumer vrf_load_test_ownerless_consumer
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner.abi ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner.bin VRFLoadTestExternalSubOwner vrf_load_test_external_sub_owner
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics.bin VRFV2LoadTestWithMetrics vrf_load_test_with_metrics
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer.bin VRFV2OwnerTestConsumer vrf_owner_test_consumer
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer.bin VRFv2Consumer vrf_v2_consumer_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.abi ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.bin VRFCoordinatorMock vrf_coordinator_mock
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.bin VRFConsumer solidity_vrf_consumer_interface_v08
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin VRFRequestIDBaseTestHelper solidity_vrf_request_id_v08
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample/VRFOwnerlessConsumerExample.abi ../../contracts/solc/v0.8.6/VRFOwnerlessConsumerExample/VRFOwnerlessConsumerExample.bin VRFOwnerlessConsumerExample vrf_ownerless_consumer_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer/VRFLoadTestOwnerlessConsumer.abi ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer/VRFLoadTestOwnerlessConsumer.bin VRFLoadTestOwnerlessConsumer vrf_load_test_ownerless_consumer
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.abi ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.bin VRFLoadTestExternalSubOwner vrf_load_test_external_sub_owner
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics/VRFV2LoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics/VRFV2LoadTestWithMetrics.bin VRFV2LoadTestWithMetrics vrf_load_test_with_metrics
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer/VRFV2OwnerTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2OwnerTestConsumer/VRFV2OwnerTestConsumer.bin VRFV2OwnerTestConsumer vrf_owner_test_consumer
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.bin VRFv2Consumer vrf_v2_consumer_wrapper
//go:generate go run ./generation/generate_link/wrap_link.go
// VRF V2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BlockhashStore.abi ../../contracts/solc/v0.8.6/BlockhashStore.bin BlockhashStore blockhash_store
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BatchBlockhashStore.abi ../../contracts/solc/v0.8.6/BatchBlockhashStore.bin BatchBlockhashStore batch_blockhash_store
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2.bin BatchVRFCoordinatorV2 batch_vrf_coordinator_v2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFOwner.abi ../../contracts/solc/v0.8.6/VRFOwner.bin VRFOwner vrf_owner
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2.bin VRFCoordinatorV2 vrf_coordinator_v2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumerV2.abi ../../contracts/solc/v0.8.6/VRFConsumerV2.bin VRFConsumerV2 vrf_consumer_v2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2.bin VRFMaliciousConsumerV2 vrf_malicious_consumer_v2
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BlockhashStore/BlockhashStore.abi ../../contracts/solc/v0.8.6/BlockhashStore/BlockhashStore.bin BlockhashStore blockhash_store
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BatchBlockhashStore/BatchBlockhashStore.abi ../../contracts/solc/v0.8.6/BatchBlockhashStore/BatchBlockhashStore.bin BatchBlockhashStore batch_blockhash_store
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/BatchVRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/BatchVRFCoordinatorV2.bin BatchVRFCoordinatorV2 batch_vrf_coordinator_v2
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFOwner/VRFOwner.abi ../../contracts/solc/v0.8.6/VRFOwner/VRFOwner.bin VRFOwner vrf_owner
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.bin VRFCoordinatorV2 vrf_coordinator_v2
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumerV2/VRFConsumerV2.abi ../../contracts/solc/v0.8.6/VRFConsumerV2/VRFConsumerV2.bin VRFConsumerV2 vrf_consumer_v2
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2/VRFMaliciousConsumerV2.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2/VRFMaliciousConsumerV2.bin VRFMaliciousConsumerV2 vrf_malicious_consumer_v2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFTestHelper.abi ../../contracts/solc/v0.8.6/VRFTestHelper.bin VRFV08TestHelper solidity_vrf_v08_verifier_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFSingleConsumerExample.bin VRFSingleConsumerExample vrf_single_consumer_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.8.6/VRFTestHelper/VRFTestHelper.bin VRFV08TestHelper solidity_vrf_v08_verifier_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFSingleConsumerExample/VRFSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFSingleConsumerExample/VRFSingleConsumerExample.bin VRFSingleConsumerExample vrf_single_consumer_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample.bin VRFExternalSubOwnerExample vrf_external_sub_owner_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.bin VRFExternalSubOwnerExample vrf_external_sub_owner_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2RevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2RevertingExample.bin VRFV2RevertingExample vrfv2_reverting_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.bin VRFV2RevertingExample vrfv2_reverting_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample.bin VRFConsumerV2UpgradeableExample vrf_consumer_v2_upgradeable_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.bin VRFConsumerV2UpgradeableExample vrf_consumer_v2_upgradeable_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy.abi ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy.bin VRFV2TransparentUpgradeableProxy vrfv2_transparent_upgradeable_proxy
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin.abi ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin.bin VRFV2ProxyAdmin vrfv2_proxy_admin
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper.bin ChainSpecificUtilHelper chain_specific_util_helper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.abi ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.bin VRFV2TransparentUpgradeableProxy vrfv2_transparent_upgradeable_proxy
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.abi ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.bin VRFV2ProxyAdmin vrfv2_proxy_admin
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.bin ChainSpecificUtilHelper chain_specific_util_helper
// VRF V2 Wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2Wrapper.abi ../../contracts/solc/v0.8.6/VRFV2Wrapper.bin VRFV2Wrapper vrfv2_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2WrapperInterface.abi ../../contracts/solc/v0.8.6/VRFV2WrapperInterface.bin VRFV2WrapperInterface vrfv2_wrapper_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample.bin VRFV2WrapperConsumerExample vrfv2_wrapper_consumer_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2Wrapper/VRFV2Wrapper.abi ../../contracts/solc/v0.8.6/VRFV2Wrapper/VRFV2Wrapper.bin VRFV2Wrapper vrfv2_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2WrapperInterface/VRFV2WrapperInterface.abi ../../contracts/solc/v0.8.6/VRFV2WrapperInterface/VRFV2WrapperInterface.bin VRFV2WrapperInterface vrfv2_wrapper_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample/VRFV2WrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2WrapperConsumerExample/VRFV2WrapperConsumerExample.bin VRFV2WrapperConsumerExample vrfv2_wrapper_consumer_example
// Keepers X VRF v2
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeepersVRFConsumer.abi ../../contracts/solc/v0.8.6/KeepersVRFConsumer.bin KeepersVRFConsumer keepers_vrf_consumer
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.abi ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.bin KeepersVRFConsumer keepers_vrf_consumer
// VRF V2Plus
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal.abi ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal.bin IVRFCoordinatorV2PlusInternal vrf_coordinator_v2plus_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus.bin BatchVRFCoordinatorV2Plus batch_vrf_coordinator_v2plus
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/TrustedBlockhashStore.abi ../../contracts/solc/v0.8.6/TrustedBlockhashStore.bin TrustedBlockhashStore trusted_blockhash_store
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample.bin VRFV2PlusConsumerExample vrfv2plus_consumer_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5.bin VRFCoordinatorV2_5 vrf_coordinator_v2_5
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapper.bin VRFV2PlusWrapper vrfv2plus_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample.bin VRFV2PlusWrapperConsumerExample vrfv2plus_wrapper_consumer_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus.bin VRFMaliciousConsumerV2Plus vrf_malicious_consumer_v2_plus
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample.bin VRFV2PlusSingleConsumerExample vrf_v2plus_single_consumer
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample.bin VRFV2PlusExternalSubOwnerExample vrf_v2plus_sub_owner
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample.bin VRFV2PlusRevertingExample vrfv2plus_reverting_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample.bin VRFConsumerV2PlusUpgradeableExample vrf_consumer_v2_plus_upgradeable_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusClient.abi ../../contracts/solc/v0.8.6/VRFV2PlusClient.bin VRFV2PlusClient vrfv2plus_client
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example.bin VRFCoordinatorV2Plus_V2Example vrf_coordinator_v2_plus_v2_example
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator.abi ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator.bin VRFV2PlusMaliciousMigrator vrfv2plus_malicious_migrator
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics.bin VRFV2PlusLoadTestWithMetrics vrf_v2plus_load_test_with_metrics
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion.bin VRFCoordinatorV2PlusUpgradedVersion vrf_v2plus_upgraded_version
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer.bin VRFV2PlusWrapperLoadTestConsumer vrfv2plus_wrapper_load_test_consumer
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.abi ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.bin IVRFCoordinatorV2PlusInternal vrf_coordinator_v2plus_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.bin BatchVRFCoordinatorV2Plus batch_vrf_coordinator_v2plus
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/TrustedBlockhashStore/TrustedBlockhashStore.abi ../../contracts/solc/v0.8.6/TrustedBlockhashStore/TrustedBlockhashStore.bin TrustedBlockhashStore trusted_blockhash_store
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample/VRFV2PlusConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusConsumerExample/VRFV2PlusConsumerExample.bin VRFV2PlusConsumerExample vrfv2plus_consumer_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.bin VRFCoordinatorV2_5 vrf_coordinator_v2_5
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusWrapper/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapper/VRFV2PlusWrapper.bin VRFV2PlusWrapper vrfv2plus_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.bin VRFV2PlusWrapperConsumerExample vrfv2plus_wrapper_consumer_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus/VRFMaliciousConsumerV2Plus.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2Plus/VRFMaliciousConsumerV2Plus.bin VRFMaliciousConsumerV2Plus vrf_malicious_consumer_v2_plus
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.bin VRFV2PlusSingleConsumerExample vrf_v2plus_single_consumer
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.bin VRFV2PlusExternalSubOwnerExample vrf_v2plus_sub_owner
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample/VRFV2PlusRevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2PlusRevertingExample/VRFV2PlusRevertingExample.bin VRFV2PlusRevertingExample vrfv2plus_reverting_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample/VRFConsumerV2PlusUpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2PlusUpgradeableExample/VRFConsumerV2PlusUpgradeableExample.bin VRFConsumerV2PlusUpgradeableExample vrf_consumer_v2_plus_upgradeable_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusClient/VRFV2PlusClient.abi ../../contracts/solc/v0.8.6/VRFV2PlusClient/VRFV2PlusClient.bin VRFV2PlusClient vrfv2plus_client
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.bin VRFCoordinatorV2Plus_V2Example vrf_coordinator_v2_plus_v2_example
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator/VRFV2PlusMaliciousMigrator.abi ../../contracts/solc/v0.8.6/VRFV2PlusMaliciousMigrator/VRFV2PlusMaliciousMigrator.bin VRFV2PlusMaliciousMigrator vrfv2plus_malicious_migrator
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.bin VRFV2PlusLoadTestWithMetrics vrf_v2plus_load_test_with_metrics
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.bin VRFCoordinatorV2PlusUpgradedVersion vrf_v2plus_upgraded_version
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.6/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.bin VRFV2PlusWrapperLoadTestConsumer vrfv2plus_wrapper_load_test_consumer
// Aggregators
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface.bin AggregatorV2V3Interface aggregator_v2v3_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV3Interface.bin AggregatorV3Interface aggregator_v3_interface
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy.bin MockAggregatorProxy mock_aggregator_proxy
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.bin AggregatorV2V3Interface aggregator_v2v3_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.bin AggregatorV3Interface aggregator_v3_interface
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin MockAggregatorProxy mock_aggregator_proxy
// Log tester
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter.bin LogEmitter log_emitter
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.bin LogEmitter log_emitter
// Chainlink Functions
//go:generate go generate ./functions
diff --git a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index abc3b47db2..293defcfbe 100644
--- a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -1,10 +1,10 @@
GETH_VERSION: 1.12.0
-errored_verifier: ../../../contracts/solc/v0.8.16/ErroredVerifier.abi ../../../contracts/solc/v0.8.16/ErroredVerifier.bin 510d18a58bfda646be35e46491baf73041eb333a349615465b20e2b5b41c5f73
-exposed_verifier: ../../../contracts/solc/v0.8.16/ExposedVerifier.abi ../../../contracts/solc/v0.8.16/ExposedVerifier.bin 6932cea8f2738e874d3ec9e1a4231d2421704030c071d9e15dd2f7f08482c246
-fee_manager: ../../../contracts/solc/v0.8.16/FeeManager.abi ../../../contracts/solc/v0.8.16/FeeManager.bin 1b852df75bfabcc2b57539e84309cd57f9e693a2bb6b25a50e4a6101ccf32c49
+errored_verifier: ../../../contracts/solc/v0.8.16/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.16/ErroredVerifier/ErroredVerifier.bin 510d18a58bfda646be35e46491baf73041eb333a349615465b20e2b5b41c5f73
+exposed_verifier: ../../../contracts/solc/v0.8.16/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.16/ExposedVerifier/ExposedVerifier.bin 6932cea8f2738e874d3ec9e1a4231d2421704030c071d9e15dd2f7f08482c246
+fee_manager: ../../../contracts/solc/v0.8.16/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.16/FeeManager/FeeManager.bin 1b852df75bfabcc2b57539e84309cd57f9e693a2bb6b25a50e4a6101ccf32c49
llo_feeds: ../../../contracts/solc/v0.8.16/FeeManager.abi ../../../contracts/solc/v0.8.16/FeeManager.bin cb71e018f67e49d7bc0e194c822204dfd59f79ff42e4fc8fd8ab63f3acd71361
llo_feeds_test: ../../../contracts/solc/v0.8.16/ExposedVerifier.abi ../../../contracts/solc/v0.8.16/ExposedVerifier.bin 6932cea8f2738e874d3ec9e1a4231d2421704030c071d9e15dd2f7f08482c246
-reward_manager: ../../../contracts/solc/v0.8.16/RewardManager.abi ../../../contracts/solc/v0.8.16/RewardManager.bin db73e9062b17a1d5aa14c06881fe2be49bd95b00b7f1a8943910c5e4ded5b221
-verifier: ../../../contracts/solc/v0.8.16/Verifier.abi ../../../contracts/solc/v0.8.16/Verifier.bin df12786bbeccf3a8f3389479cf93c055b4efd5904b9f99a4835f81af43fe62bf
-verifier_proxy: ../../../contracts/solc/v0.8.16/VerifierProxy.abi ../../../contracts/solc/v0.8.16/VerifierProxy.bin 6393443d0a323f2dbe9687dc30fd77f8dfa918944b61c651759746ff2d76e4e5
+reward_manager: ../../../contracts/solc/v0.8.16/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.16/RewardManager/RewardManager.bin db73e9062b17a1d5aa14c06881fe2be49bd95b00b7f1a8943910c5e4ded5b221
+verifier: ../../../contracts/solc/v0.8.16/Verifier/Verifier.abi ../../../contracts/solc/v0.8.16/Verifier/Verifier.bin df12786bbeccf3a8f3389479cf93c055b4efd5904b9f99a4835f81af43fe62bf
+verifier_proxy: ../../../contracts/solc/v0.8.16/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.16/VerifierProxy/VerifierProxy.bin 6393443d0a323f2dbe9687dc30fd77f8dfa918944b61c651759746ff2d76e4e5
werc20_mock: ../../../contracts/solc/v0.8.19/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock.bin ff2ca3928b2aa9c412c892cb8226c4d754c73eeb291bb7481c32c48791b2aa94
diff --git a/core/gethwrappers/llo-feeds/go_generate.go b/core/gethwrappers/llo-feeds/go_generate.go
index 8d9e3be049..5b2088f43a 100644
--- a/core/gethwrappers/llo-feeds/go_generate.go
+++ b/core/gethwrappers/llo-feeds/go_generate.go
@@ -3,9 +3,9 @@
package gethwrappers
// Chainlink LLO
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/Verifier.abi ../../../contracts/solc/v0.8.16/Verifier.bin Verifier verifier
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/VerifierProxy.abi ../../../contracts/solc/v0.8.16/VerifierProxy.bin VerifierProxy verifier_proxy
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/ErroredVerifier.abi ../../../contracts/solc/v0.8.16/ErroredVerifier.bin ErroredVerifier errored_verifier
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/ExposedVerifier.abi ../../../contracts/solc/v0.8.16/ExposedVerifier.bin ExposedVerifier exposed_verifier
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/RewardManager.abi ../../../contracts/solc/v0.8.16/RewardManager.bin RewardManager reward_manager
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/FeeManager.abi ../../../contracts/solc/v0.8.16/FeeManager.bin FeeManager fee_manager
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/Verifier/Verifier.abi ../../../contracts/solc/v0.8.16/Verifier/Verifier.bin Verifier verifier
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.16/VerifierProxy/VerifierProxy.bin VerifierProxy verifier_proxy
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.16/ErroredVerifier/ErroredVerifier.bin ErroredVerifier errored_verifier
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.16/ExposedVerifier/ExposedVerifier.bin ExposedVerifier exposed_verifier
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.16/RewardManager/RewardManager.bin RewardManager reward_manager
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.16/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.16/FeeManager/FeeManager.bin FeeManager fee_manager
diff --git a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 7ac7e77a4b..af907ce85e 100644
--- a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -1,5 +1,5 @@
GETH_VERSION: 1.12.0
-burn_mint_erc677: ../../../contracts/solc/v0.8.19/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677.bin 405c9016171e614b17e10588653ef8d33dcea21dd569c3fddc596a46fcff68a3
-erc20: ../../../contracts/solc/v0.8.19/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20.bin 5b1a93d9b24f250e49a730c96335a8113c3f7010365cba578f313b483001d4fc
-link_token: ../../../contracts/solc/v0.8.19/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken.bin c0ef9b507103aae541ebc31d87d051c2764ba9d843076b30ec505d37cdfffaba
-werc20_mock: ../../../contracts/solc/v0.8.19/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock.bin ff2ca3928b2aa9c412c892cb8226c4d754c73eeb291bb7481c32c48791b2aa94
+burn_mint_erc677: ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin 405c9016171e614b17e10588653ef8d33dcea21dd569c3fddc596a46fcff68a3
+erc20: ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin 5b1a93d9b24f250e49a730c96335a8113c3f7010365cba578f313b483001d4fc
+link_token: ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin c0ef9b507103aae541ebc31d87d051c2764ba9d843076b30ec505d37cdfffaba
+werc20_mock: ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.bin ff2ca3928b2aa9c412c892cb8226c4d754c73eeb291bb7481c32c48791b2aa94
diff --git a/core/gethwrappers/shared/go_generate.go b/core/gethwrappers/shared/go_generate.go
index 85a01670c9..6f3bead7d6 100644
--- a/core/gethwrappers/shared/go_generate.go
+++ b/core/gethwrappers/shared/go_generate.go
@@ -2,7 +2,7 @@
// golang packages, using abigen.
package gethwrappers
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677.bin BurnMintERC677 burn_mint_erc677
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken.bin LinkToken link_token
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20.bin ERC20 erc20
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock.bin WERC20Mock werc20_mock
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin BurnMintERC677 burn_mint_erc677
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin LinkToken link_token
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin ERC20 erc20
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.bin WERC20Mock werc20_mock
diff --git a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 8ea0492fa4..a6d32bf0a8 100644
--- a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -1,9 +1,9 @@
GETH_VERSION: 1.12.0
-entry_point: ../../../contracts/solc/v0.8.15/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint.bin 2cb4bb2ba3efa8df3dfb0a57eb3727d17b68fe202682024fa7cfb4faf026833e
+entry_point: ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.bin 2cb4bb2ba3efa8df3dfb0a57eb3727d17b68fe202682024fa7cfb4faf026833e
greeter: ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c
-greeter_wrapper: ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c
-paymaster_wrapper: ../../../contracts/solc/v0.8.15/Paymaster.abi ../../../contracts/solc/v0.8.15/Paymaster.bin 189ef817a5b7a6ff53ddf35b1988465b8aec479c47b77236fe20bf7e67d48100
+greeter_wrapper: ../../../contracts/solc/v0.8.15/Greeter/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c
+paymaster_wrapper: ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.bin 189ef817a5b7a6ff53ddf35b1988465b8aec479c47b77236fe20bf7e67d48100
sca: ../../../contracts/solc/v0.8.15/SCA.abi ../../../contracts/solc/v0.8.15/SCA.bin ae0f860cdac87d4ac505edbd228bd3ea1108550453aba67aebcb61f09cf70d0b
-sca_wrapper: ../../../contracts/solc/v0.8.15/SCA.abi ../../../contracts/solc/v0.8.15/SCA.bin 2a8100fbdb41e6ce917ed333a624eaa4a8984b07e2d8d8ca6bba9bc9f74b05d7
-smart_contract_account_factory: ../../../contracts/solc/v0.8.15/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.15/SmartContractAccountFactory.bin a44d6fa2dbf9cb3441d6d637d89e1cd656f28b6bf4146f58d508067474bf845b
-smart_contract_account_helper: ../../../contracts/solc/v0.8.15/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.15/SmartContractAccountHelper.bin 22f960a74bd1581a12aa4f8f438a3f265f32f43682f5c1897ca50707b9982d56
+sca_wrapper: ../../../contracts/solc/v0.8.15/SCA/SCA.abi ../../../contracts/solc/v0.8.15/SCA/SCA.bin 2a8100fbdb41e6ce917ed333a624eaa4a8984b07e2d8d8ca6bba9bc9f74b05d7
+smart_contract_account_factory: ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.bin a44d6fa2dbf9cb3441d6d637d89e1cd656f28b6bf4146f58d508067474bf845b
+smart_contract_account_helper: ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.bin 22f960a74bd1581a12aa4f8f438a3f265f32f43682f5c1897ca50707b9982d56
diff --git a/core/gethwrappers/transmission/go_generate.go b/core/gethwrappers/transmission/go_generate.go
index 52182a1150..54c6ecf94e 100644
--- a/core/gethwrappers/transmission/go_generate.go
+++ b/core/gethwrappers/transmission/go_generate.go
@@ -3,9 +3,9 @@
package gethwrappers
// Transmission
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin Greeter greeter_wrapper
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.15/SmartContractAccountFactory.bin SmartContractAccountFactory smart_contract_account_factory
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint.bin EntryPoint entry_point
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.15/SmartContractAccountHelper.bin SmartContractAccountHelper smart_contract_account_helper
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SCA.abi ../../../contracts/solc/v0.8.15/SCA.bin SCA sca_wrapper
-//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/Paymaster.abi ../../../contracts/solc/v0.8.15/Paymaster.bin Paymaster paymaster_wrapper
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/Greeter/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter/Greeter.bin Greeter greeter_wrapper
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.bin SmartContractAccountFactory smart_contract_account_factory
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.bin EntryPoint entry_point
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.bin SmartContractAccountHelper smart_contract_account_helper
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SCA/SCA.abi ../../../contracts/solc/v0.8.15/SCA/SCA.bin SCA sca_wrapper
+//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.bin Paymaster paymaster_wrapper
From 41eac0a47137b65a70caa824cdb7f2c3b7c749c6 Mon Sep 17 00:00:00 2001
From: Francisco de Borja Aranda Castillejo
Date: Fri, 3 Nov 2023 16:31:51 +0100
Subject: [PATCH 071/327] DEVEX-1046: add functionalities to LinkMon (#11097)
* DEVEX-1046: add functionalities to LinkMon
* add timestamp checks
* adding suggestions and remove duplicated checks
* add changes and tests
* polishing last details
* add custom errors
* rebase develop
* rebase develop
---
.../upkeeps/LinkAvailableBalanceMonitor.sol | 311 ++++++++--------
.../LinkAvailableBalanceMonitor.test.ts | 352 +++++++++---------
2 files changed, 339 insertions(+), 324 deletions(-)
diff --git a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
index e2d42bc066..9b9dc2d6b7 100644
--- a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
+++ b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.6;
+pragma solidity 0.8.19;
import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
-import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol";
import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol";
@@ -35,94 +34,87 @@ interface ILinkAvailable {
/// we could save a fair amount of gas and re-write this upkeep for use with Automation v2.0+,
/// which has significantly different trust assumptions
contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationCompatibleInterface {
- using EnumerableMap for EnumerableMap.AddressToUintMap;
-
+ event BalanceUpdated(address indexed addr, uint256 oldBalance, uint256 newBalance);
event FundsWithdrawn(uint256 amountWithdrawn, address payee);
- event TopUpSucceeded(address indexed topUpAddress);
+ event UpkeepIntervalSet(uint256 oldUpkeepInterval, uint256 newUpkeepInterval);
+ event MaxCheckSet(uint256 oldMaxCheck, uint256 newMaxCheck);
+ event MaxPerformSet(uint256 oldMaxPerform, uint256 newMaxPerform);
+ event MinWaitPeriodSet(uint256 s_minWaitPeriodSeconds, uint256 minWaitPeriodSeconds);
event TopUpBlocked(address indexed topUpAddress);
+ event TopUpFailed(address indexed recipient);
+ event TopUpSucceeded(address indexed topUpAddress);
+ event TopUpUpdated(address indexed addr, uint256 oldTopUpAmount, uint256 newTopUpAmount);
event WatchlistUpdated();
- event MaxPerformUpdated(uint256 oldMaxPerform, uint256 newMaxPerform);
- event MaxCheckUpdated(uint256 oldMaxCheck, uint256 newMaxCheck);
+ error InvalidAddress(address target);
+ error InvalidMaxCheck(uint16 maxCheck);
+ error InvalixMaxPerform(uint16 maxPerform);
+ error InvalidMinBalance(uint96 minBalance);
+ error InvalidTopUpAmount(uint96 topUpAmount);
+ error InvalidUpkeepInterval(uint8 upkeepInterval);
+ error InvalidLinkTokenAddress(address lt);
error InvalidWatchList();
error DuplicateAddress(address duplicate);
+ struct MonitoredAddress {
+ uint96 minBalance;
+ uint96 topUpAmount;
+ uint56 lastTopUpTimestamp;
+ bool isActive;
+ }
+
IERC20 private immutable LINK_TOKEN;
- EnumerableMap.AddressToUintMap private s_watchList;
- uint256 private s_topUpAmount;
- uint32 private s_minWaitPeriodSeconds;
+ uint256 private s_minWaitPeriodSeconds;
uint16 private s_maxPerform;
uint16 private s_maxCheck;
+ uint8 private s_upkeepInterval;
+ address[] private s_watchList;
+ mapping(address targetAddress => MonitoredAddress targetProperties) internal s_targets;
/// @param linkTokenAddress the LINK token address
- /// @param topUpAmount the amount of LINK to top up an aggregator with at once
constructor(
address linkTokenAddress,
- uint256 topUpAmount,
+ uint256 minWaitPeriodSeconds,
uint16 maxPerform,
- uint16 maxCheck
+ uint16 maxCheck,
+ uint8 upkeepInterval
) ConfirmedOwner(msg.sender) {
- require(linkTokenAddress != address(0), "LinkAvailableBalanceMonitor: invalid linkTokenAddress");
- require(topUpAmount > 0, "LinkAvailableBalanceMonitor: invalid topUpAmount");
+ if (linkTokenAddress == address(0)) revert InvalidLinkTokenAddress(linkTokenAddress);
LINK_TOKEN = IERC20(linkTokenAddress);
- s_topUpAmount = topUpAmount;
- s_maxPerform = maxPerform;
- s_maxCheck = maxCheck;
+ setMinWaitPeriodSeconds(minWaitPeriodSeconds);
+ setMaxPerform(maxPerform);
+ setMaxCheck(maxCheck);
+ setUpkeepInterval(upkeepInterval);
}
/// @notice Sets the list of subscriptions to watch and their funding parameters
/// @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy)
/// @param minBalances the list of corresponding minBalance for the target address
- function setWatchList(address[] calldata addresses, uint256[] calldata minBalances) external onlyOwner {
- if (addresses.length != minBalances.length) {
- revert InvalidWatchList();
- }
- // first, remove all existing addresses from list
- for (uint256 idx = s_watchList.length(); idx > 0; idx--) {
- (address target, ) = s_watchList.at(idx - 1);
- require(s_watchList.remove(target), "LinkAvailableBalanceMonitor: unable to setWatchlist");
- }
- // then set new addresses
- for (uint256 idx = 0; idx < addresses.length; idx++) {
- if (s_watchList.contains(addresses[idx])) {
- revert DuplicateAddress(addresses[idx]);
- }
- if (addresses[idx] == address(0)) {
- revert InvalidWatchList();
- }
- s_watchList.set(addresses[idx], minBalances[idx]);
- }
- emit WatchlistUpdated();
- }
-
- /// @notice Adds addresses to the watchlist without overwriting existing members
- /// @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy)
- /// @param minBalances the list of corresponding minBalance for the target address
- function addToWatchList(address[] calldata addresses, uint256[] calldata minBalances) external onlyOwner {
- if (addresses.length != minBalances.length) {
+ /// @param topUpAmounts the list of corresponding minTopUp for the target address
+ function setWatchList(
+ address[] calldata addresses,
+ uint96[] calldata minBalances,
+ uint96[] calldata topUpAmounts
+ ) external onlyOwner {
+ if (addresses.length != minBalances.length || addresses.length != topUpAmounts.length) {
revert InvalidWatchList();
}
- for (uint256 idx = 0; idx < addresses.length; idx++) {
- if (s_watchList.contains(addresses[idx])) {
- revert DuplicateAddress(addresses[idx]);
- }
- if (addresses[idx] == address(0)) {
- revert InvalidWatchList();
- }
- s_watchList.set(addresses[idx], minBalances[idx]);
+ for (uint256 idx = 0; idx < s_watchList.length; idx++) {
+ delete s_targets[s_watchList[idx]];
}
- emit WatchlistUpdated();
- }
-
- /// @notice Removes addresses from the watchlist
- /// @param addresses the list of target addresses to remove from the watchlist
- function removeFromWatchlist(address[] calldata addresses) external onlyOwner {
for (uint256 idx = 0; idx < addresses.length; idx++) {
- if (!s_watchList.contains(addresses[idx])) {
- revert InvalidWatchList();
- }
- s_watchList.remove(addresses[idx]);
+ address targetAddress = addresses[idx];
+ if (s_targets[targetAddress].isActive) revert DuplicateAddress(addresses[idx]);
+ if (addresses[idx] == address(0)) revert InvalidWatchList();
+ if (topUpAmounts[idx] == 0) revert InvalidWatchList();
+ s_targets[targetAddress] = MonitoredAddress({
+ isActive: true,
+ minBalance: minBalances[idx],
+ topUpAmount: topUpAmounts[idx],
+ lastTopUpTimestamp: 0
+ });
}
+ s_watchList = addresses;
emit WatchlistUpdated();
}
@@ -135,20 +127,21 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationComp
function sampleUnderfundedAddresses() public view returns (address[] memory) {
uint16 maxPerform = s_maxPerform;
uint16 maxCheck = s_maxCheck;
- uint256 numTargets = s_watchList.length();
- uint256 idx = uint256(blockhash(block.number - 1)) % numTargets; // start at random index, to distribute load
+ uint256 numTargets = s_watchList.length;
+ uint256 idx = uint256(blockhash(block.number - (block.number % s_upkeepInterval) - 1)) % numTargets;
uint256 numToCheck = numTargets < maxCheck ? numTargets : maxCheck;
uint256 numFound = 0;
address[] memory targetsToFund = new address[](maxPerform);
+ MonitoredAddress memory target;
for (
uint256 numChecked = 0;
numChecked < numToCheck;
(idx, numChecked) = ((idx + 1) % numTargets, numChecked + 1)
) {
- (address target, uint256 minBalance) = s_watchList.at(idx);
- (bool needsFunding, ) = _needsFunding(target, minBalance);
- if (needsFunding) {
- targetsToFund[numFound] = target;
+ address targetAddress = s_watchList[idx];
+ target = s_targets[targetAddress];
+ if (_needsFunding(targetAddress, target.minBalance)) {
+ targetsToFund[numFound] = targetAddress;
numFound++;
if (numFound == maxPerform) {
break; // max number of addresses in batch reached
@@ -163,29 +156,59 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationComp
return targetsToFund;
}
- /// @notice Send funds to the targets provided.
- /// @param targetAddresses the list of targets to fund
function topUp(address[] memory targetAddresses) public whenNotPaused {
- uint256 topUpAmount = s_topUpAmount;
- uint256 stopIdx = targetAddresses.length;
- uint256 numCanFund = LINK_TOKEN.balanceOf(address(this)) / topUpAmount;
- stopIdx = numCanFund < stopIdx ? numCanFund : stopIdx;
- for (uint256 idx = 0; idx < stopIdx; idx++) {
- (bool exists, uint256 minBalance) = s_watchList.tryGet(targetAddresses[idx]);
- if (!exists) {
- emit TopUpBlocked(targetAddresses[idx]);
- continue;
- }
- (bool needsFunding, address target) = _needsFunding(targetAddresses[idx], minBalance);
- if (!needsFunding) {
- emit TopUpBlocked(targetAddresses[idx]);
- continue;
+ MonitoredAddress memory target;
+ uint256 localBalance = LINK_TOKEN.balanceOf(address(this));
+ for (uint256 idx = 0; idx < targetAddresses.length; idx++) {
+ address targetAddress = targetAddresses[idx];
+ target = s_targets[targetAddress];
+ if (localBalance >= target.topUpAmount && _needsFunding(targetAddress, target.minBalance)) {
+ bool success = LINK_TOKEN.transfer(targetAddress, target.topUpAmount);
+ if (success) {
+ localBalance -= target.topUpAmount;
+ target.lastTopUpTimestamp = uint56(block.timestamp);
+ emit TopUpSucceeded(targetAddress);
+ } else {
+ emit TopUpFailed(targetAddress);
+ }
+ } else {
+ emit TopUpBlocked(targetAddress);
}
- LINK_TOKEN.transfer(target, topUpAmount);
- emit TopUpSucceeded(targetAddresses[idx]);
}
}
+ /// @notice checks the target (could be direct target or IAggregatorProxy), and determines
+ /// if it is elligible for funding
+ /// @param targetAddress the target to check
+ /// @param minBalance minimum balance required for the target
+ /// @return bool whether the target needs funding or not
+ function _needsFunding(address targetAddress, uint256 minBalance) private view returns (bool) {
+ // Explicitly check if the targetAddress is the zero address
+ // or if it's not a contract. In both cases return with false,
+ // to prevent target.linkAvailableForPayment from running,
+ // which would revert the operation.
+ if (targetAddress == address(0) || targetAddress.code.length == 0) {
+ return false;
+ }
+ MonitoredAddress memory addressToCheck = s_targets[targetAddress];
+ ILinkAvailable target;
+ IAggregatorProxy proxy = IAggregatorProxy(targetAddress);
+ try proxy.aggregator() returns (address aggregatorAddress) {
+ if (aggregatorAddress == address(0)) return false;
+ target = ILinkAvailable(aggregatorAddress);
+ } catch {
+ target = ILinkAvailable(targetAddress);
+ }
+ try target.linkAvailableForPayment() returns (int256 balance) {
+ if (
+ balance < int256(minBalance) && addressToCheck.lastTopUpTimestamp + s_minWaitPeriodSeconds <= block.timestamp
+ ) {
+ return true;
+ }
+ } catch {}
+ return false;
+ }
+
/// @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload.
/// @return upkeepNeeded signals if upkeep is needed
/// @return performData is an abi encoded list of subscription ids that need funds
@@ -193,12 +216,6 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationComp
bytes calldata
) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) {
address[] memory needsFunding = sampleUnderfundedAddresses();
- uint256 numCanFund = LINK_TOKEN.balanceOf(address(this)) / s_topUpAmount;
- if (numCanFund < needsFunding.length) {
- assembly {
- mstore(needsFunding, numCanFund) // resize
- }
- }
upkeepNeeded = needsFunding.length > 0;
performData = abi.encode(needsFunding);
return (upkeepNeeded, performData);
@@ -215,38 +232,54 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationComp
/// @param amount the amount of the LINK to withdraw
/// @param payee the address to pay
function withdraw(uint256 amount, address payable payee) external onlyOwner {
- require(payee != address(0), "LinkAvailableBalanceMonitor: invalid payee address");
+ if (payee == address(0)) revert InvalidAddress(payee);
LINK_TOKEN.transfer(payee, amount);
emit FundsWithdrawn(amount, payee);
}
- /// @notice Sets the top up amount
- function setTopUpAmount(uint256 topUpAmount) external onlyOwner returns (uint256) {
- require(topUpAmount > 0, "LinkAvailableBalanceMonitor: invalid linkTokenAddress");
- return s_topUpAmount = topUpAmount;
+ /// @notice Sets the minimum balance for the given target address
+ function setMinBalance(address target, uint96 minBalance) external onlyOwner {
+ if (target == address(0)) revert InvalidAddress(target);
+ if (minBalance == 0) revert InvalidMinBalance(minBalance);
+ if (!s_targets[target].isActive) revert InvalidWatchList();
+ uint256 oldBalance = s_targets[target].minBalance;
+ s_targets[target].minBalance = minBalance;
+ emit BalanceUpdated(target, oldBalance, minBalance);
}
/// @notice Sets the minimum balance for the given target address
- function setMinBalance(address target, uint256 minBalance) external onlyOwner returns (uint256) {
- require(minBalance > 0, "LinkAvailableBalanceMonitor: invalid minBalance");
- (bool exists, uint256 prevMinBalance) = s_watchList.tryGet(target);
- if (!exists) {
- revert InvalidWatchList();
- }
- s_watchList.set(target, minBalance);
- return prevMinBalance;
+ function setTopUpAmount(address target, uint96 topUpAmount) external onlyOwner {
+ if (target == address(0)) revert InvalidAddress(target);
+ if (topUpAmount == 0) revert InvalidTopUpAmount(topUpAmount);
+ if (!s_targets[target].isActive) revert InvalidWatchList();
+ uint256 oldTopUpAmount = s_targets[target].topUpAmount;
+ s_targets[target].topUpAmount = topUpAmount;
+ emit BalanceUpdated(target, oldTopUpAmount, topUpAmount);
}
/// @notice Update s_maxPerform
- function setMaxPerform(uint16 maxPerform) external onlyOwner {
- emit MaxPerformUpdated(s_maxPerform, maxPerform);
+ function setMaxPerform(uint16 maxPerform) public onlyOwner {
s_maxPerform = maxPerform;
+ emit MaxPerformSet(s_maxPerform, maxPerform);
}
/// @notice Update s_maxCheck
- function setMaxCheck(uint16 maxCheck) external onlyOwner {
- emit MaxCheckUpdated(s_maxCheck, maxCheck);
+ function setMaxCheck(uint16 maxCheck) public onlyOwner {
s_maxCheck = maxCheck;
+ emit MaxCheckSet(s_maxCheck, maxCheck);
+ }
+
+ /// @notice Sets the minimum wait period (in seconds) for addresses between funding
+ function setMinWaitPeriodSeconds(uint256 minWaitPeriodSeconds) public onlyOwner {
+ s_minWaitPeriodSeconds = minWaitPeriodSeconds;
+ emit MinWaitPeriodSet(s_minWaitPeriodSeconds, minWaitPeriodSeconds);
+ }
+
+ /// @notice Update s_upkeepInterval
+ function setUpkeepInterval(uint8 upkeepInterval) public onlyOwner {
+ if (upkeepInterval > 255) revert InvalidUpkeepInterval(upkeepInterval);
+ s_upkeepInterval = upkeepInterval;
+ emit UpkeepIntervalSet(s_upkeepInterval, upkeepInterval);
}
/// @notice Gets maxPerform
@@ -259,31 +292,27 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationComp
return s_maxCheck;
}
- /// @notice Gets the list of subscription ids being watched
- function getWatchList() external view returns (address[] memory, uint256[] memory) {
- uint256 len = s_watchList.length();
- address[] memory targets = new address[](len);
- uint256[] memory minBalances = new uint256[](len);
-
- for (uint256 idx = 0; idx < len; idx++) {
- (targets[idx], minBalances[idx]) = s_watchList.at(idx);
- }
+ /// @notice Gets the minimum wait period
+ function getMinWaitPeriodSeconds() external view returns (uint256) {
+ return s_minWaitPeriodSeconds;
+ }
- return (targets, minBalances);
+ /// @notice Gets upkeepInterval
+ function getUpkeepInterval() external view returns (uint8) {
+ return s_upkeepInterval;
}
- /// @notice Gets the configured top up amount
- function getTopUpAmount() external view returns (uint256) {
- return s_topUpAmount;
+ /// @notice Gets the list of subscription ids being watched
+ function getWatchList() external view returns (address[] memory) {
+ return s_watchList;
}
- /// @notice Gets the configured minimum balance for the given target
- function getMinBalance(address target) external view returns (uint256) {
- (bool exists, uint256 minBalance) = s_watchList.tryGet(target);
- if (!exists) {
- revert InvalidWatchList();
- }
- return minBalance;
+ /// @notice Gets configuration information for an address on the watchlist
+ function getAccountInfo(
+ address targetAddress
+ ) external view returns (bool isActive, uint256 minBalance, uint256 topUpAmount) {
+ MonitoredAddress memory target = s_targets[targetAddress];
+ return (target.isActive, target.minBalance, target.topUpAmount);
}
/// @notice Pause the contract, which prevents executing performUpkeep
@@ -295,26 +324,4 @@ contract LinkAvailableBalanceMonitor is ConfirmedOwner, Pausable, AutomationComp
function unpause() external onlyOwner {
_unpause();
}
-
- /// @notice checks the target (could be direct target or IAggregatorProxy), and determines
- /// if it is elligible for funding
- /// @param targetAddress the target to check
- /// @param minBalance minimum balance required for the target
- /// @return bool whether the target needs funding or not
- /// @return address the address of the contract needing funding
- function _needsFunding(address targetAddress, uint256 minBalance) private view returns (bool, address) {
- ILinkAvailable target;
- IAggregatorProxy proxy = IAggregatorProxy(targetAddress);
- try proxy.aggregator() returns (address aggregatorAddress) {
- target = ILinkAvailable(aggregatorAddress);
- } catch {
- target = ILinkAvailable(targetAddress);
- }
- try target.linkAvailableForPayment() returns (int256 balance) {
- if (balance < 0 || uint256(balance) < minBalance) {
- return (true, address(target));
- }
- } catch {}
- return (false, address(0));
- }
}
diff --git a/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts b/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts
index af0063fb50..76a3dcfff1 100644
--- a/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts
+++ b/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts
@@ -34,6 +34,7 @@ const PAUSED_ERR = 'Pausable: paused'
const zeroLINK = ethers.utils.parseEther('0')
const oneLINK = ethers.utils.parseEther('1')
const twoLINK = ethers.utils.parseEther('2')
+const fourLINK = ethers.utils.parseEther('4')
const fiveLINK = ethers.utils.parseEther('5')
const tenLINK = ethers.utils.parseEther('10')
const oneHundredLINK = ethers.utils.parseEther('100')
@@ -59,6 +60,7 @@ let directTarget2: MockContract
let watchListAddresses: string[]
let watchListMinBalances: BigNumber[]
+let watchListTopUpAmounts: BigNumber[]
async function assertContractLinkBalances(
balance1: BigNumber,
@@ -120,6 +122,7 @@ const setup = async () => {
directTarget2.address,
]
watchListMinBalances = [oneLINK, oneLINK, oneLINK, twoLINK, twoLINK]
+ watchListTopUpAmounts = [twoLINK, twoLINK, twoLINK, twoLINK, twoLINK]
await proxy1.mock.aggregator.returns(aggregator1.address)
await proxy2.mock.aggregator.returns(aggregator2.address)
@@ -144,9 +147,17 @@ const setup = async () => {
// New parameters needed by the constructor
const maxPerform = 5
const maxCheck = 20
+ const minWaitPeriodSeconds = 0
+ const upkeepInterval = 10
lt = (await ltFactory.deploy()) as LinkToken
- labm = await labmFactory.deploy(lt.address, twoLINK, maxPerform, maxCheck)
+ labm = await labmFactory.deploy(
+ lt.address,
+ minWaitPeriodSeconds,
+ maxPerform,
+ maxCheck,
+ upkeepInterval,
+ )
await labm.deployed()
for (let i = 1; i <= 4; i++) {
@@ -156,7 +167,11 @@ const setup = async () => {
const setTx = await labm
.connect(owner)
- .setWatchList(watchListAddresses, watchListMinBalances)
+ .setWatchList(
+ watchListAddresses,
+ watchListMinBalances,
+ watchListTopUpAmounts,
+ )
await setTx.wait()
}
@@ -174,19 +189,27 @@ describe('LinkAvailableBalanceMonitor', () => {
describe('setTopUpAmount()', () => {
it('configures the top-up amount', async () => {
- await labm.connect(owner).setTopUpAmount(100)
- assert.equal((await labm.getTopUpAmount()).toNumber(), 100)
+ await labm
+ .connect(owner)
+ .setTopUpAmount(directTarget1.address, BigNumber.from(100))
+ const report = await labm.getAccountInfo(directTarget1.address)
+ assert.equal(report.topUpAmount.toString(), '100')
})
it('configuresis only callable by the owner', async () => {
- await expect(labm.connect(stranger).setTopUpAmount(100)).to.be.reverted
+ await expect(
+ labm.connect(stranger).setTopUpAmount(directTarget1.address, 100),
+ ).to.be.reverted
})
})
describe('setMinBalance()', () => {
it('configures the min balance', async () => {
- await labm.connect(owner).setMinBalance(proxy1.address, 100)
- assert.equal((await labm.getMinBalance(proxy1.address)).toNumber(), 100)
+ await labm
+ .connect(owner)
+ .setMinBalance(proxy1.address, BigNumber.from(100))
+ const report = await labm.getAccountInfo(proxy1.address)
+ assert.equal(report.minBalance.toString(), '100')
})
it('reverts if address is not in the watchlist', async () => {
@@ -266,66 +289,29 @@ describe('LinkAvailableBalanceMonitor', () => {
beforeEach(async () => {
// reset watchlist to empty before running these tests
- await labm.connect(owner).setWatchList([], [])
- let watchList = await labm.getWatchList()
- assert.deepEqual(watchList, [[], []])
+ await labm.connect(owner).setWatchList([], [], [])
+ const watchList = await labm.getWatchList()
+ assert.deepEqual(watchList, [])
})
it('Should allow owner to adjust the watchlist', async () => {
// add first watchlist
let tx = await labm
.connect(owner)
- .setWatchList([watchAddress1], [oneLINK])
+ .setWatchList([watchAddress1], [oneLINK], [oneLINK])
let watchList = await labm.getWatchList()
- assert.deepEqual(watchList[0], [watchAddress1])
- assert.deepEqual(
- watchList[1].map((x) => x.toString()),
- [oneLINK].map((x) => x.toString()),
- )
+ assert.deepEqual(watchList[0], watchAddress1)
// add more to watchlist
tx = await labm
.connect(owner)
.setWatchList(
[watchAddress1, watchAddress2, watchAddress3],
[oneLINK, oneLINK, oneLINK],
+ [oneLINK, oneLINK, oneLINK],
)
await tx.wait()
watchList = await labm.getWatchList()
- assert.deepEqual(watchList[0], [
- watchAddress1,
- watchAddress2,
- watchAddress3,
- ])
- assert.deepEqual(
- watchList[1].map((x) => x.toString()),
- [oneLINK, oneLINK, oneLINK].map((x) => x.toString()),
- )
- // remove some from watchlist
- tx = await labm
- .connect(owner)
- .removeFromWatchlist([watchAddress3, watchAddress1])
- await tx.wait()
- watchList = await labm.getWatchList()
- assert.deepEqual(watchList[0], [watchAddress2])
- assert.deepEqual(
- watchList[1].map((x) => x.toString()),
- [oneLINK].map((x) => x.toString()),
- )
- // add some to watchlist
- tx = await labm
- .connect(owner)
- .addToWatchList([watchAddress1, watchAddress3], [twoLINK, twoLINK])
- await tx.wait()
- watchList = await labm.getWatchList()
- assert.deepEqual(watchList[0], [
- watchAddress2,
- watchAddress1,
- watchAddress3,
- ])
- assert.deepEqual(
- watchList[1].map((x) => x.toString()),
- [oneLINK, twoLINK, twoLINK].map((x) => x.toString()),
- )
+ assert.deepEqual(watchList, [watchAddress1, watchAddress2, watchAddress3])
})
it('Should not allow different length arrays in the watchlist', async () => {
@@ -335,6 +321,7 @@ describe('LinkAvailableBalanceMonitor', () => {
.setWatchList(
[watchAddress1, watchAddress2, watchAddress1],
[oneLINK, oneLINK],
+ [oneLINK, oneLINK],
)
await expect(tx).to.be.revertedWith(errMsg)
})
@@ -346,12 +333,6 @@ describe('LinkAvailableBalanceMonitor', () => {
.setWatchList(
[watchAddress1, watchAddress2, watchAddress1],
[oneLINK, oneLINK, oneLINK],
- )
- await expect(tx).to.be.revertedWith(errMsg)
- tx = labm
- .connect(owner)
- .addToWatchList(
- [watchAddress1, watchAddress2, watchAddress1],
[oneLINK, oneLINK, oneLINK],
)
await expect(tx).to.be.revertedWith(errMsg)
@@ -360,14 +341,8 @@ describe('LinkAvailableBalanceMonitor', () => {
it('Should not allow strangers to set the watchlist', async () => {
const setTxStranger = labm
.connect(stranger)
- .setWatchList([watchAddress1], [oneLINK])
+ .setWatchList([watchAddress1], [oneLINK], [oneLINK])
await expect(setTxStranger).to.be.revertedWith(OWNABLE_ERR)
- const addTxStranger = labm
- .connect(stranger)
- .addToWatchList([watchAddress1], [oneLINK])
- await expect(addTxStranger).to.be.revertedWith(OWNABLE_ERR)
- const removeTxStranger = labm.connect(stranger).removeFromWatchlist([])
- await expect(removeTxStranger).to.be.revertedWith(OWNABLE_ERR)
})
it('Should revert if any of the addresses are empty', async () => {
@@ -376,12 +351,6 @@ describe('LinkAvailableBalanceMonitor', () => {
.setWatchList(
[watchAddress1, ethers.constants.AddressZero],
[oneLINK, oneLINK],
- )
- await expect(tx).to.be.revertedWith(INVALID_WATCHLIST_ERR)
- tx = labm
- .connect(owner)
- .addToWatchList(
- [watchAddress1, ethers.constants.AddressZero],
[oneLINK, oneLINK],
)
await expect(tx).to.be.revertedWith(INVALID_WATCHLIST_ERR)
@@ -390,69 +359,68 @@ describe('LinkAvailableBalanceMonitor', () => {
describe('checkUpkeep() / sampleUnderfundedAddresses() [ @skip-coverage ]', () => {
it('Should return list of address that are underfunded', async () => {
- const fundTx = await lt.connect(owner).transfer(
- labm.address,
- tenLINK, // needs 10 total
- )
+ const fundTx = await lt
+ .connect(owner)
+ .transfer(labm.address, oneHundredLINK)
await fundTx.wait()
+
+ await labm.setWatchList(
+ watchListAddresses,
+ watchListMinBalances,
+ watchListTopUpAmounts,
+ )
+
const [should, payload] = await labm.checkUpkeep('0x')
assert.isTrue(should)
let [addresses] = ethers.utils.defaultAbiCoder.decode(
['address[]'],
payload,
)
+
expect(addresses).to.deep.equalInAnyOrder(watchListAddresses)
- // checkUpkeep payload should match sampleUnderfundedAddresses()
addresses = await labm.sampleUnderfundedAddresses()
expect(addresses).to.deep.equalInAnyOrder(watchListAddresses)
})
- it('Should return some results even if contract cannot fund all eligible targets', async () => {
+ it('Should omit aggregators that have sufficient funding', async () => {
const fundTx = await lt.connect(owner).transfer(
labm.address,
- fiveLINK, // needs 2Link per contract, so can fund 2 max
+ oneHundredLINK, // enough for anything that needs funding
)
await fundTx.wait()
- const [should, payload] = await labm.checkUpkeep('0x')
- assert.isTrue(should)
- let [addresses] = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- payload,
+
+ await labm.setWatchList(
+ [aggregator2.address, directTarget1.address, directTarget2.address],
+ [oneLINK, twoLINK, twoLINK],
+ [oneLINK, oneLINK, oneLINK],
)
- assert.equal(addresses.length, 2)
- assert.notEqual(addresses[0], addresses[1])
- assert(watchListAddresses.includes(addresses[0]))
- assert(watchListAddresses.includes(addresses[1]))
- // underfunded sample should still match list
- addresses = await labm.sampleUnderfundedAddresses()
- expect(addresses).to.deep.equalInAnyOrder(watchListAddresses)
- })
- it('Should omit aggregators that have sufficient funding', async () => {
+ // all of them are underfunded, return 3
+ await aggregator2.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget1.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK)
+
let addresses = await labm.sampleUnderfundedAddresses()
- expect(addresses).to.deep.equalInAnyOrder(watchListAddresses)
- await aggregator2.mock.linkAvailableForPayment.returns(oneLINK) // aggregator2 is enough funded
- await directTarget1.mock.linkAvailableForPayment.returns(oneLINK) // directTarget1 is NOT enough funded
- await directTarget2.mock.linkAvailableForPayment.returns(twoLINK) // directTarget2 is enough funded
- addresses = await labm.sampleUnderfundedAddresses()
expect(addresses).to.deep.equalInAnyOrder([
- proxy1.address,
- proxy3.address,
+ aggregator2.address,
directTarget1.address,
+ directTarget2.address,
])
- await aggregator1.mock.linkAvailableForPayment.returns(tenLINK)
+ await aggregator2.mock.linkAvailableForPayment.returns(oneLINK) // aggregator2 is enough funded
+ await directTarget1.mock.linkAvailableForPayment.returns(oneLINK) // directTarget1 is NOT enough funded
+ await directTarget2.mock.linkAvailableForPayment.returns(oneLINK) // directTarget2 is NOT funded
addresses = await labm.sampleUnderfundedAddresses()
expect(addresses).to.deep.equalInAnyOrder([
- proxy3.address,
directTarget1.address,
+ directTarget2.address,
])
- await aggregator3.mock.linkAvailableForPayment.returns(tenLINK)
+ await directTarget1.mock.linkAvailableForPayment.returns(tenLINK)
addresses = await labm.sampleUnderfundedAddresses()
- expect(addresses).to.deep.equalInAnyOrder([directTarget1.address])
+ expect(addresses).to.deep.equalInAnyOrder([directTarget2.address])
- await directTarget1.mock.linkAvailableForPayment.returns(tenLINK)
+ await directTarget2.mock.linkAvailableForPayment.returns(tenLINK)
addresses = await labm.sampleUnderfundedAddresses()
expect(addresses).to.deep.equalInAnyOrder([])
})
@@ -471,6 +439,7 @@ describe('LinkAvailableBalanceMonitor', () => {
let MAX_CHECK: number
let proxyAddresses: string[]
let minBalances: BigNumber[]
+ let topUpAmount: BigNumber[]
let aggregators: MockContract[]
beforeEach(async () => {
@@ -478,6 +447,7 @@ describe('LinkAvailableBalanceMonitor', () => {
MAX_CHECK = await labm.getMaxCheck()
proxyAddresses = []
minBalances = []
+ topUpAmount = []
aggregators = []
const numAggregators = MAX_CHECK + 50
for (let idx = 0; idx < numAggregators; idx++) {
@@ -493,18 +463,18 @@ describe('LinkAvailableBalanceMonitor', () => {
await aggregator.mock.linkAvailableForPayment.returns(0)
proxyAddresses.push(proxy.address)
minBalances.push(oneLINK)
+ topUpAmount.push(oneLINK)
aggregators.push(aggregator)
}
- await labm.setWatchList(proxyAddresses, minBalances)
- expect(await labm.getWatchList()).to.deep.equalInAnyOrder([
- proxyAddresses,
- minBalances,
- ])
+ await labm.setWatchList(proxyAddresses, minBalances, topUpAmount)
+ let watchlist = await labm.getWatchList()
+ expect(watchlist).to.deep.equalInAnyOrder(proxyAddresses)
+ assert.equal(watchlist.length, minBalances.length)
})
it('Should not include more than MAX_PERFORM addresses', async () => {
const addresses = await labm.sampleUnderfundedAddresses()
- assert.equal(addresses.length, MAX_PERFORM)
+ expect(addresses.length).to.be.lessThanOrEqual(MAX_PERFORM)
})
it('Should sample from the list of addresses pseudorandomly', async () => {
@@ -547,7 +517,11 @@ describe('LinkAvailableBalanceMonitor', () => {
)
await labm
.connect(owner)
- .setWatchList(watchListAddresses, watchListMinBalances)
+ .setWatchList(
+ watchListAddresses,
+ watchListMinBalances,
+ watchListTopUpAmounts,
+ )
})
it('Should revert when paused', async () => {
@@ -557,32 +531,38 @@ describe('LinkAvailableBalanceMonitor', () => {
})
it('Should fund the appropriate addresses', async () => {
- await lt.connect(owner).transfer(labm.address, tenLINK)
- await assertContractLinkBalances(
- zeroLINK,
- zeroLINK,
- zeroLINK,
- zeroLINK,
- zeroLINK,
- )
+ await aggregator1.mock.linkAvailableForPayment.returns(zeroLINK)
+ await aggregator2.mock.linkAvailableForPayment.returns(zeroLINK)
+ await aggregator3.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget1.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK)
+
+ const fundTx = await lt.connect(owner).transfer(labm.address, tenLINK)
+ await fundTx.wait()
+
+ h.assertLinkTokenBalance(lt, aggregator1.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, aggregator2.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, aggregator3.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, directTarget1.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, directTarget2.address, zeroLINK)
+
const performTx = await labm
.connect(keeperRegistry)
- .performUpkeep(validPayload, { gasLimit: 2_500_000 })
+ .performUpkeep(validPayload, { gasLimit: 1_500_000 })
await performTx.wait()
- await assertContractLinkBalances(
- twoLINK,
- twoLINK,
- twoLINK,
- twoLINK,
- twoLINK,
- )
+
+ h.assertLinkTokenBalance(lt, aggregator1.address, twoLINK)
+ h.assertLinkTokenBalance(lt, aggregator2.address, twoLINK)
+ h.assertLinkTokenBalance(lt, aggregator3.address, twoLINK)
+ h.assertLinkTokenBalance(lt, directTarget1.address, twoLINK)
+ h.assertLinkTokenBalance(lt, directTarget2.address, twoLINK)
})
it('Can handle MAX_PERFORM proxies within gas limit', async () => {
- // add MAX_PERFORM number of proxies
const MAX_PERFORM = await labm.getMaxPerform()
const proxyAddresses = []
const minBalances = []
+ const topUpAmount = []
for (let idx = 0; idx < MAX_PERFORM; idx++) {
const proxy = await deployMockContract(
owner,
@@ -596,20 +576,29 @@ describe('LinkAvailableBalanceMonitor', () => {
await aggregator.mock.linkAvailableForPayment.returns(0)
proxyAddresses.push(proxy.address)
minBalances.push(oneLINK)
+ topUpAmount.push(oneLINK)
}
- await labm.setWatchList(proxyAddresses, minBalances)
- expect(await labm.getWatchList()).to.deep.equalInAnyOrder([
- proxyAddresses,
- minBalances,
- ])
+ await labm.setWatchList(proxyAddresses, minBalances, topUpAmount)
+ let watchlist = await labm.getWatchList()
+ expect(watchlist).to.deep.equalInAnyOrder(proxyAddresses)
+ assert.equal(watchlist.length, minBalances.length)
+
// add funds
- const fundsNeeded = (await labm.getTopUpAmount()).mul(MAX_PERFORM)
+ const wl = await labm.getWatchList()
+ let fundsNeeded = BigNumber.from(0)
+ for (let idx = 0; idx < wl.length; idx++) {
+ const targetInfo = await labm.getAccountInfo(wl[idx])
+ const targetTopUpAmount = targetInfo.topUpAmount
+ fundsNeeded.add(targetTopUpAmount)
+ }
await lt.connect(owner).transfer(labm.address, fundsNeeded)
+
// encode payload
const payload = ethers.utils.defaultAbiCoder.encode(
['address[]'],
[proxyAddresses],
)
+
// do the thing
await labm
.connect(keeperRegistry)
@@ -618,6 +607,11 @@ describe('LinkAvailableBalanceMonitor', () => {
})
describe('topUp()', () => {
+ it('Should revert topUp address(0)', async () => {
+ const tx = await labm.connect(owner).topUp([ethers.constants.AddressZero])
+ await expect(tx).to.emit(labm, 'TopUpBlocked')
+ })
+
context('when not paused', () => {
it('Should be callable by anyone', async () => {
const users = [owner, keeperRegistry, stranger]
@@ -654,13 +648,13 @@ describe('LinkAvailableBalanceMonitor', () => {
it('Should fund the appropriate addresses', async () => {
const tx = await labm.connect(keeperRegistry).topUp(watchListAddresses)
- await assertContractLinkBalances(
- twoLINK,
- twoLINK,
- twoLINK,
- twoLINK,
- twoLINK,
- )
+
+ await aggregator1.mock.linkAvailableForPayment.returns(twoLINK)
+ await aggregator2.mock.linkAvailableForPayment.returns(twoLINK)
+ await aggregator3.mock.linkAvailableForPayment.returns(twoLINK)
+ await directTarget1.mock.linkAvailableForPayment.returns(twoLINK)
+ await directTarget2.mock.linkAvailableForPayment.returns(twoLINK)
+
await expect(tx)
.to.emit(labm, 'TopUpSucceeded')
.withArgs(proxy1.address)
@@ -682,13 +676,12 @@ describe('LinkAvailableBalanceMonitor', () => {
await labm
.connect(keeperRegistry)
.topUp([proxy1.address, directTarget1.address])
- await assertContractLinkBalances(
- twoLINK,
- zeroLINK,
- zeroLINK,
- twoLINK,
- zeroLINK,
- )
+
+ await aggregator1.mock.linkAvailableForPayment.returns(twoLINK)
+ await aggregator2.mock.linkAvailableForPayment.returns(zeroLINK)
+ await aggregator3.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget1.mock.linkAvailableForPayment.returns(twoLINK)
+ await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK)
})
it('Should skip un-approved addresses', async () => {
@@ -697,6 +690,7 @@ describe('LinkAvailableBalanceMonitor', () => {
.setWatchList(
[proxy1.address, directTarget1.address],
[oneLINK, oneLINK],
+ [oneLINK, oneLINK],
)
const tx = await labm
.connect(keeperRegistry)
@@ -707,13 +701,13 @@ describe('LinkAvailableBalanceMonitor', () => {
directTarget1.address,
directTarget2.address,
])
- await assertContractLinkBalances(
- twoLINK,
- zeroLINK,
- zeroLINK,
- twoLINK,
- zeroLINK,
- )
+
+ h.assertLinkTokenBalance(lt, aggregator1.address, twoLINK)
+ h.assertLinkTokenBalance(lt, aggregator2.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, aggregator3.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, directTarget1.address, twoLINK)
+ h.assertLinkTokenBalance(lt, directTarget2.address, zeroLINK)
+
await expect(tx)
.to.emit(labm, 'TopUpSucceeded')
.withArgs(proxy1.address)
@@ -730,7 +724,11 @@ describe('LinkAvailableBalanceMonitor', () => {
it('Should skip an address if the proxy is invalid and it is not a direct target', async () => {
await labm
.connect(owner)
- .setWatchList([proxy1.address, proxy4.address], [oneLINK, oneLINK])
+ .setWatchList(
+ [proxy1.address, proxy4.address],
+ [oneLINK, oneLINK],
+ [oneLINK, oneLINK],
+ )
const tx = await labm
.connect(keeperRegistry)
.topUp([proxy1.address, proxy4.address])
@@ -744,7 +742,11 @@ describe('LinkAvailableBalanceMonitor', () => {
await proxy4.mock.aggregator.returns(aggregator4.address)
await labm
.connect(owner)
- .setWatchList([proxy1.address, proxy4.address], [oneLINK, oneLINK])
+ .setWatchList(
+ [proxy1.address, proxy4.address],
+ [oneLINK, oneLINK],
+ [oneLINK, oneLINK],
+ )
const tx = await labm
.connect(keeperRegistry)
.topUp([proxy1.address, proxy4.address])
@@ -759,7 +761,11 @@ describe('LinkAvailableBalanceMonitor', () => {
await aggregator4.mock.linkAvailableForPayment.returns(tenLINK)
await labm
.connect(owner)
- .setWatchList([proxy1.address, proxy4.address], [oneLINK, oneLINK])
+ .setWatchList(
+ [proxy1.address, proxy4.address],
+ [oneLINK, oneLINK],
+ [oneLINK, oneLINK],
+ )
const tx = await labm
.connect(keeperRegistry)
.topUp([proxy1.address, proxy4.address])
@@ -776,6 +782,7 @@ describe('LinkAvailableBalanceMonitor', () => {
.setWatchList(
[proxy1.address, directTarget1.address],
[oneLINK, oneLINK],
+ [oneLINK, oneLINK],
)
const tx = await labm
.connect(keeperRegistry)
@@ -790,25 +797,26 @@ describe('LinkAvailableBalanceMonitor', () => {
})
context('when partially funded', () => {
- it('Should fund as many addresses as possible', async () => {
+ it('Should fund as many addresses as possible T', async () => {
await lt.connect(owner).transfer(
labm.address,
- fiveLINK, // only enough LINK to fund 2 addresses
+ fourLINK, // only enough LINK to fund 2 addresses
)
+
+ await aggregator1.mock.linkAvailableForPayment.returns(twoLINK)
+ await aggregator2.mock.linkAvailableForPayment.returns(twoLINK)
+ await aggregator3.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget1.mock.linkAvailableForPayment.returns(zeroLINK)
+ await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK)
+
+ h.assertLinkTokenBalance(lt, aggregator1.address, twoLINK)
+ h.assertLinkTokenBalance(lt, aggregator2.address, twoLINK)
+ h.assertLinkTokenBalance(lt, aggregator3.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, directTarget1.address, zeroLINK)
+ h.assertLinkTokenBalance(lt, directTarget2.address, zeroLINK)
+
const tx = await labm.connect(keeperRegistry).topUp(watchListAddresses)
- await assertContractLinkBalances(
- twoLINK,
- twoLINK,
- zeroLINK,
- zeroLINK,
- zeroLINK,
- )
- await expect(tx)
- .to.emit(labm, 'TopUpSucceeded')
- .withArgs(proxy1.address)
- await expect(tx)
- .to.emit(labm, 'TopUpSucceeded')
- .withArgs(proxy2.address)
+ await expect(tx).to.emit(labm, 'TopUpSucceeded')
})
})
})
From cea3e6e037d77291ba392a69ba0dc7c6c9cc67c2 Mon Sep 17 00:00:00 2001
From: CL-Andrew <96407253+CL-Andrew@users.noreply.github.com>
Date: Fri, 3 Nov 2023 15:15:10 -0700
Subject: [PATCH 072/327] Optional and Configurable LDAP User/Session
Management Support and Reworked Pluggable Auth Driver Interface (#9750)
* Initial commit of LDAP Auth driver support with toml config docs and parser driver, pluggable auth interface defined and localauth (default) moved to scoped module
* 'orm sessions.UserManager' to 'um sessions.UserManager'
* Add missing checks for the UserApiTokenEnabled config field for token related calls, rename ServerTls to ServerTLS
* Update docs toml LDAP section to clarify how the fields are used and specify LDAP terminology
* Clarify LDAP 'cn' in toml docs for LDAP
* Fix WebServer TOML and config definitions, split types for WebServerLDAPSecrets to following config and secret toml convention, improved error handling on startup for missing WebServer and LDAP fields
* Error application startup if authentication method is not one of the valid options, instead of defaulting to local
* Don't export unneeded ldapGroupMembersListToUser in ldap module
* Bugfixes for LDAP find user when no results of passed email, address the two ways local CLI can attempt auth using local client for LDAP implementation of createSession, moved ErrNotSupported up to authentication types level so router can expose to API response when type message
* Rework LDAP function to check if list of provided query emails possess the 'active' attribute/group in a single query. Now returns list of bools one to one for the passed in emails array and correctly handles the case for querying more than one email at a time, changing function return signature from just error
* Update LDAP field naming for Cn, Dn to Go convention CN, DN in toml and types, tidy god mod, fix path imports for test files, fix toml comments
* Post merge toml module rename LDAP model fixes
Populate test config and test secrets toml file with new LDAP config fields, use secrets parse type for LDAPSecrets interface
* Update top level application struct to accomodate new sibling AuthProvider field to preserve always available local admin auth
This commit splits the newly added UserManager interface (now renamed) into two interfaces where the existing local user ORM
auth provider covers the implementation for the required always available Admin commands. These are used when configuring the node
initially (creating the admin user) or assuming the admin role from the command line, which should work locally as well regardless
of the configured Authentication Provider.
Renamed new UserManager interface to AuthenticationProvider, which no longer has the boilerplate Admin prefix functions.
* Update all err comparison checks for ErrNotSupported to errors.Is
* go generate mocks
* Tidy unecessary string cast, bump ldap library to latest and use v3, test forward compatibility, mod tidy
* Clean up auth provider config switch statement
* Update checked in test txtar output
* Update gql test and mocks with new authprovider mock, updated in mock struct. Add missing TestPassword call
* Update remaining test config toml files with new WebServer LDAP fields, populated where test case makes sense, add toml config validation checks on parse for LDAP fields non empty, update LDAP Server field to Models Secret URL, add parsing test for secrets
* Update LDAP module with missing API token implementation - creation, use, and deletion
Bugfixes and logic improvements for LDAP session reaper/upstream sync. Reaper now correctly syncs roles and users from upstream via sleeper task tied to LDAP auth actions. User sessions and API tokens are correctly removed when the expire TTL is met, the local LDAP sessions and API tokens role is updated and synced with the state of the upstream LDAP server as part of the logic of this sleeper task, and if a user is no longer present in any of the defined groups they are automatically removed from the LDAP sessions and API tokens tables (checked on cadence of sleeper task Work call)
Update LDAP webconfigToken duration to match wrapped models.Duration type
Add const for LDAPUniqueMemberAttribute/uniqueMember in ldapauth module
Add info logger connection attempt message in case of hang on node startup
Fix expired LDAP api tokens purge issue
Nicer error for session missing / expired on attempt of sesion token use (remove error within stdout)
* Add missing support for local CLI user and auth when using LDAP Authentication module
Fixed edge cases for FindUser, check local users table as well, local user API Token creation and support
Add localauth_user flag for ldap specific tables to support node usage by the initial required local admin user, add logic in CreateSession
* Update config UpstreamSyncInterval and UpstreamSyncRateLimit functionality for LDAP Sync daemon
Implement .Work call on timer for LDAP sync in the background, independent of Auth related calls. The implementation of SleeperTask calls Work when hooked into Auth events, being called on login or logout. Now if UpstreamSyncInterval is defined as non 0, a background timer call will call the sync function, respecting the new UpstreamSyncRateLimit field
* LDAP Fix for checks of optional isactive property on group query, find user functionality, and admin functions
Bug fix for ldap driver not supporting local admin users case of change password and list users, FindUser functionality can now return matches of local admin users
List Users now includes local users and works as expected for upstream LDAP users who have any of the defined groups required for node access. Bugfix for group search query in both the sync and ldap providers modules. Factored out group query functionality for both call sites
Set Password support for only local admin users as functionality is still supported and required when using LDAP auth, upstream user modification remains unsupported
Bugfix for shell local initialization not using local admin auth ORM, causing issue with initial assume user step in ListUsers
* bump migration file index
* remove incorrect rebased merge resolution for Explorer removal
* Change default config definitions for LDAP 'Is Active' attribute checks to empty, as not all LDAP providers will use 'ActiveAttribute', or retain group member access when inactive. Fix error handling in find users for case when NoRows, dont log error automatically with Transaction middleware
* Simplify sessions purge sql exec using pq.Array instead of manually generating placeholders, and Regenerate mocks
* Merge go mod require groups, gotidy
* Rename changed authentication provider session ORM in test files, fix config test reordering, add missing mock, update const err strings
* Add mock value for one test case of config ldap is active attribute, revert purge sessions api token test file, migrate to new errors module and update how errors are wrapped, lowercase all error messages
* Factor out unsupported action error message in user controller with new errUnsupportedForAuth type
* Rebase, update migration index
* Update config_test full case, error case for missing fields
* Fix tests with missing Mocks for cmd shell, config resolver, and sessions localauth
Missing mocks for LocalAdminUsersORM
Revert change unrelated to LDAP feature in AuthorizedUserWithSession (refactored)
Fix leaked internal error over HTTP response + test case for delete user
Fix mocks and missing TestPassword call cases for graphql mutation tests, update incorrect password test case
Add expected LDAP config fields for config resolver tests
* Bump migration file index for ldap tables
* Linter fixes - application.go localAdminUsersORM in initialized one line
Fix config sesion timeout interface naming (r -> l)
Typos fix in ldap.go docstring
Rework logic in checkErr for FindUser logic of testing admin table query before failing (rework to avoid error shadowing)
Invert logic for err != nil in case for local admin user found
Fix missing errors.Is comparison for sessions.ErrUserSessionExpired in ldap module
Run docs generate
Fix typo in txtar test LDAP config
* Add missing ldap fields to warnings.txtar, fix err shadowing linter errors in ldap.go and sync.go
Run go mod tidy
* Fix linter import order and groupings
* More import ordering lint
* Rebase, bump sql migraiton index
* use correct guregu/null.v4 version
* Implement test cases for ldap module, create LDAP client and LDAPConn wrapper interfaces and mocks
New LDAPClient and LDAPConn interfaces allow test mocks to handle Bind and Search functionality. the ldap implementation has been updated to store the ldapClient (still ephemeral single use, like a factory) in the struct such that the test harness can swap the implementation with the mocks.
Create helpers_test.go following codebase convention to allow a Setter method to be defined for the ldapClient field, but separated from the production build. This allows the ldap struct and field properties to remain unexported. Test helper contains test mock configand helper constructor function
New ldap_test.go module with cases for ldap query functionality and local admin support assertions
ldap.go module improvements, return struct in constructor instead of interface type for authentication provider, define user facing error consts (test assertion), store ldapClient in struct, nicer error handling for user not found in FindUser, fix err shadowing reuse error in token expired case, fix typos in ListUsers
LDAP Sync rework for new ldapclient field, use new interface to support mocking
Remove dangling commited localauth orm.mock, which was being imported by a missed test. Test now imports the correct mock (new authentication provider mocks)
* Updated CHANGELOG.md
* Update go.mod
* Linter fixes UserNoLDAPGroups -> ErrUserNoLDAPGroups, shadowing
* module -> package, format package docstring properly for ldapauth to support godoc render
Remove redundant LDAP prefix for UniqueMemberAttribute
* Remove rebased gomod line
* define const NodeAdmins* for mocked tests in helpers_test, reference [WebServer].AuthenticationMethod in changelog
* Add missing returns in sync Work call when failed to establish LDAP connection as it is required for the sync functionality, flip return flow in TestPassword for admin fallback
* Updating naming and address nits
LocalAdminUsersORM -> BasicAdminUsersORM, regenerate mocks
Save indent in WebServer ValidateConfig when ldapauth
Update comments and rename CreateEphemeralClient -> CreateEphemeralConnection
* Add missed go generate Application change for BasicAdminUsersORM rename
---
core/cmd/admin_commands_test.go | 6 +-
core/cmd/app_test.go | 1 +
core/cmd/shell.go | 12 +-
core/cmd/shell_local.go | 7 +-
core/cmd/shell_local_test.go | 11 +-
core/cmd/shell_remote_test.go | 16 +-
core/cmd/shell_test.go | 13 +-
core/config/docs/core.toml | 40 +
core/config/docs/secrets.toml | 9 +
core/config/toml/types.go | 146 +++
core/config/web_config.go | 25 +
core/internal/cltest/cltest.go | 2 +-
core/internal/cltest/mocks.go | 4 +-
core/internal/features/features_test.go | 2 +-
core/internal/mocks/application.go | 48 +-
core/scripts/go.mod | 3 +
core/scripts/go.sum | 15 +
core/services/chainlink/application.go | 49 +-
core/services/chainlink/config.go | 24 +-
core/services/chainlink/config_general.go | 2 +-
.../services/chainlink/config_general_test.go | 10 +
core/services/chainlink/config_test.go | 51 +-
core/services/chainlink/config_web_server.go | 145 +++
.../testdata/config-empty-effective.toml | 20 +
.../chainlink/testdata/config-full.toml | 20 +
.../chainlink/testdata/config-invalid.toml | 22 +
.../config-multi-chain-effective.toml | 20 +
.../secrets-webserver-ldap.toml | 4 +
.../testdata/secrets-full-redacted.toml | 6 +
.../chainlink/testdata/secrets-full.toml | 6 +
core/sessions/authentication.go | 66 ++
core/sessions/ldapauth/client.go | 47 +
core/sessions/ldapauth/helpers_test.go | 131 +++
core/sessions/ldapauth/ldap.go | 858 ++++++++++++++++++
core/sessions/ldapauth/ldap_test.go | 639 +++++++++++++
core/sessions/ldapauth/mocks/ldap_client.go | 53 ++
core/sessions/ldapauth/mocks/ldap_conn.go | 82 ++
core/sessions/ldapauth/sync.go | 343 +++++++
core/sessions/{ => localauth}/orm.go | 111 +--
core/sessions/{ => localauth}/orm_test.go | 10 +-
core/sessions/{ => localauth}/reaper.go | 2 +-
core/sessions/{ => localauth}/reaper_test.go | 40 +-
.../{orm.go => authentication_provider.go} | 62 +-
core/sessions/mocks/basic_admin_users_orm.go | 91 ++
core/sessions/session.go | 74 ++
core/sessions/user.go | 64 --
core/sessions/webauthn.go | 4 +-
.../0208_create_ldap_sessions_table.sql | 22 +
core/web/auth/auth.go | 5 +-
core/web/auth/auth_test.go | 4 +-
core/web/auth/gql_test.go | 4 +-
core/web/resolver/api_token_test.go | 64 +-
core/web/resolver/mutation.go | 20 +-
core/web/resolver/resolver_test.go | 6 +-
.../testdata/config-empty-effective.toml | 20 +
core/web/resolver/testdata/config-full.toml | 20 +
.../config-multi-chain-effective.toml | 20 +
core/web/resolver/user_test.go | 26 +-
core/web/router.go | 12 +-
core/web/sessions_controller.go | 6 +-
core/web/sessions_controller_test.go | 18 +-
core/web/user_controller.go | 76 +-
core/web/user_controller_test.go | 4 +-
core/web/webauthn_controller.go | 6 +-
docs/CHANGELOG.md | 5 +
docs/CONFIG.md | 133 +++
docs/SECRETS.md | 27 +
go.mod | 3 +
go.sum | 15 +
integration-tests/go.mod | 3 +
integration-tests/go.sum | 9 +
testdata/scripts/node/validate/default.txtar | 20 +
.../disk-based-logging-disabled.txtar | 20 +
.../validate/disk-based-logging-no-dir.txtar | 20 +
.../node/validate/disk-based-logging.txtar | 20 +
testdata/scripts/node/validate/invalid.txtar | 20 +
testdata/scripts/node/validate/valid.txtar | 20 +
testdata/scripts/node/validate/warnings.txtar | 20 +
78 files changed, 3743 insertions(+), 341 deletions(-)
create mode 100644 core/services/chainlink/testdata/mergingsecretsdata/secrets-webserver-ldap.toml
create mode 100644 core/sessions/authentication.go
create mode 100644 core/sessions/ldapauth/client.go
create mode 100644 core/sessions/ldapauth/helpers_test.go
create mode 100644 core/sessions/ldapauth/ldap.go
create mode 100644 core/sessions/ldapauth/ldap_test.go
create mode 100644 core/sessions/ldapauth/mocks/ldap_client.go
create mode 100644 core/sessions/ldapauth/mocks/ldap_conn.go
create mode 100644 core/sessions/ldapauth/sync.go
rename core/sessions/{ => localauth}/orm.go (80%)
rename core/sessions/{ => localauth}/orm_test.go (95%)
rename core/sessions/{ => localauth}/reaper.go (98%)
rename core/sessions/{ => localauth}/reaper_test.go (69%)
rename core/sessions/mocks/{orm.go => authentication_provider.go} (75%)
create mode 100644 core/sessions/mocks/basic_admin_users_orm.go
create mode 100644 core/sessions/session.go
create mode 100644 core/store/migrate/migrations/0208_create_ldap_sessions_table.sql
diff --git a/core/cmd/admin_commands_test.go b/core/cmd/admin_commands_test.go
index a5512fddda..954e3577d3 100644
--- a/core/cmd/admin_commands_test.go
+++ b/core/cmd/admin_commands_test.go
@@ -62,7 +62,7 @@ func TestShell_ChangeRole(t *testing.T) {
app := startNewApplicationV2(t, nil)
client, _ := app.NewShellAndRenderer()
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.AuthenticationProvider().CreateUser(&user))
tests := []struct {
name string
@@ -101,7 +101,7 @@ func TestShell_DeleteUser(t *testing.T) {
app := startNewApplicationV2(t, nil)
client, _ := app.NewShellAndRenderer()
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.BasicAdminUsersORM().CreateUser(&user))
tests := []struct {
name string
@@ -135,7 +135,7 @@ func TestShell_ListUsers(t *testing.T) {
app := startNewApplicationV2(t, nil)
client, _ := app.NewShellAndRenderer()
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.AuthenticationProvider().CreateUser(&user))
set := flag.NewFlagSet("test", 0)
cltest.FlagSetApplyFromAction(client.ListUsers, set, "")
diff --git a/core/cmd/app_test.go b/core/cmd/app_test.go
index bbb00bff3e..e5e2940642 100644
--- a/core/cmd/app_test.go
+++ b/core/cmd/app_test.go
@@ -151,6 +151,7 @@ func Test_initServerConfig(t *testing.T) {
"../services/chainlink/testdata/mergingsecretsdata/secrets-mercury-split-one.toml",
"../services/chainlink/testdata/mergingsecretsdata/secrets-mercury-split-two.toml",
"../services/chainlink/testdata/mergingsecretsdata/secrets-threshold.toml",
+ "../services/chainlink/testdata/mergingsecretsdata/secrets-webserver-ldap.toml",
},
},
wantErr: false,
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 308ebf8da8..80ecd2590b 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -776,8 +776,8 @@ func (f *fileSessionRequestBuilder) Build(file string) (sessions.SessionRequest,
// APIInitializer is the interface used to create the API User credentials
// needed to access the API. Does nothing if API user already exists.
type APIInitializer interface {
- // Initialize creates a new user for API access, or does nothing if one exists.
- Initialize(orm sessions.ORM, lggr logger.Logger) (sessions.User, error)
+ // Initialize creates a new local Admin user for API access, or does nothing if one exists.
+ Initialize(orm sessions.BasicAdminUsersORM, lggr logger.Logger) (sessions.User, error)
}
type promptingAPIInitializer struct {
@@ -791,11 +791,11 @@ func NewPromptingAPIInitializer(prompter Prompter) APIInitializer {
}
// Initialize uses the terminal to get credentials that it then saves in the store.
-func (t *promptingAPIInitializer) Initialize(orm sessions.ORM, lggr logger.Logger) (sessions.User, error) {
+func (t *promptingAPIInitializer) Initialize(orm sessions.BasicAdminUsersORM, lggr logger.Logger) (sessions.User, error) {
// Load list of users to determine which to assume, or if a user needs to be created
dbUsers, err := orm.ListUsers()
if err != nil {
- return sessions.User{}, err
+ return sessions.User{}, errors.Wrap(err, "Unable to List users for initialization")
}
// If there are no users in the database, prompt for initial admin user creation
@@ -845,7 +845,7 @@ func NewFileAPIInitializer(file string) APIInitializer {
return fileAPIInitializer{file: file}
}
-func (f fileAPIInitializer) Initialize(orm sessions.ORM, lggr logger.Logger) (sessions.User, error) {
+func (f fileAPIInitializer) Initialize(orm sessions.BasicAdminUsersORM, lggr logger.Logger) (sessions.User, error) {
request, err := credentialsFromFile(f.file, lggr)
if err != nil {
return sessions.User{}, err
@@ -854,7 +854,7 @@ func (f fileAPIInitializer) Initialize(orm sessions.ORM, lggr logger.Logger) (se
// Load list of users to determine which to assume, or if a user needs to be created
dbUsers, err := orm.ListUsers()
if err != nil {
- return sessions.User{}, err
+ return sessions.User{}, errors.Wrap(err, "Unable to List users for initialization")
}
// If there are no users in the database, create initial admin user from session request from file creds
diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go
index 401375238d..dea9a29359 100644
--- a/core/cmd/shell_local.go
+++ b/core/cmd/shell_local.go
@@ -362,7 +362,8 @@ func (s *Shell) runNode(c *cli.Context) error {
return s.errorOut(errors.Wrap(err, "fatal error instantiating application"))
}
- sessionORM := app.SessionORM()
+ // Local shell initialization always uses local auth users table for admin auth
+ authProviderORM := app.BasicAdminUsersORM()
keyStore := app.GetKeyStore()
err = s.KeyStoreAuthenticator.authenticate(keyStore, s.Config.Password())
if err != nil {
@@ -449,11 +450,11 @@ func (s *Shell) runNode(c *cli.Context) error {
}
var user sessions.User
- if user, err = NewFileAPIInitializer(c.String("api")).Initialize(sessionORM, lggr); err != nil {
+ if user, err = NewFileAPIInitializer(c.String("api")).Initialize(authProviderORM, lggr); err != nil {
if !errors.Is(err, ErrNoCredentialFile) {
return errors.Wrap(err, "error creating api initializer")
}
- if user, err = s.FallbackAPIInitializer.Initialize(sessionORM, lggr); err != nil {
+ if user, err = s.FallbackAPIInitializer.Initialize(authProviderORM, lggr); err != nil {
if errors.Is(err, ErrorNoAPICredentialsAvailable) {
return errors.WithStack(err)
}
diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go
index 89b8704f87..df60e16423 100644
--- a/core/cmd/shell_local_test.go
+++ b/core/cmd/shell_local_test.go
@@ -25,7 +25,7 @@ import (
chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
- "github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth"
"github.com/smartcontractkit/chainlink/v2/core/store/dialects"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -79,7 +79,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) {
})
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db, cfg.Database())
- sessionORM := sessions.NewORM(db, time.Minute, logger.TestLogger(t), cfg.Database(), audit.NoopLogger)
+ authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), cfg.Database(), audit.NoopLogger)
lggr := logger.TestLogger(t)
@@ -100,7 +100,8 @@ func TestShell_RunNodeWithPasswords(t *testing.T) {
pgtest.MustExec(t, db, "DELETE FROM users;")
app := mocks.NewApplication(t)
- app.On("SessionORM").Return(sessionORM).Maybe()
+ app.On("AuthenticationProvider").Return(authProviderORM).Maybe()
+ app.On("BasicAdminUsersORM").Return(authProviderORM).Maybe()
app.On("GetKeyStore").Return(keyStore).Maybe()
app.On("GetRelayers").Return(testRelayers).Maybe()
app.On("Start", mock.Anything).Maybe().Return(nil)
@@ -171,7 +172,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) {
c.Insecure.OCRDevelopmentMode = nil
})
db := pgtest.NewSqlxDB(t)
- sessionORM := sessions.NewORM(db, time.Minute, logger.TestLogger(t), cfg.Database(), audit.NoopLogger)
+ authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), cfg.Database(), audit.NoopLogger)
// Clear out fixture users/users created from the other test cases
// This asserts that on initial run with an empty users table that the credentials file will instantiate and
@@ -199,7 +200,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) {
}
testRelayers := genTestEVMRelayers(t, opts, keyStore)
app := mocks.NewApplication(t)
- app.On("SessionORM").Return(sessionORM)
+ app.On("BasicAdminUsersORM").Return(authProviderORM)
app.On("GetKeyStore").Return(keyStore)
app.On("GetRelayers").Return(testRelayers).Maybe()
app.On("Start", mock.Anything).Maybe().Return(nil)
diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go
index 7f998225f6..91b56ee53a 100644
--- a/core/cmd/shell_remote_test.go
+++ b/core/cmd/shell_remote_test.go
@@ -258,7 +258,7 @@ func TestShell_DestroyExternalInitiator_NotFound(t *testing.T) {
func TestShell_RemoteLogin(t *testing.T) {
app := startNewApplicationV2(t, nil)
- orm := app.SessionORM()
+ orm := app.AuthenticationProvider()
u := cltest.NewUserWithSession(t, orm)
@@ -301,7 +301,7 @@ func TestShell_RemoteBuildCompatibility(t *testing.T) {
t.Parallel()
app := startNewApplicationV2(t, nil)
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
enteredStrings := []string{u.Email, cltest.Password}
prompter := &cltest.MockCountingPrompter{T: t, EnteredStrings: append(enteredStrings, enteredStrings...)}
client := app.NewAuthenticatingShell(prompter)
@@ -340,7 +340,7 @@ func TestShell_CheckRemoteBuildCompatibility(t *testing.T) {
t.Parallel()
app := startNewApplicationV2(t, nil)
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
tests := []struct {
name string
remoteVersion, remoteSha string
@@ -416,7 +416,7 @@ func TestShell_ChangePassword(t *testing.T) {
t.Parallel()
app := startNewApplicationV2(t, nil)
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
enteredStrings := []string{u.Email, cltest.Password}
prompter := &cltest.MockCountingPrompter{T: t, EnteredStrings: enteredStrings}
@@ -466,7 +466,7 @@ func TestShell_Profile_InvalidSecondsParam(t *testing.T) {
t.Parallel()
app := startNewApplicationV2(t, nil)
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
enteredStrings := []string{u.Email, cltest.Password}
prompter := &cltest.MockCountingPrompter{T: t, EnteredStrings: enteredStrings}
@@ -497,7 +497,7 @@ func TestShell_Profile(t *testing.T) {
t.Parallel()
app := startNewApplicationV2(t, nil)
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
enteredStrings := []string{u.Email, cltest.Password}
prompter := &cltest.MockCountingPrompter{T: t, EnteredStrings: enteredStrings}
@@ -648,7 +648,7 @@ func TestShell_AutoLogin(t *testing.T) {
app := startNewApplicationV2(t, nil)
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.BasicAdminUsersORM().CreateUser(&user))
sr := sessions.SessionRequest{
Email: user.Email,
@@ -676,7 +676,7 @@ func TestShell_AutoLogin_AuthFails(t *testing.T) {
app := startNewApplicationV2(t, nil)
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.BasicAdminUsersORM().CreateUser(&user))
sr := sessions.SessionRequest{
Email: user.Email,
diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go
index 9b87e8fb1d..2a8c2c5586 100644
--- a/core/cmd/shell_test.go
+++ b/core/cmd/shell_test.go
@@ -26,6 +26,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks"
"github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth"
"github.com/smartcontractkit/chainlink/v2/plugins"
)
@@ -33,7 +34,7 @@ func TestTerminalCookieAuthenticator_AuthenticateWithoutSession(t *testing.T) {
t.Parallel()
app := cltest.NewApplicationEVMDisabled(t)
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
tests := []struct {
name, email, pwd string
@@ -65,7 +66,7 @@ func TestTerminalCookieAuthenticator_AuthenticateWithSession(t *testing.T) {
app := cltest.NewApplicationEVMDisabled(t)
require.NoError(t, app.Start(testutils.Context(t)))
- u := cltest.NewUserWithSession(t, app.SessionORM())
+ u := cltest.NewUserWithSession(t, app.AuthenticationProvider())
tests := []struct {
name, email, pwd string
@@ -155,7 +156,7 @@ func TestTerminalAPIInitializer_InitializeWithoutAPIUser(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
db := pgtest.NewSqlxDB(t)
lggr := logger.TestLogger(t)
- orm := sessions.NewORM(db, time.Minute, lggr, pgtest.NewQConfig(true), audit.NoopLogger)
+ orm := localauth.NewORM(db, time.Minute, lggr, pgtest.NewQConfig(true), audit.NoopLogger)
mock := &cltest.MockCountingPrompter{T: t, EnteredStrings: test.enteredStrings, NotTerminal: !test.isTerminal}
tai := cmd.NewPromptingAPIInitializer(mock)
@@ -186,7 +187,7 @@ func TestTerminalAPIInitializer_InitializeWithExistingAPIUser(t *testing.T) {
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewGeneralConfig(t, nil)
lggr := logger.TestLogger(t)
- orm := sessions.NewORM(db, time.Minute, lggr, cfg.Database(), audit.NoopLogger)
+ orm := localauth.NewORM(db, time.Minute, lggr, cfg.Database(), audit.NoopLogger)
// Clear out fixture users/users created from the other test cases
// This asserts that on initial run with an empty users table that the credentials file will instantiate and
@@ -223,7 +224,7 @@ func TestFileAPIInitializer_InitializeWithoutAPIUser(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
db := pgtest.NewSqlxDB(t)
lggr := logger.TestLogger(t)
- orm := sessions.NewORM(db, time.Minute, lggr, pgtest.NewQConfig(true), audit.NoopLogger)
+ orm := localauth.NewORM(db, time.Minute, lggr, pgtest.NewQConfig(true), audit.NoopLogger)
// Clear out fixture users/users created from the other test cases
// This asserts that on initial run with an empty users table that the credentials file will instantiate and
@@ -248,7 +249,7 @@ func TestFileAPIInitializer_InitializeWithoutAPIUser(t *testing.T) {
func TestFileAPIInitializer_InitializeWithExistingAPIUser(t *testing.T) {
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewGeneralConfig(t, nil)
- orm := sessions.NewORM(db, time.Minute, logger.TestLogger(t), cfg.Database(), audit.NoopLogger)
+ orm := localauth.NewORM(db, time.Minute, logger.TestLogger(t), cfg.Database(), audit.NoopLogger)
tests := []struct {
name string
diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml
index 1ca4c656a7..0a8e6aba3b 100644
--- a/core/config/docs/core.toml
+++ b/core/config/docs/core.toml
@@ -161,6 +161,8 @@ MaxAgeDays = 0 # Default
MaxBackups = 1 # Default
[WebServer]
+# AuthenticationMethod defines which pluggable auth interface to use for user login and role assumption. Options include 'local' and 'ldap'. See docs for more details
+AuthenticationMethod = 'local' # Default
# AllowOrigins controls the URLs Chainlink nodes emit in the `Allow-Origins` header of its API responses. The setting can be a comma-separated list with no spaces. You might experience CORS issues if this is not set correctly.
#
# You should set this to the external URL that you use to access the Chainlink UI.
@@ -191,6 +193,44 @@ StartTimeout = '15s' # Default
# ListenIP specifies the IP to bind the HTTP server to
ListenIP = '0.0.0.0' # Default
+# Optional LDAP config if WebServer.AuthenticationMethod is set to 'ldap'
+# LDAP queries are all parameterized to support custom LDAP 'dn', 'cn', and attributes
+[WebServer.LDAP]
+# ServerTLS defines the option to require the secure ldaps
+ServerTLS = true # Default
+# SessionTimeout determines the amount of idle time to elapse before session cookies expire. This signs out GUI users from their sessions.
+SessionTimeout = '15m0s' # Default
+# QueryTimeout defines how long queries should wait before timing out, defined in seconds
+QueryTimeout = '2m0s' # Default
+# BaseUserAttr defines the base attribute used to populate LDAP queries such as "uid=$", default is example
+BaseUserAttr = 'uid' # Default
+# BaseDN defines the base LDAP 'dn' search filter to apply to every LDAP query, replace example,com with the appropriate LDAP server's structure
+BaseDN = 'dc=custom,dc=example,dc=com' # Example
+# UsersDN defines the 'dn' query to use when querying for the 'users' 'ou' group
+UsersDN = 'ou=users' # Default
+# GroupsDN defines the 'dn' query to use when querying for the 'groups' 'ou' group
+GroupsDN = 'ou=groups' # Default
+# ActiveAttribute is an optional user field to check truthiness for if a user is valid/active. This is only required if the LDAP provider lists inactive users as members of groups
+ActiveAttribute = '' # Default
+# ActiveAttributeAllowedValue is the value to check against for the above optional user attribute
+ActiveAttributeAllowedValue = '' # Default
+# AdminUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Admin' role
+AdminUserGroupCN = 'NodeAdmins' # Default
+# EditUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Edit' role
+EditUserGroupCN = 'NodeEditors' # Default
+# RunUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Run' role
+RunUserGroupCN = 'NodeRunners' # Default
+# ReadUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Read' role
+ReadUserGroupCN = 'NodeReadOnly' # Default
+# UserApiTokenEnabled enables the users to issue API tokens with the same access of their role
+UserApiTokenEnabled = false # Default
+# UserAPITokenDuration is the duration of time an API token is active for before expiring
+UserAPITokenDuration = '240h0m0s' # Default
+# UpstreamSyncInterval is the interval at which the background LDAP sync task will be called. A '0s' value disables the background sync being run on an interval. This check is already performed during login/logout actions, all sessions and API tokens stored in the local ldap tables are updated to match the remote server
+UpstreamSyncInterval = '0s' # Default
+# UpstreamSyncRateLimit defines a duration to limit the number of query/API calls to the upstream LDAP provider. It prevents the sync functionality from being called multiple times within the defined duration
+UpstreamSyncRateLimit = '2m0s' # Default
+
[WebServer.RateLimit]
# Authenticated defines the threshold to which authenticated requests get limited. More than this many authenticated requests per `AuthenticatedRateLimitPeriod` will be rejected.
Authenticated = 1000 # Default
diff --git a/core/config/docs/secrets.toml b/core/config/docs/secrets.toml
index 2b491a7749..4ed2325dfb 100644
--- a/core/config/docs/secrets.toml
+++ b/core/config/docs/secrets.toml
@@ -14,6 +14,15 @@ BackupURL = "postgresql://user:pass@read-replica.example.com:5432/dbname?sslmode
# Environment variable: `CL_DATABASE_ALLOW_SIMPLE_PASSWORDS`
AllowSimplePasswords = false # Default
+# Optional LDAP config
+[WebServer.LDAP]
+# ServerAddress is the full ldaps:// address of the ldap server to authenticate with and query
+ServerAddress = 'ldaps://127.0.0.1' # Example
+# ReadOnlyUserLogin is the username of the read only root user used to authenticate the requested LDAP queries
+ReadOnlyUserLogin = 'viewer@example.com' # Example
+# ReadOnlyUserPass is the password for the above account
+ReadOnlyUserPass = 'password' # Example
+
[Password]
# Keystore is the password for the node's account.
#
diff --git a/core/config/toml/types.go b/core/config/toml/types.go
index b7c8cfbc47..61962d43e5 100644
--- a/core/config/toml/types.go
+++ b/core/config/toml/types.go
@@ -20,6 +20,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/config/parse"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions"
"github.com/smartcontractkit/chainlink/v2/core/store/dialects"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -101,6 +102,7 @@ func (c *Core) ValidateConfig() (err error) {
type Secrets struct {
Database DatabaseSecrets `toml:",omitempty"`
Password Passwords `toml:",omitempty"`
+ WebServer WebServerSecrets `toml:",omitempty"`
Pyroscope PyroscopeSecrets `toml:",omitempty"`
Prometheus PrometheusSecrets `toml:",omitempty"`
Mercury MercurySecrets `toml:",omitempty"`
@@ -592,6 +594,7 @@ func (l *LogFile) setFrom(f *LogFile) {
}
type WebServer struct {
+ AuthenticationMethod *string
AllowOrigins *string
BridgeResponseURL *models.URL
BridgeCacheTTL *models.Duration
@@ -604,12 +607,16 @@ type WebServer struct {
StartTimeout *models.Duration
ListenIP *net.IP
+ LDAP WebServerLDAP `toml:",omitempty"`
MFA WebServerMFA `toml:",omitempty"`
RateLimit WebServerRateLimit `toml:",omitempty"`
TLS WebServerTLS `toml:",omitempty"`
}
func (w *WebServer) setFrom(f *WebServer) {
+ if v := f.AuthenticationMethod; v != nil {
+ w.AuthenticationMethod = v
+ }
if v := f.AllowOrigins; v != nil {
w.AllowOrigins = v
}
@@ -644,11 +651,46 @@ func (w *WebServer) setFrom(f *WebServer) {
w.HTTPMaxSize = v
}
+ w.LDAP.setFrom(&f.LDAP)
w.MFA.setFrom(&f.MFA)
w.RateLimit.setFrom(&f.RateLimit)
w.TLS.setFrom(&f.TLS)
}
+func (w *WebServer) ValidateConfig() (err error) {
+ // Validate LDAP fields when authentication method is LDAPAuth
+ if *w.AuthenticationMethod != string(sessions.LDAPAuth) {
+ return
+ }
+
+ // Assert LDAP fields when AuthMethod set to LDAP
+ if *w.LDAP.BaseDN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.BaseDN", Msg: "LDAP BaseDN can not be empty"})
+ }
+ if *w.LDAP.BaseUserAttr == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.BaseUserAttr", Msg: "LDAP BaseUserAttr can not be empty"})
+ }
+ if *w.LDAP.UsersDN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.UsersDN", Msg: "LDAP UsersDN can not be empty"})
+ }
+ if *w.LDAP.GroupsDN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.GroupsDN", Msg: "LDAP GroupsDN can not be empty"})
+ }
+ if *w.LDAP.AdminUserGroupCN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.AdminUserGroupCN", Msg: "LDAP AdminUserGroupCN can not be empty"})
+ }
+ if *w.LDAP.EditUserGroupCN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.RunUserGroupCN", Msg: "LDAP ReadUserGroupCN can not be empty"})
+ }
+ if *w.LDAP.RunUserGroupCN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.RunUserGroupCN", Msg: "LDAP RunUserGroupCN can not be empty"})
+ }
+ if *w.LDAP.ReadUserGroupCN == "" {
+ err = multierr.Append(err, configutils.ErrInvalid{Name: "LDAP.ReadUserGroupCN", Msg: "LDAP ReadUserGroupCN can not be empty"})
+ }
+ return err
+}
+
type WebServerMFA struct {
RPID *string
RPOrigin *string
@@ -715,6 +757,110 @@ func (w *WebServerTLS) setFrom(f *WebServerTLS) {
}
}
+type WebServerLDAP struct {
+ ServerTLS *bool
+ SessionTimeout *models.Duration
+ QueryTimeout *models.Duration
+ BaseUserAttr *string
+ BaseDN *string
+ UsersDN *string
+ GroupsDN *string
+ ActiveAttribute *string
+ ActiveAttributeAllowedValue *string
+ AdminUserGroupCN *string
+ EditUserGroupCN *string
+ RunUserGroupCN *string
+ ReadUserGroupCN *string
+ UserApiTokenEnabled *bool
+ UserAPITokenDuration *models.Duration
+ UpstreamSyncInterval *models.Duration
+ UpstreamSyncRateLimit *models.Duration
+}
+
+func (w *WebServerLDAP) setFrom(f *WebServerLDAP) {
+ if v := f.ServerTLS; v != nil {
+ w.ServerTLS = v
+ }
+ if v := f.SessionTimeout; v != nil {
+ w.SessionTimeout = v
+ }
+ if v := f.SessionTimeout; v != nil {
+ w.SessionTimeout = v
+ }
+ if v := f.QueryTimeout; v != nil {
+ w.QueryTimeout = v
+ }
+ if v := f.BaseUserAttr; v != nil {
+ w.BaseUserAttr = v
+ }
+ if v := f.BaseDN; v != nil {
+ w.BaseDN = v
+ }
+ if v := f.UsersDN; v != nil {
+ w.UsersDN = v
+ }
+ if v := f.GroupsDN; v != nil {
+ w.GroupsDN = v
+ }
+ if v := f.ActiveAttribute; v != nil {
+ w.ActiveAttribute = v
+ }
+ if v := f.ActiveAttributeAllowedValue; v != nil {
+ w.ActiveAttributeAllowedValue = v
+ }
+ if v := f.AdminUserGroupCN; v != nil {
+ w.AdminUserGroupCN = v
+ }
+ if v := f.EditUserGroupCN; v != nil {
+ w.EditUserGroupCN = v
+ }
+ if v := f.RunUserGroupCN; v != nil {
+ w.RunUserGroupCN = v
+ }
+ if v := f.ReadUserGroupCN; v != nil {
+ w.ReadUserGroupCN = v
+ }
+ if v := f.UserApiTokenEnabled; v != nil {
+ w.UserApiTokenEnabled = v
+ }
+ if v := f.UserAPITokenDuration; v != nil {
+ w.UserAPITokenDuration = v
+ }
+ if v := f.UpstreamSyncInterval; v != nil {
+ w.UpstreamSyncInterval = v
+ }
+ if v := f.UpstreamSyncRateLimit; v != nil {
+ w.UpstreamSyncRateLimit = v
+ }
+}
+
+type WebServerLDAPSecrets struct {
+ ServerAddress *models.SecretURL
+ ReadOnlyUserLogin *models.Secret
+ ReadOnlyUserPass *models.Secret
+}
+
+func (w *WebServerLDAPSecrets) setFrom(f *WebServerLDAPSecrets) {
+ if v := f.ServerAddress; v != nil {
+ w.ServerAddress = v
+ }
+ if v := f.ReadOnlyUserLogin; v != nil {
+ w.ReadOnlyUserLogin = v
+ }
+ if v := f.ReadOnlyUserPass; v != nil {
+ w.ReadOnlyUserPass = v
+ }
+}
+
+type WebServerSecrets struct {
+ LDAP WebServerLDAPSecrets `toml:",omitempty"`
+}
+
+func (w *WebServerSecrets) SetFrom(f *WebServerSecrets) error {
+ w.LDAP.setFrom(&f.LDAP)
+ return nil
+}
+
type JobPipeline struct {
ExternalInitiatorsEnabled *bool
MaxRunDuration *models.Duration
diff --git a/core/config/web_config.go b/core/config/web_config.go
index 12209a0267..429a31e7e8 100644
--- a/core/config/web_config.go
+++ b/core/config/web_config.go
@@ -32,7 +32,31 @@ type MFA interface {
RPOrigin() string
}
+type LDAP interface {
+ ServerAddress() string
+ ReadOnlyUserLogin() string
+ ReadOnlyUserPass() string
+ ServerTLS() bool
+ SessionTimeout() models.Duration
+ QueryTimeout() time.Duration
+ BaseUserAttr() string
+ BaseDN() string
+ UsersDN() string
+ GroupsDN() string
+ ActiveAttribute() string
+ ActiveAttributeAllowedValue() string
+ AdminUserGroupCN() string
+ EditUserGroupCN() string
+ RunUserGroupCN() string
+ ReadUserGroupCN() string
+ UserApiTokenEnabled() bool
+ UserAPITokenDuration() models.Duration
+ UpstreamSyncInterval() models.Duration
+ UpstreamSyncRateLimit() models.Duration
+}
+
type WebServer interface {
+ AuthenticationMethod() string
AllowOrigins() string
BridgeCacheTTL() time.Duration
BridgeResponseURL() *url.URL
@@ -49,4 +73,5 @@ type WebServer interface {
TLS() TLS
RateLimit() RateLimit
MFA() MFA
+ LDAP() LDAP
}
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index fb4a69cf30..66162aef10 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -628,7 +628,7 @@ func (ta *TestApplication) NewHTTPClient(user *User) HTTPClientCleaner {
u, err := clsessions.NewUser(user.Email, Password, user.Role)
require.NoError(ta.t, err)
- err = ta.SessionORM().CreateUser(&u)
+ err = ta.BasicAdminUsersORM().CreateUser(&u)
require.NoError(ta.t, err)
sessionID := ta.MustSeedNewSession(user.Email)
diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go
index 9fdbcbb373..00f72199dd 100644
--- a/core/internal/cltest/mocks.go
+++ b/core/internal/cltest/mocks.go
@@ -309,7 +309,7 @@ func MustRandomUser(t testing.TB) sessions.User {
return r
}
-func NewUserWithSession(t testing.TB, orm sessions.ORM) sessions.User {
+func NewUserWithSession(t testing.TB, orm sessions.AuthenticationProvider) sessions.User {
u := MustRandomUser(t)
require.NoError(t, orm.CreateUser(&u))
@@ -330,7 +330,7 @@ func NewMockAPIInitializer(t testing.TB) *MockAPIInitializer {
return &MockAPIInitializer{t: t}
}
-func (m *MockAPIInitializer) Initialize(orm sessions.ORM, lggr logger.Logger) (sessions.User, error) {
+func (m *MockAPIInitializer) Initialize(orm sessions.BasicAdminUsersORM, lggr logger.Logger) (sessions.User, error) {
if user, err := orm.FindUser(APIEmailAdmin); err == nil {
return user, err
}
diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go
index 3293066191..23451bf29f 100644
--- a/core/internal/features/features_test.go
+++ b/core/internal/features/features_test.go
@@ -266,7 +266,7 @@ func TestIntegration_AuthToken(t *testing.T) {
mockUser := cltest.MustRandomUser(t)
key, secret := uuid.New().String(), uuid.New().String()
apiToken := auth.Token{AccessKey: key, Secret: secret}
- orm := app.SessionORM()
+ orm := app.AuthenticationProvider()
require.NoError(t, orm.CreateUser(&mockUser))
require.NoError(t, orm.SetAuthToken(&mockUser, &apiToken))
diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go
index ec656509af..7853361db9 100644
--- a/core/internal/mocks/application.go
+++ b/core/internal/mocks/application.go
@@ -63,6 +63,38 @@ func (_m *Application) AddJobV2(ctx context.Context, _a1 *job.Job) error {
return r0
}
+// AuthenticationProvider provides a mock function with given fields:
+func (_m *Application) AuthenticationProvider() sessions.AuthenticationProvider {
+ ret := _m.Called()
+
+ var r0 sessions.AuthenticationProvider
+ if rf, ok := ret.Get(0).(func() sessions.AuthenticationProvider); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(sessions.AuthenticationProvider)
+ }
+ }
+
+ return r0
+}
+
+// BasicAdminUsersORM provides a mock function with given fields:
+func (_m *Application) BasicAdminUsersORM() sessions.BasicAdminUsersORM {
+ ret := _m.Called()
+
+ var r0 sessions.BasicAdminUsersORM
+ if rf, ok := ret.Get(0).(func() sessions.BasicAdminUsersORM); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(sessions.BasicAdminUsersORM)
+ }
+ }
+
+ return r0
+}
+
// BridgeORM provides a mock function with given fields:
func (_m *Application) BridgeORM() bridges.ORM {
ret := _m.Called()
@@ -439,22 +471,6 @@ func (_m *Application) SecretGenerator() chainlink.SecretGenerator {
return r0
}
-// SessionORM provides a mock function with given fields:
-func (_m *Application) SessionORM() sessions.ORM {
- ret := _m.Called()
-
- var r0 sessions.ORM
- if rf, ok := ret.Get(0).(func() sessions.ORM); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(sessions.ORM)
- }
- }
-
- return r0
-}
-
// SetLogLevel provides a mock function with given fields: lvl
func (_m *Application) SetLogLevel(lvl zapcore.Level) error {
ret := _m.Called(lvl)
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 65dcec563e..17c2cff103 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -44,6 +44,7 @@ require (
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
+ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/CosmWasm/wasmd v0.40.1 // indirect
github.com/CosmWasm/wasmvm v1.2.4 // indirect
@@ -119,8 +120,10 @@ require (
github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
+ github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
+ github.com/go-ldap/ldap/v3 v3.4.5 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 781eed46ce..ae1f924c0f 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -79,6 +79,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOv
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -124,6 +126,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
+github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@@ -424,6 +428,8 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
+github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@@ -438,6 +444,8 @@ github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEai
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-ldap/ldap/v3 v3.4.5 h1:ekEKmaDrpvR2yf5Nc/DClsGG9lAmdDixe44mLzlW5r8=
+github.com/go-ldap/ldap/v3 v3.4.5/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
@@ -1745,6 +1753,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1785,6 +1794,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1846,6 +1856,7 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1872,6 +1883,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1975,6 +1987,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1987,6 +2000,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2063,6 +2077,7 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go
index 63a9b2696c..3285acdc07 100644
--- a/core/services/chainlink/application.go
+++ b/core/services/chainlink/application.go
@@ -52,6 +52,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/vrf"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
"github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/plugins"
)
@@ -82,7 +84,8 @@ type Application interface {
EVMORM() evmtypes.Configs
PipelineORM() pipeline.ORM
BridgeORM() bridges.ORM
- SessionORM() sessions.ORM
+ BasicAdminUsersORM() sessions.BasicAdminUsersORM
+ AuthenticationProvider() sessions.AuthenticationProvider
TxmStorageService() txmgr.EvmTxStore
AddJobV2(ctx context.Context, job *job.Job) error
DeleteJob(ctx context.Context, jobID int32) error
@@ -115,7 +118,8 @@ type ChainlinkApplication struct {
pipelineORM pipeline.ORM
pipelineRunner pipeline.Runner
bridgeORM bridges.ORM
- sessionORM sessions.ORM
+ localAdminUsersORM sessions.BasicAdminUsersORM
+ authenticationProvider sessions.AuthenticationProvider
txmStorageService txmgr.EvmTxStore
FeedsService feeds.Service
webhookJobRunner webhook.JobRunner
@@ -245,10 +249,36 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
return nil, fmt.Errorf("no evm chains found")
}
+ // Initialize Local Users ORM and Authentication Provider specified in config
+ // BasicAdminUsersORM is initialized and required regardless of separate Authentication Provider
+ localAdminUsersORM := localauth.NewORM(db, cfg.WebServer().SessionTimeout().Duration(), globalLogger, cfg.Database(), auditLogger)
+
+ // Initialize Sessions ORM based on environment configured authenticator
+ // localDB auth or remote LDAP auth
+ authMethod := cfg.WebServer().AuthenticationMethod()
+ var authenticationProvider sessions.AuthenticationProvider
+ var sessionReaper utils.SleeperTask
+
+ switch sessions.AuthenticationProviderName(authMethod) {
+ case sessions.LDAPAuth:
+ var err error
+ authenticationProvider, err = ldapauth.NewLDAPAuthenticator(
+ db, cfg.Database(), 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(db, cfg.Database(), cfg.WebServer().LDAP(), globalLogger)
+ case sessions.LocalAuth:
+ authenticationProvider = localauth.NewORM(db, cfg.WebServer().SessionTimeout().Duration(), globalLogger, cfg.Database(), auditLogger)
+ sessionReaper = localauth.NewSessionReaper(db.DB, 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(db, globalLogger, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns())
bridgeORM = bridges.NewORM(db, globalLogger, cfg.Database())
- sessionORM = sessions.NewORM(db, cfg.WebServer().SessionTimeout().Duration(), globalLogger, cfg.Database(), auditLogger)
mercuryORM = mercury.NewORM(db, globalLogger, cfg.Database())
pipelineRunner = pipeline.NewRunner(pipelineORM, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyEVMChains, keyStore.Eth(), keyStore.VRF(), globalLogger, restrictedHTTPClient, unrestrictedHTTPClient)
jobORM = job.NewORM(db, pipelineORM, bridgeORM, keyStore, globalLogger, cfg.Database())
@@ -440,13 +470,14 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
pipelineRunner: pipelineRunner,
pipelineORM: pipelineORM,
bridgeORM: bridgeORM,
- sessionORM: sessionORM,
+ localAdminUsersORM: localAdminUsersORM,
+ authenticationProvider: authenticationProvider,
txmStorageService: txmORM,
FeedsService: feedsService,
Config: cfg,
webhookJobRunner: webhookJobRunner,
KeyStore: keyStore,
- SessionReaper: sessions.NewSessionReaper(db.DB, cfg.WebServer(), globalLogger),
+ SessionReaper: sessionReaper,
ExternalInitiatorManager: externalInitiatorManager,
HealthChecker: healthChecker,
Nurse: nurse,
@@ -612,8 +643,12 @@ func (app *ChainlinkApplication) BridgeORM() bridges.ORM {
return app.bridgeORM
}
-func (app *ChainlinkApplication) SessionORM() sessions.ORM {
- return app.sessionORM
+func (app *ChainlinkApplication) BasicAdminUsersORM() sessions.BasicAdminUsersORM {
+ return app.localAdminUsersORM
+}
+
+func (app *ChainlinkApplication) AuthenticationProvider() sessions.AuthenticationProvider {
+ return app.authenticationProvider
}
// TODO BCF-2516 remove this all together remove EVM specifics
diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go
index 3f55a2dc00..10598718f9 100644
--- a/core/services/chainlink/config.go
+++ b/core/services/chainlink/config.go
@@ -168,28 +168,32 @@ type Secrets struct {
}
func (s *Secrets) SetFrom(f *Secrets) (err error) {
- if err1 := s.Database.SetFrom(&f.Database); err1 != nil {
- err = multierr.Append(err, config.NamedMultiErrorList(err1, "Database"))
+ if err2 := s.Database.SetFrom(&f.Database); err2 != nil {
+ err = multierr.Append(err, config.NamedMultiErrorList(err2, "Database"))
}
if err2 := s.Password.SetFrom(&f.Password); err2 != nil {
err = multierr.Append(err, config.NamedMultiErrorList(err2, "Password"))
}
- if err3 := s.Pyroscope.SetFrom(&f.Pyroscope); err3 != nil {
- err = multierr.Append(err, config.NamedMultiErrorList(err3, "Pyroscope"))
+ if err2 := s.WebServer.SetFrom(&f.WebServer); err2 != nil {
+ err = multierr.Append(err, config.NamedMultiErrorList(err2, "WebServer"))
}
- if err4 := s.Prometheus.SetFrom(&f.Prometheus); err4 != nil {
- err = multierr.Append(err, config.NamedMultiErrorList(err4, "Prometheus"))
+ if err2 := s.Pyroscope.SetFrom(&f.Pyroscope); err2 != nil {
+ err = multierr.Append(err, config.NamedMultiErrorList(err2, "Pyroscope"))
}
- if err5 := s.Mercury.SetFrom(&f.Mercury); err5 != nil {
- err = multierr.Append(err, config.NamedMultiErrorList(err5, "Mercury"))
+ if err2 := s.Prometheus.SetFrom(&f.Prometheus); err2 != nil {
+ err = multierr.Append(err, config.NamedMultiErrorList(err2, "Prometheus"))
}
- if err6 := s.Threshold.SetFrom(&f.Threshold); err6 != nil {
- err = multierr.Append(err, config.NamedMultiErrorList(err6, "Threshold"))
+ if err2 := s.Mercury.SetFrom(&f.Mercury); err2 != nil {
+ err = multierr.Append(err, config.NamedMultiErrorList(err2, "Mercury"))
+ }
+
+ if err2 := s.Threshold.SetFrom(&f.Threshold); err2 != nil {
+ err = multierr.Append(err, config.NamedMultiErrorList(err2, "Threshold"))
}
_, err = utils.MultiErrorList(err)
diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go
index 81e3883335..6a835e09c8 100644
--- a/core/services/chainlink/config_general.go
+++ b/core/services/chainlink/config_general.go
@@ -348,7 +348,7 @@ func (g *generalConfig) StarkNetEnabled() bool {
}
func (g *generalConfig) WebServer() config.WebServer {
- return &webServerConfig{c: g.c.WebServer, rootDir: g.RootDir}
+ return &webServerConfig{c: g.c.WebServer, s: g.secrets.WebServer, rootDir: g.RootDir}
}
func (g *generalConfig) AutoPprofBlockProfileRate() int {
diff --git a/core/services/chainlink/config_general_test.go b/core/services/chainlink/config_general_test.go
index 46931e53e2..c122f8f968 100644
--- a/core/services/chainlink/config_general_test.go
+++ b/core/services/chainlink/config_general_test.go
@@ -149,6 +149,9 @@ var mercurySecretsTOMLSplitTwo string
//go:embed testdata/mergingsecretsdata/secrets-threshold.toml
var thresholdSecretsTOML string
+//go:embed testdata/mergingsecretsdata/secrets-webserver-ldap.toml
+var WebServerLDAPSecretsTOML string
+
func TestConfig_SecretsMerging(t *testing.T) {
t.Run("verify secrets merging in GeneralConfigOpts.New()", func(t *testing.T) {
databaseSecrets, err := parseSecrets(databaseSecretsTOML)
@@ -165,6 +168,8 @@ func TestConfig_SecretsMerging(t *testing.T) {
require.NoErrorf(t, err6, "error: %s", err6)
thresholdSecrets, err7 := parseSecrets(thresholdSecretsTOML)
require.NoErrorf(t, err7, "error: %s", err7)
+ webserverLDAPSecrets, err8 := parseSecrets(WebServerLDAPSecretsTOML)
+ require.NoErrorf(t, err8, "error: %s", err8)
opts := new(GeneralConfigOpts)
configFiles := []string{
@@ -178,6 +183,7 @@ func TestConfig_SecretsMerging(t *testing.T) {
"testdata/mergingsecretsdata/secrets-mercury-split-one.toml",
"testdata/mergingsecretsdata/secrets-mercury-split-two.toml",
"testdata/mergingsecretsdata/secrets-threshold.toml",
+ "testdata/mergingsecretsdata/secrets-webserver-ldap.toml",
}
err = opts.Setup(configFiles, secretsFiles)
require.NoErrorf(t, err, "error: %s", err)
@@ -194,6 +200,10 @@ func TestConfig_SecretsMerging(t *testing.T) {
assert.Equal(t, (string)(*prometheusSecrets.Prometheus.AuthToken), (string)(*opts.Secrets.Prometheus.AuthToken))
assert.Equal(t, (string)(*thresholdSecrets.Threshold.ThresholdKeyShare), (string)(*opts.Secrets.Threshold.ThresholdKeyShare))
+ assert.Equal(t, webserverLDAPSecrets.WebServer.LDAP.ServerAddress.URL().String(), opts.Secrets.WebServer.LDAP.ServerAddress.URL().String())
+ assert.Equal(t, webserverLDAPSecrets.WebServer.LDAP.ReadOnlyUserLogin, opts.Secrets.WebServer.LDAP.ReadOnlyUserLogin)
+ assert.Equal(t, webserverLDAPSecrets.WebServer.LDAP.ReadOnlyUserPass, opts.Secrets.WebServer.LDAP.ReadOnlyUserPass)
+
err = assertDeepEqualityMercurySecrets(*merge(mercurySecrets_a.Mercury, mercurySecrets_b.Mercury), opts.Secrets.Mercury)
require.NoErrorf(t, err, "merged mercury secrets unequal")
})
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 986b98d936..96e6db42c8 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -308,6 +308,7 @@ func TestConfig_Marshal(t *testing.T) {
},
}
full.WebServer = toml.WebServer{
+ AuthenticationMethod: ptr("local"),
AllowOrigins: ptr("*"),
BridgeResponseURL: mustURL("https://bridge.response"),
BridgeCacheTTL: models.MustNewDuration(10 * time.Second),
@@ -323,6 +324,25 @@ func TestConfig_Marshal(t *testing.T) {
RPID: ptr("test-rpid"),
RPOrigin: ptr("test-rp-origin"),
},
+ LDAP: toml.WebServerLDAP{
+ ServerTLS: ptr(true),
+ SessionTimeout: models.MustNewDuration(15 * time.Minute),
+ QueryTimeout: models.MustNewDuration(2 * time.Minute),
+ BaseUserAttr: ptr("uid"),
+ BaseDN: ptr("dc=custom,dc=example,dc=com"),
+ UsersDN: ptr("ou=users"),
+ GroupsDN: ptr("ou=groups"),
+ ActiveAttribute: ptr("organizationalStatus"),
+ ActiveAttributeAllowedValue: ptr("ACTIVE"),
+ AdminUserGroupCN: ptr("NodeAdmins"),
+ EditUserGroupCN: ptr("NodeEditors"),
+ RunUserGroupCN: ptr("NodeRunners"),
+ ReadUserGroupCN: ptr("NodeReadOnly"),
+ UserApiTokenEnabled: ptr(false),
+ UserAPITokenDuration: models.MustNewDuration(240 * time.Hour),
+ UpstreamSyncInterval: models.MustNewDuration(0 * time.Second),
+ UpstreamSyncRateLimit: models.MustNewDuration(2 * time.Minute),
+ },
RateLimit: toml.WebServerRateLimit{
Authenticated: ptr[int64](42),
AuthenticatedPeriod: models.MustNewDuration(time.Second),
@@ -738,6 +758,7 @@ MaxAgeDays = 17
MaxBackups = 9
`},
{"WebServer", Config{Core: toml.Core{WebServer: full.WebServer}}, `[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = '*'
BridgeResponseURL = 'https://bridge.response'
BridgeCacheTTL = '10s'
@@ -750,6 +771,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '192.158.1.37'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = 'dc=custom,dc=example,dc=com'
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = 'organizationalStatus'
+ActiveAttributeAllowedValue = 'ACTIVE'
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = 'test-rpid'
RPOrigin = 'test-rp-origin'
@@ -1118,8 +1158,17 @@ func TestConfig_Validate(t *testing.T) {
toml string
exp string
}{
- {name: "invalid", toml: invalidTOML, exp: `invalid configuration: 5 errors:
+ {name: "invalid", toml: invalidTOML, exp: `invalid configuration: 6 errors:
- Database.Lock.LeaseRefreshInterval: invalid value (6s): must be less than or equal to half of LeaseDuration (10s)
+ - WebServer: 8 errors:
+ - LDAP.BaseDN: invalid value (): LDAP BaseDN can not be empty
+ - LDAP.BaseUserAttr: invalid value (): LDAP BaseUserAttr can not be empty
+ - LDAP.UsersDN: invalid value (): LDAP UsersDN can not be empty
+ - LDAP.GroupsDN: invalid value (): LDAP GroupsDN can not be empty
+ - LDAP.AdminUserGroupCN: invalid value (): LDAP AdminUserGroupCN can not be empty
+ - LDAP.RunUserGroupCN: invalid value (): LDAP ReadUserGroupCN can not be empty
+ - LDAP.RunUserGroupCN: invalid value (): LDAP RunUserGroupCN can not be empty
+ - LDAP.ReadUserGroupCN: invalid value (): LDAP ReadUserGroupCN can not be empty
- EVM: 8 errors:
- 1.ChainID: invalid value (1): duplicate - must be unique
- 0.Nodes.1.Name: invalid value (foo): duplicate - must be unique
diff --git a/core/services/chainlink/config_web_server.go b/core/services/chainlink/config_web_server.go
index a931d67f38..06db398e2e 100644
--- a/core/services/chainlink/config_web_server.go
+++ b/core/services/chainlink/config_web_server.go
@@ -98,6 +98,7 @@ func (m *mfaConfig) RPOrigin() string {
type webServerConfig struct {
c toml.WebServer
+ s toml.WebServerSecrets
rootDir func() string
}
@@ -113,6 +114,14 @@ func (w *webServerConfig) MFA() config.MFA {
return &mfaConfig{c: w.c.MFA}
}
+func (w *webServerConfig) LDAP() config.LDAP {
+ return &ldapConfig{c: w.c.LDAP, s: w.s.LDAP}
+}
+
+func (w *webServerConfig) AuthenticationMethod() string {
+ return *w.c.AuthenticationMethod
+}
+
func (w *webServerConfig) AllowOrigins() string {
return *w.c.AllowOrigins
}
@@ -168,3 +177,139 @@ func (w *webServerConfig) SessionTimeout() models.Duration {
func (w *webServerConfig) ListenIP() net.IP {
return *w.c.ListenIP
}
+
+type ldapConfig struct {
+ c toml.WebServerLDAP
+ s toml.WebServerLDAPSecrets
+}
+
+func (l *ldapConfig) ServerAddress() string {
+ if l.s.ServerAddress == nil {
+ return ""
+ }
+ return l.s.ServerAddress.URL().String()
+}
+
+func (l *ldapConfig) ReadOnlyUserLogin() string {
+ if l.s.ReadOnlyUserLogin == nil {
+ return ""
+ }
+ return string(*l.s.ReadOnlyUserLogin)
+}
+
+func (l *ldapConfig) ReadOnlyUserPass() string {
+ if l.s.ReadOnlyUserPass == nil {
+ return ""
+ }
+ return string(*l.s.ReadOnlyUserPass)
+}
+
+func (l *ldapConfig) ServerTLS() bool {
+ if l.c.ServerTLS == nil {
+ return false
+ }
+ return *l.c.ServerTLS
+}
+
+func (l *ldapConfig) SessionTimeout() models.Duration {
+ return *l.c.SessionTimeout
+}
+
+func (l *ldapConfig) QueryTimeout() time.Duration {
+ return l.c.QueryTimeout.Duration()
+}
+
+func (l *ldapConfig) UserAPITokenDuration() models.Duration {
+ return *l.c.UserAPITokenDuration
+}
+
+func (l *ldapConfig) BaseUserAttr() string {
+ if l.c.BaseUserAttr == nil {
+ return ""
+ }
+ return *l.c.BaseUserAttr
+}
+
+func (l *ldapConfig) BaseDN() string {
+ if l.c.BaseDN == nil {
+ return ""
+ }
+ return *l.c.BaseDN
+}
+
+func (l *ldapConfig) UsersDN() string {
+ if l.c.UsersDN == nil {
+ return ""
+ }
+ return *l.c.UsersDN
+}
+
+func (l *ldapConfig) GroupsDN() string {
+ if l.c.GroupsDN == nil {
+ return ""
+ }
+ return *l.c.GroupsDN
+}
+
+func (l *ldapConfig) ActiveAttribute() string {
+ if l.c.ActiveAttribute == nil {
+ return ""
+ }
+ return *l.c.ActiveAttribute
+}
+
+func (l *ldapConfig) ActiveAttributeAllowedValue() string {
+ if l.c.ActiveAttributeAllowedValue == nil {
+ return ""
+ }
+ return *l.c.ActiveAttributeAllowedValue
+}
+
+func (l *ldapConfig) AdminUserGroupCN() string {
+ if l.c.AdminUserGroupCN == nil {
+ return ""
+ }
+ return *l.c.AdminUserGroupCN
+}
+
+func (l *ldapConfig) EditUserGroupCN() string {
+ if l.c.EditUserGroupCN == nil {
+ return ""
+ }
+ return *l.c.EditUserGroupCN
+}
+
+func (l *ldapConfig) RunUserGroupCN() string {
+ if l.c.RunUserGroupCN == nil {
+ return ""
+ }
+ return *l.c.RunUserGroupCN
+}
+
+func (l *ldapConfig) ReadUserGroupCN() string {
+ if l.c.ReadUserGroupCN == nil {
+ return ""
+ }
+ return *l.c.ReadUserGroupCN
+}
+
+func (l *ldapConfig) UserApiTokenEnabled() bool {
+ if l.c.UserApiTokenEnabled == nil {
+ return false
+ }
+ return *l.c.UserApiTokenEnabled
+}
+
+func (l *ldapConfig) UpstreamSyncInterval() models.Duration {
+ if l.c.UpstreamSyncInterval == nil {
+ return models.Duration{}
+ }
+ return *l.c.UpstreamSyncInterval
+}
+
+func (l *ldapConfig) UpstreamSyncRateLimit() models.Duration {
+ if l.c.UpstreamSyncRateLimit == nil {
+ return models.Duration{}
+ }
+ return *l.c.UpstreamSyncRateLimit
+}
diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml
index 48d432138a..f5d775fe74 100644
--- a/core/services/chainlink/testdata/config-empty-effective.toml
+++ b/core/services/chainlink/testdata/config-empty-effective.toml
@@ -61,6 +61,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -73,6 +74,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml
index 7ce0d185b1..5ede10ef69 100644
--- a/core/services/chainlink/testdata/config-full.toml
+++ b/core/services/chainlink/testdata/config-full.toml
@@ -67,6 +67,7 @@ MaxAgeDays = 17
MaxBackups = 9
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = '*'
BridgeResponseURL = 'https://bridge.response'
BridgeCacheTTL = '10s'
@@ -79,6 +80,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '192.158.1.37'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = 'dc=custom,dc=example,dc=com'
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = 'organizationalStatus'
+ActiveAttributeAllowedValue = 'ACTIVE'
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = 'test-rpid'
RPOrigin = 'test-rp-origin'
diff --git a/core/services/chainlink/testdata/config-invalid.toml b/core/services/chainlink/testdata/config-invalid.toml
index 3b7e89299f..4d8c9bc29a 100644
--- a/core/services/chainlink/testdata/config-invalid.toml
+++ b/core/services/chainlink/testdata/config-invalid.toml
@@ -2,6 +2,28 @@
LeaseRefreshInterval='6s'
LeaseDuration='10s'
+[WebServer]
+AuthenticationMethod = 'ldap'
+
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = ''
+BaseDN = ''
+UsersDN = ''
+GroupsDN = ''
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = ''
+EditUserGroupCN = ''
+RunUserGroupCN = ''
+ReadUserGroupCN = ''
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[[EVM]]
ChainID = '1'
Transactions.MaxInFlight= 10
diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml
index 1dcbfe3a83..9dd0be8f5d 100644
--- a/core/services/chainlink/testdata/config-multi-chain-effective.toml
+++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml
@@ -61,6 +61,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -73,6 +74,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/core/services/chainlink/testdata/mergingsecretsdata/secrets-webserver-ldap.toml b/core/services/chainlink/testdata/mergingsecretsdata/secrets-webserver-ldap.toml
new file mode 100644
index 0000000000..f73efcff0c
--- /dev/null
+++ b/core/services/chainlink/testdata/mergingsecretsdata/secrets-webserver-ldap.toml
@@ -0,0 +1,4 @@
+[WebServer.LDAP]
+ServerAddress = 'ldaps://127.0.0.1'
+ReadOnlyUserLogin = 'viewer@example.com'
+ReadOnlyUserPass = 'password'
\ No newline at end of file
diff --git a/core/services/chainlink/testdata/secrets-full-redacted.toml b/core/services/chainlink/testdata/secrets-full-redacted.toml
index 740c3250ed..9d91d79cb5 100644
--- a/core/services/chainlink/testdata/secrets-full-redacted.toml
+++ b/core/services/chainlink/testdata/secrets-full-redacted.toml
@@ -7,6 +7,12 @@ AllowSimplePasswords = false
Keystore = 'xxxxx'
VRF = 'xxxxx'
+[WebServer]
+[WebServer.LDAP]
+ServerAddress = 'xxxxx'
+ReadOnlyUserLogin = 'xxxxx'
+ReadOnlyUserPass = 'xxxxx'
+
[Pyroscope]
AuthToken = 'xxxxx'
diff --git a/core/services/chainlink/testdata/secrets-full.toml b/core/services/chainlink/testdata/secrets-full.toml
index 37e5dafc7d..37a3e2e7dc 100644
--- a/core/services/chainlink/testdata/secrets-full.toml
+++ b/core/services/chainlink/testdata/secrets-full.toml
@@ -6,6 +6,12 @@ BackupURL = "postgresql://user:pass@localhost:5432/backupdbname?sslmode=disable"
Keystore = "keystore_pass"
VRF = "VRF_pass"
+[WebServer]
+[WebServer.LDAP]
+ServerAddress = 'ldaps://127.0.0.1'
+ReadOnlyUserLogin = 'viewer@example.com'
+ReadOnlyUserPass = 'password'
+
[Pyroscope]
AuthToken = "pyroscope-token"
diff --git a/core/sessions/authentication.go b/core/sessions/authentication.go
new file mode 100644
index 0000000000..0f0dda3bf3
--- /dev/null
+++ b/core/sessions/authentication.go
@@ -0,0 +1,66 @@
+package sessions
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/smartcontractkit/chainlink/v2/core/auth"
+ "github.com/smartcontractkit/chainlink/v2/core/bridges"
+)
+
+// Application config constant options
+type AuthenticationProviderName string
+
+const (
+ LocalAuth AuthenticationProviderName = "local"
+ LDAPAuth AuthenticationProviderName = "ldap"
+)
+
+// ErrUserSessionExpired defines the error triggered when the user session has expired
+var ErrUserSessionExpired = errors.New("session missing or expired, please login again")
+
+// ErrNotSupported defines the error where interface functionality doesn't align with the underlying Auth Provider
+var ErrNotSupported = fmt.Errorf("functionality not supported with current authentication provider: %w", errors.ErrUnsupported)
+
+// ErrEmptySessionID captures the empty case error message
+var ErrEmptySessionID = errors.New("session ID cannot be empty")
+
+//go:generate mockery --quiet --name BasicAdminUsersORM --output ./mocks/ --case=underscore
+
+// BasicAdminUsersORM is the interface that defines the functionality required for supporting basic admin functionality
+// adjacent to the identity provider authentication provider implementation. It is currently implemented by the local
+// users/sessions ORM containing local admin CLI actions. This is separate from the AuthenticationProvider,
+// as local admin management (ie initial core node setup, initial admin user creation), is always
+// required no matter what the pluggable AuthenticationProvider implementation is.
+type BasicAdminUsersORM interface {
+ ListUsers() ([]User, error)
+ CreateUser(user *User) error
+ FindUser(email string) (User, error)
+}
+
+//go:generate mockery --quiet --name AuthenticationProvider --output ./mocks/ --case=underscore
+
+// AuthenticationProvider is an interface that abstracts the required application calls to a user management backend
+// Currently localauth (users table DB) or LDAP server (readonly)
+type AuthenticationProvider interface {
+ FindUser(email string) (User, error)
+ FindUserByAPIToken(apiToken string) (User, error)
+ ListUsers() ([]User, error)
+ AuthorizedUserWithSession(sessionID string) (User, error)
+ DeleteUser(email string) error
+ DeleteUserSession(sessionID string) error
+ CreateSession(sr SessionRequest) (string, error)
+ ClearNonCurrentSessions(sessionID string) error
+ CreateUser(user *User) error
+ UpdateRole(email, newRole string) (User, error)
+ SetAuthToken(user *User, token *auth.Token) error
+ CreateAndSetAuthToken(user *User) (*auth.Token, error)
+ DeleteAuthToken(user *User) error
+ SetPassword(user *User, newPassword string) error
+ TestPassword(email, password string) error
+ Sessions(offset, limit int) ([]Session, error)
+ GetUserWebAuthn(email string) ([]WebAuthn, error)
+ SaveWebAuthn(token *WebAuthn) error
+
+ FindExternalInitiator(eia *auth.Token) (initiator *bridges.ExternalInitiator, err error)
+}
diff --git a/core/sessions/ldapauth/client.go b/core/sessions/ldapauth/client.go
new file mode 100644
index 0000000000..bb259f8c9a
--- /dev/null
+++ b/core/sessions/ldapauth/client.go
@@ -0,0 +1,47 @@
+package ldapauth
+
+import (
+ "fmt"
+
+ "github.com/go-ldap/ldap/v3"
+
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+)
+
+type ldapClient struct {
+ config config.LDAP
+}
+
+//go:generate mockery --quiet --name LDAPClient --output ./mocks/ --case=underscore
+
+// Wrapper for creating a handle to a *ldap.Conn/LDAPConn interface
+type LDAPClient interface {
+ CreateEphemeralConnection() (LDAPConn, error)
+}
+
+//go:generate mockery --quiet --name LDAPConn --output ./mocks/ --case=underscore
+
+// Wrapper for ldap connection and mock testing, implemented by *ldap.Conn
+type LDAPConn interface {
+ Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error)
+ Bind(username string, password string) error
+ Close() (err error)
+}
+
+func newLDAPClient(config config.LDAP) LDAPClient {
+ return &ldapClient{config}
+}
+
+// CreateEphemeralConnection returns a valid, active LDAP connection for upstream Search and Bind queries
+func (l *ldapClient) CreateEphemeralConnection() (LDAPConn, error) {
+ conn, err := ldap.DialURL(l.config.ServerAddress())
+ if err != nil {
+ return nil, fmt.Errorf("failed to Dial LDAP Server: %w", err)
+ }
+ // Root level root user auth with credentials provided from config
+ bindStr := l.config.BaseUserAttr() + "=" + l.config.ReadOnlyUserLogin() + "," + l.config.BaseDN()
+ if err := conn.Bind(bindStr, l.config.ReadOnlyUserPass()); err != nil {
+ return nil, fmt.Errorf("unable to login as initial root LDAP user: %w", err)
+ }
+ return conn, nil
+}
diff --git a/core/sessions/ldapauth/helpers_test.go b/core/sessions/ldapauth/helpers_test.go
new file mode 100644
index 0000000000..c554d5436e
--- /dev/null
+++ b/core/sessions/ldapauth/helpers_test.go
@@ -0,0 +1,131 @@
+package ldapauth
+
+import (
+ "time"
+
+ "github.com/smartcontractkit/sqlx"
+
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/logger/audit"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/smartcontractkit/chainlink/v2/core/store/models"
+)
+
+// Returns an instantiated ldapAuthenticator struct without validation for testing
+func NewTestLDAPAuthenticator(
+ db *sqlx.DB,
+ pgCfg pg.QConfig,
+ ldapCfg config.LDAP,
+ dev bool,
+ lggr logger.Logger,
+ auditLogger audit.AuditLogger,
+) (*ldapAuthenticator, error) {
+ namedLogger := lggr.Named("LDAPAuthenticationProvider")
+ ldapAuth := ldapAuthenticator{
+ q: pg.NewQ(db, namedLogger, pgCfg),
+ ldapClient: newLDAPClient(ldapCfg),
+ config: ldapCfg,
+ lggr: lggr.Named("LDAPAuthenticationProvider"),
+ auditLogger: auditLogger,
+ }
+
+ return &ldapAuth, nil
+}
+
+// Default server group name mappings for test config and mocked ldap search results
+const (
+ NodeAdminsGroupCN = "NodeAdmins"
+ NodeEditorsGroupCN = "NodeEditors"
+ NodeRunnersGroupCN = "NodeRunners"
+ NodeReadOnlyGroupCN = "NodeReadOnly"
+)
+
+// Implement a setter function within the _test file so that the ldapauth_test module can set the unexported field with a mock
+func (l *ldapAuthenticator) SetLDAPClient(newClient LDAPClient) {
+ l.ldapClient = newClient
+}
+
+// Implements config.LDAP
+type TestConfig struct {
+}
+
+func (t *TestConfig) ServerAddress() string {
+ return "ldaps://MOCK"
+}
+
+func (t *TestConfig) ReadOnlyUserLogin() string {
+ return "mock-readonly"
+}
+
+func (t *TestConfig) ReadOnlyUserPass() string {
+ return "mock-password"
+}
+
+func (t *TestConfig) ServerTLS() bool {
+ return false
+}
+
+func (t *TestConfig) SessionTimeout() models.Duration {
+ return models.MustMakeDuration(time.Duration(0))
+}
+
+func (t *TestConfig) QueryTimeout() time.Duration {
+ return time.Duration(0)
+}
+
+func (t *TestConfig) UserAPITokenDuration() models.Duration {
+ return models.MustMakeDuration(time.Duration(0))
+}
+
+func (t *TestConfig) BaseUserAttr() string {
+ return "uid"
+}
+
+func (t *TestConfig) BaseDN() string {
+ return "dc=custom,dc=example,dc=com"
+}
+
+func (t *TestConfig) UsersDN() string {
+ return "ou=users"
+}
+
+func (t *TestConfig) GroupsDN() string {
+ return "ou=groups"
+}
+
+func (t *TestConfig) ActiveAttribute() string {
+ return "organizationalStatus"
+}
+
+func (t *TestConfig) ActiveAttributeAllowedValue() string {
+ return "ACTIVE"
+}
+
+func (t *TestConfig) AdminUserGroupCN() string {
+ return NodeAdminsGroupCN
+}
+
+func (t *TestConfig) EditUserGroupCN() string {
+ return NodeEditorsGroupCN
+}
+
+func (t *TestConfig) RunUserGroupCN() string {
+ return NodeRunnersGroupCN
+}
+
+func (t *TestConfig) ReadUserGroupCN() string {
+ return NodeReadOnlyGroupCN
+}
+
+func (t *TestConfig) UserApiTokenEnabled() bool {
+ return true
+}
+
+func (t *TestConfig) UpstreamSyncInterval() models.Duration {
+ return models.MustMakeDuration(time.Duration(0))
+}
+
+func (t *TestConfig) UpstreamSyncRateLimit() models.Duration {
+ return models.MustMakeDuration(time.Duration(0))
+}
diff --git a/core/sessions/ldapauth/ldap.go b/core/sessions/ldapauth/ldap.go
new file mode 100644
index 0000000000..188f2684e7
--- /dev/null
+++ b/core/sessions/ldapauth/ldap.go
@@ -0,0 +1,858 @@
+/*
+The LDAP authentication package forwards the credentials in the user session request
+for authentication with a configured upstream LDAP server
+
+This package relies on the two following local database tables:
+
+ ldap_sessions: Upon successful LDAP response, creates a keyed local copy of the user email
+ ldap_user_api_tokens: User created API tokens, tied to the node, storing user email.
+
+Note: user can have only one API token at a time, and token expiration is enforced
+
+User session and roles are cached and revalidated with the upstream service at the interval defined in
+the local LDAP config through the Application.sessionReaper implementation in reaper.go.
+
+Changes to the upstream identity server will propagate through and update local tables (web sessions, API tokens)
+by either removing the entries or updating the roles. This sync happens for every auth endpoint hit, and
+via the defined sync interval. One goroutine is created to coordinate the sync timing in the New function
+
+This implementation is read only; user mutation actions such as Delete are not supported.
+
+MFA is supported via the remote LDAP server implementation. Sufficient request time out should accommodate
+for a blocking auth call while the user responds to a potential push notification callback.
+*/
+package ldapauth
+
+import (
+ "crypto/subtle"
+ "database/sql"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/go-ldap/ldap/v3"
+ "github.com/smartcontractkit/sqlx"
+
+ "github.com/smartcontractkit/chainlink/v2/core/auth"
+ "github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/logger/audit"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+ "github.com/smartcontractkit/chainlink/v2/core/utils/mathutil"
+)
+
+const (
+ UniqueMemberAttribute = "uniqueMember"
+)
+
+var ErrUserNotInUpstream = errors.New("LDAP query returned no matching users")
+var ErrUserNoLDAPGroups = errors.New("user present in directory, but matching no role groups assigned")
+
+type ldapAuthenticator struct {
+ q pg.Q
+ ldapClient LDAPClient
+ config config.LDAP
+ lggr logger.Logger
+ auditLogger audit.AuditLogger
+}
+
+// ldapAuthenticator implements sessions.AuthenticationProvider interface
+var _ sessions.AuthenticationProvider = (*ldapAuthenticator)(nil)
+
+func NewLDAPAuthenticator(
+ db *sqlx.DB,
+ pgCfg pg.QConfig,
+ ldapCfg config.LDAP,
+ dev bool,
+ lggr logger.Logger,
+ auditLogger audit.AuditLogger,
+) (*ldapAuthenticator, error) {
+ namedLogger := lggr.Named("LDAPAuthenticationProvider")
+
+ // If not chainlink dev and not tls, error
+ if !dev && !ldapCfg.ServerTLS() {
+ return nil, errors.New("LDAP Authentication driver requires TLS when running in Production mode")
+ }
+
+ // Ensure all RBAC role mappings to LDAP Groups are defined, and required fields populated, or error on startup
+ if ldapCfg.AdminUserGroupCN() == "" || ldapCfg.EditUserGroupCN() == "" ||
+ ldapCfg.RunUserGroupCN() == "" || ldapCfg.ReadUserGroupCN() == "" {
+ return nil, errors.New("LDAP Group mapping from server group name for all local RBAC role required. Set group names for `_UserGroupCN` fields")
+ }
+ if ldapCfg.ServerAddress() == "" {
+ return nil, errors.New("LDAP ServerAddress config required")
+ }
+ if ldapCfg.ReadOnlyUserLogin() == "" {
+ return nil, errors.New("LDAP ReadOnlyUserLogin config required")
+ }
+
+ ldapAuth := ldapAuthenticator{
+ q: pg.NewQ(db, namedLogger, pgCfg),
+ ldapClient: newLDAPClient(ldapCfg),
+ config: ldapCfg,
+ lggr: lggr.Named("LDAPAuthenticationProvider"),
+ auditLogger: auditLogger,
+ }
+
+ // Single override of library defined global
+ ldap.DefaultTimeout = ldapCfg.QueryTimeout()
+
+ // Test initial connection and credentials
+ lggr.Infof("Attempting initial connection to configured LDAP server with bind as API user")
+ conn, err := ldapAuth.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ return nil, fmt.Errorf("unable to establish connection to LDAP server with provided URL and credentials: %w", err)
+ }
+ conn.Close()
+
+ // Store LDAP connection config for auth/new connection per request instead of persisted connection with reconnect
+ return &ldapAuth, nil
+}
+
+// FindUser will attempt to return an LDAP user with mapped role by email.
+func (l *ldapAuthenticator) FindUser(email string) (sessions.User, error) {
+ email = strings.ToLower(email)
+ foundUser := sessions.User{}
+
+ // First check for the supported local admin users table
+ var foundLocalAdminUser sessions.User
+ checkErr := l.q.Transaction(func(tx pg.Queryer) error {
+ sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
+ return tx.Get(&foundLocalAdminUser, sql, email)
+ })
+ if checkErr != nil {
+ // If error is not nil, there was either an issue or no local users found
+ if !errors.Is(checkErr, sql.ErrNoRows) {
+ // If the error is not that no local user was found, log and exit
+ l.lggr.Errorf("error searching users table: %v", checkErr)
+ return sessions.User{}, errors.New("error Finding user")
+ }
+ } else {
+ // Error was nil, local user found. Return
+ return foundLocalAdminUser, nil
+ }
+
+ // First query for user "is active" property if defined
+ usersActive, err := l.validateUsersActive([]string{email})
+ if err != nil {
+ if errors.Is(err, ErrUserNotInUpstream) {
+ return foundUser, ErrUserNotInUpstream
+ }
+ l.lggr.Errorf("error in validateUsers call: %v", err)
+ return foundUser, errors.New("error running query to validate user active")
+ }
+ if !usersActive[0] {
+ return foundUser, errors.New("user not active")
+ }
+
+ conn, err := l.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ l.lggr.Errorf("error in LDAP dial: ", err)
+ return foundUser, errors.New("unable to establish connection to LDAP server with provided URL and credentials")
+ }
+ defer conn.Close()
+
+ // User email and role are the only upstream data that needs queried for.
+ // List query user groups using the provided email, on success is a list of group the uniquemember belongs to
+ // data is readily available
+ escapedEmail := ldap.EscapeFilter(email)
+ searchBaseDN := fmt.Sprintf("%s, %s", l.config.GroupsDN(), l.config.BaseDN())
+ filterQuery := fmt.Sprintf("(&(uniquemember=%s=%s,%s,%s))", l.config.BaseUserAttr(), escapedEmail, l.config.UsersDN(), l.config.BaseDN())
+ searchRequest := ldap.NewSearchRequest(
+ searchBaseDN,
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
+ 0, int(l.config.QueryTimeout().Seconds()), false,
+ filterQuery,
+ []string{"cn"},
+ nil,
+ )
+
+ // Query the server
+ result, err := conn.Search(searchRequest)
+ if err != nil {
+ l.lggr.Errorf("error searching users in LDAP query: %v", err)
+ return foundUser, errors.New("error searching users in LDAP directory")
+ }
+
+ if len(result.Entries) == 0 {
+ // Provided email is not present in upstream LDAP server, local admin CLI auth is supported
+ // So query and check the users table as well before failing
+ if err = l.q.Transaction(func(tx pg.Queryer) error {
+ var localUserRole sessions.UserRole
+ if err = tx.Get(&localUserRole, "SELECT role FROM users WHERE email = $1", email); err != nil {
+ return err
+ }
+ foundUser = sessions.User{
+ Email: email,
+ Role: localUserRole,
+ }
+ return nil
+ }); err != nil {
+ // Above query for local user unsuccessful, return error
+ l.lggr.Warnf("No local users table user found with email %s", email)
+ return foundUser, errors.New("no users found with provided email")
+ }
+
+ // If the above query to the local users table was successful, return that local user's role
+ return foundUser, nil
+ }
+
+ // Populate found user by email and role based on matched group names
+ userRole, err := l.groupSearchResultsToUserRole(result.Entries)
+ if err != nil {
+ l.lggr.Warnf("User '%s' found but no matching assigned groups in LDAP to assume role", email)
+ return sessions.User{}, err
+ }
+
+ // Convert search result to sessions.User type with required fields
+ foundUser = sessions.User{
+ Email: email,
+ Role: userRole,
+ }
+
+ return foundUser, nil
+}
+
+// FindUserByAPIToken retrieves a possible stored user and role from the ldap_user_api_tokens table store
+func (l *ldapAuthenticator) FindUserByAPIToken(apiToken string) (sessions.User, error) {
+ if !l.config.UserApiTokenEnabled() {
+ return sessions.User{}, errors.New("API token is not enabled ")
+ }
+
+ var foundUser sessions.User
+ err := l.q.Transaction(func(tx pg.Queryer) error {
+ // Query the ldap user API token table for given token, user role and email are cached so
+ // no further upstream LDAP query is performed, sessions and tokens are synced against the upstream server
+ // via the UpstreamSyncInterval config and reaper.go sync implementation
+ var foundUserToken struct {
+ UserEmail string
+ UserRole sessions.UserRole
+ Valid bool
+ }
+ if err := tx.Get(&foundUserToken,
+ "SELECT user_email, user_role, created_at + $2 >= now() as valid FROM ldap_user_api_tokens WHERE token_key = $1",
+ apiToken, l.config.UserAPITokenDuration().Duration(),
+ ); err != nil {
+ return err
+ }
+ if !foundUserToken.Valid {
+ return sessions.ErrUserSessionExpired
+ }
+ foundUser = sessions.User{
+ Email: foundUserToken.UserEmail,
+ Role: foundUserToken.UserRole,
+ }
+ return nil
+ })
+ if err != nil {
+ if errors.Is(err, sessions.ErrUserSessionExpired) {
+ // API Token expired, purge
+ if _, execErr := l.q.Exec("DELETE FROM ldap_user_api_tokens WHERE token_key = $1", apiToken); err != nil {
+ l.lggr.Errorf("error purging stale ldap API token session: %v", execErr)
+ }
+ }
+ return sessions.User{}, err
+ }
+ return foundUser, nil
+}
+
+// ListUsers will load and return all active users in applicable LDAP groups, extended with local admin users as well
+func (l *ldapAuthenticator) ListUsers() ([]sessions.User, error) {
+ // For each defined role/group, query for the list of group members to gather the full list of possible users
+ users := []sessions.User{}
+ var err error
+
+ conn, err := l.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ l.lggr.Errorf("error in LDAP dial: ", err)
+ return users, errors.New("unable to establish connection to LDAP server with provided URL and credentials")
+ }
+ defer conn.Close()
+
+ // Query for list of uniqueMember IDs present in Admin group
+ adminUsers, err := l.ldapGroupMembersListToUser(conn, l.config.AdminUserGroupCN(), sessions.UserRoleAdmin)
+ if err != nil {
+ l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err)
+ return users, errors.New("unable to list group users")
+ }
+ // Query for list of uniqueMember IDs present in Edit group
+ editUsers, err := l.ldapGroupMembersListToUser(conn, l.config.EditUserGroupCN(), sessions.UserRoleEdit)
+ if err != nil {
+ l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err)
+ return users, errors.New("unable to list group users")
+ }
+ // Query for list of uniqueMember IDs present in Run group
+ runUsers, err := l.ldapGroupMembersListToUser(conn, l.config.RunUserGroupCN(), sessions.UserRoleRun)
+ if err != nil {
+ l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err)
+ return users, errors.New("unable to list group users")
+ }
+ // Query for list of uniqueMember IDs present in Read group
+ readUsers, err := l.ldapGroupMembersListToUser(conn, l.config.ReadUserGroupCN(), sessions.UserRoleView)
+ if err != nil {
+ l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err)
+ return users, errors.New("unable to list group users")
+ }
+
+ // Aggregate full list
+ users = append(users, adminUsers...)
+ users = append(users, editUsers...)
+ users = append(users, runUsers...)
+ users = append(users, readUsers...)
+
+ // Dedupe preserving order of highest role
+ uniqueRef := make(map[string]struct{})
+ dedupedUsers := []sessions.User{}
+ for _, user := range users {
+ if _, ok := uniqueRef[user.Email]; !ok {
+ uniqueRef[user.Email] = struct{}{}
+ dedupedUsers = append(dedupedUsers, user)
+ }
+ }
+
+ // If no active attribute to check is defined, user simple being assigned the group is enough, return full list
+ if l.config.ActiveAttribute() == "" {
+ return dedupedUsers, nil
+ }
+
+ // Now optionally validate that all uniqueMembers are active in the org/LDAP server
+ emails := []string{}
+ for _, user := range dedupedUsers {
+ emails = append(emails, user.Email)
+ }
+ activeUsers, err := l.validateUsersActive(emails)
+ if err != nil {
+ l.lggr.Errorf("error validating supplied user list: ", err)
+ return users, errors.New("error validating supplied user list")
+ }
+
+ // Filter non active users
+ returnUsers := []sessions.User{}
+ for i, active := range activeUsers {
+ if active {
+ returnUsers = append(returnUsers, dedupedUsers[i])
+ }
+ }
+
+ // Extend with local admin users
+ var localAdminUsers []sessions.User
+ if err := l.q.Transaction(func(tx pg.Queryer) error {
+ sql := "SELECT * FROM users ORDER BY email ASC;"
+ return tx.Select(&localAdminUsers, sql)
+ }); err != nil {
+ l.lggr.Errorf("error extending upstream LDAP users with local admin users in users table: ", err)
+ } else {
+ returnUsers = append(returnUsers, localAdminUsers...)
+ }
+
+ return returnUsers, nil
+}
+
+// ldapGroupMembersListToUser queries the LDAP server given a conn for a list of uniqueMember who are part of the parameterized group
+func (l *ldapAuthenticator) ldapGroupMembersListToUser(conn LDAPConn, groupNameCN string, roleToAssign sessions.UserRole) ([]sessions.User, error) {
+ users, err := ldapGroupMembersListToUser(
+ conn, groupNameCN, roleToAssign, l.config.GroupsDN(),
+ l.config.BaseDN(), l.config.QueryTimeout(),
+ l.lggr,
+ )
+ if err != nil {
+ l.lggr.Errorf("error listing members of group (%s): %v", groupNameCN, err)
+ return users, errors.New("error searching group members in LDAP directory")
+ }
+ return users, nil
+}
+
+// AuthorizedUserWithSession will return the API user associated with the Session ID if it
+// exists and hasn't expired, and update session's LastUsed field. The state of the upstream LDAP server
+// is polled and synced at the defined interval via a SleeperTask
+func (l *ldapAuthenticator) AuthorizedUserWithSession(sessionID string) (sessions.User, error) {
+ if len(sessionID) == 0 {
+ return sessions.User{}, errors.New("session ID cannot be empty")
+ }
+ var foundUser sessions.User
+ err := l.q.Transaction(func(tx pg.Queryer) error {
+ // Query the ldap_sessions table for given session ID, user role and email are cached so
+ // no further upstream LDAP query is performed
+ var foundSession struct {
+ UserEmail string
+ UserRole sessions.UserRole
+ Valid bool
+ }
+ if err := tx.Get(&foundSession,
+ "SELECT user_email, user_role, created_at + $2 >= now() as valid FROM ldap_sessions WHERE id = $1",
+ sessionID, l.config.SessionTimeout().Duration(),
+ ); err != nil {
+ return sessions.ErrUserSessionExpired
+ }
+ if !foundSession.Valid {
+ // Sessions expired, purge
+ return sessions.ErrUserSessionExpired
+ }
+ foundUser = sessions.User{
+ Email: foundSession.UserEmail,
+ Role: foundSession.UserRole,
+ }
+ return nil
+ })
+ if err != nil {
+ if errors.Is(err, sessions.ErrUserSessionExpired) {
+ if _, execErr := l.q.Exec("DELETE FROM ldap_sessions WHERE id = $1", sessionID); err != nil {
+ l.lggr.Errorf("error purging stale ldap session: %v", execErr)
+ }
+ }
+ return sessions.User{}, err
+ }
+ return foundUser, nil
+}
+
+// DeleteUser is not supported for read only LDAP
+func (l *ldapAuthenticator) DeleteUser(email string) error {
+ return sessions.ErrNotSupported
+}
+
+// DeleteUserSession removes an ldapSession table entry by ID
+func (l *ldapAuthenticator) DeleteUserSession(sessionID string) error {
+ _, err := l.q.Exec("DELETE FROM ldap_sessions WHERE id = $1", sessionID)
+ return err
+}
+
+// GetUserWebAuthn returns an empty stub, MFA token prompt is handled either by the upstream
+// server blocking callback, or an error code to pass a OTP
+func (l *ldapAuthenticator) GetUserWebAuthn(email string) ([]sessions.WebAuthn, error) {
+ return []sessions.WebAuthn{}, nil
+}
+
+// CreateSession will forward the session request credentials to the
+// LDAP server, querying for a user + role response if username and
+// password match. The API call is blocking with timeout, so a sufficient timeout
+// should allow the user to respond to potential MFA push notifications
+func (l *ldapAuthenticator) CreateSession(sr sessions.SessionRequest) (string, error) {
+ conn, err := l.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ return "", errors.New("unable to establish connection to LDAP server with provided URL and credentials")
+ }
+ defer conn.Close()
+
+ var returnErr error
+
+ // Attempt to LDAP Bind with user provided credentials
+ escapedEmail := ldap.EscapeFilter(strings.ToLower(sr.Email))
+ searchBaseDN := fmt.Sprintf("%s=%s,%s,%s", l.config.BaseUserAttr(), escapedEmail, l.config.UsersDN(), l.config.BaseDN())
+ if err = conn.Bind(searchBaseDN, sr.Password); err != nil {
+ l.lggr.Infof("Error binding user authentication request in LDAP Bind: %v", err)
+ returnErr = errors.New("unable to log in with LDAP server. Check credentials")
+ }
+
+ // Bind was successful meaning user and credentials are present in LDAP directory
+ // Reuse FindUser functionality to fetch user roles used to create ldap_session entry
+ // with cached user email and role
+ foundUser, err := l.FindUser(escapedEmail)
+ if err != nil {
+ l.lggr.Infof("Successful user login, but error querying for user groups: user: %s, error %v", escapedEmail, err)
+ returnErr = errors.New("log in successful, but no assigned groups to assume role")
+ }
+
+ isLocalUser := false
+ if returnErr != nil {
+ // Unable to log in against LDAP server, attempt fallback local auth with credentials, case of local CLI Admin account
+ // Successful local user sessions can not be managed by the upstream server and have expiration handled by the reaper sync module
+ foundUser, returnErr = l.localLoginFallback(sr)
+ isLocalUser = true
+ }
+
+ // If err is still populated, return
+ if returnErr != nil {
+ return "", returnErr
+ }
+
+ l.lggr.Infof("Successful LDAP login request for user %s - %s", sr.Email, foundUser.Role)
+
+ // Save session, user, and role to database. Given a session ID for future queries, the LDAP server will not be queried
+ // Sessions are set to expire after the duration + creation date elapsed, and are synced on an interval against the upstream
+ // LDAP server
+ session := sessions.NewSession()
+ _, err = l.q.Exec(
+ "INSERT INTO ldap_sessions (id, user_email, user_role, localauth_user, created_at) VALUES ($1, $2, $3, $4, now())",
+ session.ID,
+ strings.ToLower(sr.Email),
+ foundUser.Role,
+ isLocalUser,
+ )
+ if err != nil {
+ l.lggr.Errorf("unable to create new session in ldap_sessions table %v", err)
+ return "", fmt.Errorf("error creating local LDAP session: %w", err)
+ }
+
+ l.auditLogger.Audit(audit.AuthLoginSuccessNo2FA, map[string]interface{}{"email": sr.Email})
+
+ return session.ID, nil
+}
+
+// ClearNonCurrentSessions removes all ldap_sessions but the id passed in.
+func (l *ldapAuthenticator) ClearNonCurrentSessions(sessionID string) error {
+ _, err := l.q.Exec("DELETE FROM ldap_sessions where id != $1", sessionID)
+ return err
+}
+
+// CreateUser is not supported for read only LDAP
+func (l *ldapAuthenticator) CreateUser(user *sessions.User) error {
+ return sessions.ErrNotSupported
+}
+
+// UpdateRole is not supported for read only LDAP
+func (l *ldapAuthenticator) UpdateRole(email, newRole string) (sessions.User, error) {
+ return sessions.User{}, sessions.ErrNotSupported
+}
+
+// SetPassword for remote users is not supported via the read only LDAP implementation, however change password
+// in the context of updating a local admin user's password is required
+func (l *ldapAuthenticator) SetPassword(user *sessions.User, newPassword string) error {
+ // Ensure specified user is part of the local admins user table
+ var localAdminUser sessions.User
+ if err := l.q.Transaction(func(tx pg.Queryer) error {
+ sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
+ return tx.Get(&localAdminUser, sql, user.Email)
+ }); err != nil {
+ l.lggr.Infof("Can not change password, local user with email not found in users table: %s, err: %v", user.Email, err)
+ return sessions.ErrNotSupported
+ }
+
+ // User is local admin, save new password
+ hashedPassword, err := utils.HashPassword(newPassword)
+ if err != nil {
+ return err
+ }
+ if err := l.q.Transaction(func(tx pg.Queryer) error {
+ sql := "UPDATE users SET hashed_password = $1, updated_at = now() WHERE email = $2 RETURNING *"
+ return tx.Get(user, sql, hashedPassword, user.Email)
+ }); err != nil {
+ l.lggr.Errorf("unable to set password for user: %s, err: %v", user.Email, err)
+ return errors.New("unable to save password")
+ }
+ return nil
+}
+
+// TestPassword tests if an LDAP login bind can be performed with provided credentials, returns nil if success
+func (l *ldapAuthenticator) TestPassword(email string, password string) error {
+ conn, err := l.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ return errors.New("unable to establish connection to LDAP server with provided URL and credentials")
+ }
+ defer conn.Close()
+
+ // Attempt to LDAP Bind with user provided credentials
+ escapedEmail := ldap.EscapeFilter(strings.ToLower(email))
+ searchBaseDN := fmt.Sprintf("%s=%s,%s,%s", l.config.BaseUserAttr(), escapedEmail, l.config.UsersDN(), l.config.BaseDN())
+ err = conn.Bind(searchBaseDN, password)
+ if err == nil {
+ return nil
+ }
+ l.lggr.Infof("Error binding user authentication request in TestPassword call LDAP Bind: %v", err)
+
+ // Fall back to test local users table in case of supported local CLI users as well
+ var hashedPassword string
+ if err := l.q.Get(&hashedPassword, "SELECT hashed_password FROM users WHERE lower(email) = lower($1)", email); err != nil {
+ return errors.New("invalid credentials")
+ }
+ if !utils.CheckPasswordHash(password, hashedPassword) {
+ return errors.New("invalid credentials")
+ }
+
+ return nil
+}
+
+// CreateAndSetAuthToken generates a new credential token with the user role
+func (l *ldapAuthenticator) CreateAndSetAuthToken(user *sessions.User) (*auth.Token, error) {
+ newToken := auth.NewToken()
+
+ err := l.SetAuthToken(user, newToken)
+ if err != nil {
+ return nil, err
+ }
+
+ return newToken, nil
+}
+
+// SetAuthToken updates the user to use the given Authentication Token.
+func (l *ldapAuthenticator) SetAuthToken(user *sessions.User, token *auth.Token) error {
+ if !l.config.UserApiTokenEnabled() {
+ return errors.New("API token is not enabled ")
+ }
+
+ salt := utils.NewSecret(utils.DefaultSecretSize)
+ hashedSecret, err := auth.HashedSecret(token, salt)
+ if err != nil {
+ return fmt.Errorf("LDAPAuth SetAuthToken hashed secret error: %w", err)
+ }
+
+ err = l.q.Transaction(func(tx pg.Queryer) error {
+ // Is this user a local CLI Admin or upstream LDAP user?
+ // Check presence in local users table. Set localauth_user column true if present.
+ // This flag omits the session/token from being purged by the sync daemon/reaper.go
+ isLocalCLIAdmin := false
+ err = l.q.QueryRow("SELECT EXISTS (SELECT 1 FROM users WHERE email = $1)", user.Email).Scan(&isLocalCLIAdmin)
+ if err != nil {
+ return fmt.Errorf("error checking user presence in users table: %w", err)
+ }
+
+ // Remove any existing API tokens
+ if _, err = l.q.Exec("DELETE FROM ldap_user_api_tokens WHERE user_email = $1", user.Email); err != nil {
+ return fmt.Errorf("error executing DELETE FROM ldap_user_api_tokens: %w", err)
+ }
+ // Create new API token for user
+ _, err = l.q.Exec(
+ "INSERT INTO ldap_user_api_tokens (user_email, user_role, localauth_user, token_key, token_salt, token_hashed_secret, created_at) VALUES ($1, $2, $3, $4, $5, $6, now())",
+ user.Email,
+ user.Role,
+ isLocalCLIAdmin,
+ token.AccessKey,
+ salt,
+ hashedSecret,
+ )
+ if err != nil {
+ return fmt.Errorf("failed insert into ldap_user_api_tokens: %w", err)
+ }
+ return nil
+ })
+ if err != nil {
+ return errors.New("error creating API token")
+ }
+
+ l.auditLogger.Audit(audit.APITokenCreated, map[string]interface{}{"user": user.Email})
+ return nil
+}
+
+// DeleteAuthToken clears and disables the users Authentication Token.
+func (l *ldapAuthenticator) DeleteAuthToken(user *sessions.User) error {
+ _, err := l.q.Exec("DELETE FROM ldap_user_api_tokens WHERE email = $1")
+ return err
+}
+
+// SaveWebAuthn is not supported for read only LDAP
+func (l *ldapAuthenticator) SaveWebAuthn(token *sessions.WebAuthn) error {
+ return sessions.ErrNotSupported
+}
+
+// Sessions returns all sessions limited by the parameters.
+func (l *ldapAuthenticator) Sessions(offset, limit int) ([]sessions.Session, error) {
+ var sessions []sessions.Session
+ sql := `SELECT * FROM ldap_sessions ORDER BY created_at, id LIMIT $1 OFFSET $2;`
+ if err := l.q.Select(&sessions, sql, limit, offset); err != nil {
+ return sessions, nil
+ }
+ return sessions, nil
+}
+
+// FindExternalInitiator supports the 'Run' role external intiator header auth functionality
+func (l *ldapAuthenticator) FindExternalInitiator(eia *auth.Token) (*bridges.ExternalInitiator, error) {
+ exi := &bridges.ExternalInitiator{}
+ err := l.q.Get(exi, `SELECT * FROM external_initiators WHERE access_key = $1`, eia.AccessKey)
+ return exi, err
+}
+
+// localLoginFallback tests the credentials provided against the 'local' authentication method
+// This covers the case of local CLI API calls requiring local login separate from the LDAP server
+func (l *ldapAuthenticator) localLoginFallback(sr sessions.SessionRequest) (sessions.User, error) {
+ var user sessions.User
+ sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
+ err := l.q.Get(&user, sql, sr.Email)
+ if err != nil {
+ return user, err
+ }
+ if !constantTimeEmailCompare(strings.ToLower(sr.Email), strings.ToLower(user.Email)) {
+ l.auditLogger.Audit(audit.AuthLoginFailedEmail, map[string]interface{}{"email": sr.Email})
+ return user, errors.New("invalid email")
+ }
+
+ if !utils.CheckPasswordHash(sr.Password, user.HashedPassword) {
+ l.auditLogger.Audit(audit.AuthLoginFailedPassword, map[string]interface{}{"email": sr.Email})
+ return user, errors.New("invalid password")
+ }
+
+ return user, nil
+}
+
+// validateUsersActive performs an additional LDAP server query for the supplied emails, checking the
+// returned user data for an 'active' property defined optionally in the config.
+// Returns same length bool 'valid' array, indexed by sorted email
+func (l *ldapAuthenticator) validateUsersActive(emails []string) ([]bool, error) {
+ validUsers := make([]bool, len(emails))
+ // If active attribute to check is not defined in config, skip
+ if l.config.ActiveAttribute() == "" {
+ // fill with valids
+ for i := range emails {
+ validUsers[i] = true
+ }
+ return validUsers, nil
+ }
+
+ conn, err := l.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ l.lggr.Errorf("error in LDAP dial: ", err)
+ return validUsers, errors.New("unable to establish connection to LDAP server with provided URL and credentials")
+ }
+ defer conn.Close()
+
+ // Build the full email list query to pull all 'isActive' information for each user specified in one query
+ filterQuery := "(|"
+ for _, email := range emails {
+ escapedEmail := ldap.EscapeFilter(email)
+ filterQuery = fmt.Sprintf("%s(%s=%s)", filterQuery, l.config.BaseUserAttr(), escapedEmail)
+ }
+ filterQuery = fmt.Sprintf("(&%s))", filterQuery)
+ searchBaseDN := fmt.Sprintf("%s,%s", l.config.UsersDN(), l.config.BaseDN())
+ searchRequest := ldap.NewSearchRequest(
+ searchBaseDN,
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
+ 0, int(l.config.QueryTimeout().Seconds()), false,
+ filterQuery,
+ []string{l.config.BaseUserAttr(), l.config.ActiveAttribute()},
+ nil,
+ )
+ // Query LDAP server for the ActiveAttribute property of each specified user
+ results, err := conn.Search(searchRequest)
+ if err != nil {
+ l.lggr.Errorf("error searching user in LDAP query: %v", err)
+ return validUsers, errors.New("error searching users in LDAP directory")
+ }
+
+ // Ensure user response entries
+ if len(results.Entries) == 0 {
+ return validUsers, ErrUserNotInUpstream
+ }
+
+ // Pull expected ActiveAttribute value from list of string possible values
+ // keyed on email for final step to return flag bool list where order is preserved
+ emailToActiveMap := make(map[string]bool)
+ for _, result := range results.Entries {
+ isActiveAttribute := result.GetAttributeValue(l.config.ActiveAttribute())
+ uidAttribute := result.GetAttributeValue(l.config.BaseUserAttr())
+ emailToActiveMap[uidAttribute] = isActiveAttribute == l.config.ActiveAttributeAllowedValue()
+ }
+ for i, email := range emails {
+ active, ok := emailToActiveMap[email]
+ if ok && active {
+ validUsers[i] = true
+ }
+ }
+
+ return validUsers, nil
+}
+
+// ldapGroupMembersListToUser queries the LDAP server given a conn for a list of uniqueMember who are part of the parameterized group. Reused by sync.go
+func ldapGroupMembersListToUser(
+ conn LDAPConn,
+ groupNameCN string,
+ roleToAssign sessions.UserRole,
+ groupsDN string,
+ baseDN string,
+ queryTimeout time.Duration,
+ lggr logger.Logger,
+) ([]sessions.User, error) {
+ users := []sessions.User{}
+ // Prepare and query the GroupsDN for the specified group name
+ searchBaseDN := fmt.Sprintf("%s, %s", groupsDN, baseDN)
+ filterQuery := fmt.Sprintf("(&(cn=%s))", groupNameCN)
+ searchRequest := ldap.NewSearchRequest(
+ searchBaseDN,
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
+ 0, int(queryTimeout.Seconds()), false,
+ filterQuery,
+ []string{UniqueMemberAttribute},
+ nil,
+ )
+ result, err := conn.Search(searchRequest)
+ if err != nil {
+ lggr.Errorf("error searching group members in LDAP query: %v", err)
+ return users, errors.New("error searching group members in LDAP directory")
+ }
+
+ // The result.Entry query response here is for the 'group' type of LDAP resource. The result should be a single entry, containing
+ // a single Attribute named 'uniqueMember' containing a list of string Values. These Values are strings that should be returned in
+ // the format "uid=test.user@example.com,ou=users,dc=example,dc=com". The 'uid' is then manually parsed here as the library does
+ // not expose the functionality
+ if len(result.Entries) != 1 {
+ lggr.Errorf("unexpected length of query results for group user members, expected one got %d", len(result.Entries))
+ return users, errors.New("error searching group members in LDAP directory")
+ }
+
+ // Get string list of members from 'uniqueMember' attribute
+ uniqueMemberValues := result.Entries[0].GetAttributeValues(UniqueMemberAttribute)
+ for _, uniqueMemberEntry := range uniqueMemberValues {
+ parts := strings.Split(uniqueMemberEntry, ",") // Split attribute value on comma (uid, ou, dc parts)
+ uidComponent := ""
+ for _, part := range parts { // Iterate parts for "uid="
+ if strings.HasPrefix(part, "uid=") {
+ uidComponent = part
+ break
+ }
+ }
+ if uidComponent == "" {
+ lggr.Errorf("unexpected LDAP group query response for unique members - expected list of LDAP Values for uniqueMember containing LDAP strings in format uid=test.user@example.com,ou=users,dc=example,dc=com. Got %s", uniqueMemberEntry)
+ continue
+ }
+ // Map each user email to the sessions.User struct
+ userEmail := strings.TrimPrefix(uidComponent, "uid=")
+ users = append(users, sessions.User{
+ Email: userEmail,
+ Role: roleToAssign,
+ })
+ }
+ return users, nil
+}
+
+// groupSearchResultsToUserRole takes a list of LDAP group search result entries and returns the associated
+// internal user role based on the group name mappings defined in the configuration
+func (l *ldapAuthenticator) groupSearchResultsToUserRole(ldapGroups []*ldap.Entry) (sessions.UserRole, error) {
+ return GroupSearchResultsToUserRole(
+ ldapGroups,
+ l.config.AdminUserGroupCN(),
+ l.config.EditUserGroupCN(),
+ l.config.RunUserGroupCN(),
+ l.config.ReadUserGroupCN(),
+ )
+}
+
+func GroupSearchResultsToUserRole(ldapGroups []*ldap.Entry, adminCN string, editCN string, runCN string, readCN string) (sessions.UserRole, error) {
+ // If defined Admin group name is present in groups search result, return UserRoleAdmin
+ for _, group := range ldapGroups {
+ if group.GetAttributeValue("cn") == adminCN {
+ return sessions.UserRoleAdmin, nil
+ }
+ }
+ // Check edit role
+ for _, group := range ldapGroups {
+ if group.GetAttributeValue("cn") == editCN {
+ return sessions.UserRoleEdit, nil
+ }
+ }
+ // Check run role
+ for _, group := range ldapGroups {
+ if group.GetAttributeValue("cn") == runCN {
+ return sessions.UserRoleRun, nil
+ }
+ }
+ // Check view role
+ for _, group := range ldapGroups {
+ if group.GetAttributeValue("cn") == readCN {
+ return sessions.UserRoleView, nil
+ }
+ }
+ // No role group found, error
+ return sessions.UserRoleView, ErrUserNoLDAPGroups
+}
+
+const constantTimeEmailLength = 256
+
+func constantTimeEmailCompare(left, right string) bool {
+ length := mathutil.Max(constantTimeEmailLength, len(left), len(right))
+ leftBytes := make([]byte, length)
+ rightBytes := make([]byte, length)
+ copy(leftBytes, left)
+ copy(rightBytes, right)
+ return subtle.ConstantTimeCompare(leftBytes, rightBytes) == 1
+}
diff --git a/core/sessions/ldapauth/ldap_test.go b/core/sessions/ldapauth/ldap_test.go
new file mode 100644
index 0000000000..261141d66e
--- /dev/null
+++ b/core/sessions/ldapauth/ldap_test.go
@@ -0,0 +1,639 @@
+package ldapauth_test
+
+import (
+ "errors"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/go-ldap/ldap/v3"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/sqlx"
+
+ "github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/logger/audit"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth/mocks"
+)
+
+// Setup LDAP Auth authenticator
+func setupAuthenticationProvider(t *testing.T, ldapClient ldapauth.LDAPClient) (*sqlx.DB, sessions.AuthenticationProvider) {
+ t.Helper()
+
+ cfg := ldapauth.TestConfig{}
+ db := pgtest.NewSqlxDB(t)
+ ldapAuthProvider, err := ldapauth.NewTestLDAPAuthenticator(db, pgtest.NewQConfig(true), &cfg, true, logger.TestLogger(t), &audit.AuditLoggerService{})
+ if err != nil {
+ t.Fatalf("Error constructing NewTestLDAPAuthenticator: %v\n", err)
+ }
+
+ // Override the LDAPClient responsible for returning the *ldap.Conn struct with Mock
+ ldapAuthProvider.SetLDAPClient(ldapClient)
+ return db, ldapAuthProvider
+}
+
+func TestORM_FindUser_Empty(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // User not in upstream, return no entry
+ expectedResults := ldap.SearchResult{}
+
+ // On search performed for validateUsersActive
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedResults, nil)
+
+ // Not in upstream, no local admin users, expect error
+ _, err := ldapAuthProvider.FindUser("unknown-user")
+ require.ErrorContains(t, err, "LDAP query returned no matching users")
+}
+
+func TestORM_FindUser_NoGroups(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // User present in Upstream but no groups assigned
+ user1 := cltest.MustRandomUser(t)
+ expectedResults := ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=User One,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "organizationalStatus",
+ Values: []string{"ACTIVE"},
+ },
+ {
+ Name: "uid",
+ Values: []string{user1.Email},
+ },
+ },
+ },
+ },
+ }
+
+ // On search performed for validateUsersActive
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedResults, nil)
+
+ // No Groups, expect error
+ _, err := ldapAuthProvider.FindUser(user1.Email)
+ require.ErrorContains(t, err, "user present in directory, but matching no role groups assigned")
+}
+
+func TestORM_FindUser_NotActive(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // User present in Upstream but not active
+ user1 := cltest.MustRandomUser(t)
+ expectedResults := ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=User One,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "organizationalStatus",
+ Values: []string{"INACTIVE"},
+ },
+ {
+ Name: "uid",
+ Values: []string{user1.Email},
+ },
+ },
+ },
+ },
+ }
+
+ // On search performed for validateUsersActive
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedResults, nil)
+
+ // User not active, expect error
+ _, err := ldapAuthProvider.FindUser(user1.Email)
+ require.ErrorContains(t, err, "user not active")
+}
+
+func TestORM_FindUser_Single(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // User present and valid
+ user1 := cltest.MustRandomUser(t)
+ expectedResults := ldap.SearchResult{ // Users query
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=User One,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "organizationalStatus",
+ Values: []string{"ACTIVE"},
+ },
+ {
+ Name: "uid",
+ Values: []string{user1.Email},
+ },
+ },
+ },
+ },
+ }
+ expectedGroupResults := ldap.SearchResult{ // Groups query
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=NodeEditors,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{"NodeEditors"},
+ },
+ },
+ },
+ },
+ }
+
+ // On search performed for validateUsersActive
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedResults, nil).Once()
+
+ // Second call on user groups search
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedGroupResults, nil).Once()
+
+ // User active, and has editor group. Expect success
+ user, err := ldapAuthProvider.FindUser(user1.Email)
+ require.NoError(t, err)
+ require.Equal(t, user1.Email, user.Email)
+ require.Equal(t, sessions.UserRoleEdit, user.Role)
+}
+
+func TestORM_FindUser_FallbackMatchLocalAdmin(t *testing.T) {
+ t.Parallel()
+
+ // Initilaize LDAP Authentication Provider with mock client
+ mockLdapClient := mocks.NewLDAPClient(t)
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // Not in upstream, but utilize text fixture admin user presence in test DB. Succeed
+ user, err := ldapAuthProvider.FindUser(cltest.APIEmailAdmin)
+ require.NoError(t, err)
+ require.Equal(t, cltest.APIEmailAdmin, user.Email)
+ require.Equal(t, sessions.UserRoleAdmin, user.Role)
+}
+
+func TestORM_FindUserByAPIToken_Success(t *testing.T) {
+ // Initilaize LDAP Authentication Provider with mock client
+ mockLdapClient := mocks.NewLDAPClient(t)
+ db, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // Ensure valid tokens return a user with role
+ testEmail := "test@test.com"
+ apiToken := "example"
+ _, err := db.Exec("INSERT INTO ldap_user_api_tokens values ($1, 'edit', false, $2, '', '', now())", testEmail, apiToken)
+ require.NoError(t, err)
+
+ // Found user by API token in specific ldap_user_api_tokens table
+ user, err := ldapAuthProvider.FindUserByAPIToken(apiToken)
+ require.NoError(t, err)
+ require.Equal(t, testEmail, user.Email)
+ require.Equal(t, sessions.UserRoleEdit, user.Role)
+}
+
+func TestORM_FindUserByAPIToken_Expired(t *testing.T) {
+ cfg := ldapauth.TestConfig{}
+
+ // Initilaize LDAP Authentication Provider with mock client
+ mockLdapClient := mocks.NewLDAPClient(t)
+ db, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // Ensure valid tokens return a user with role
+ testEmail := "test@test.com"
+ apiToken := "example"
+ expiredTime := time.Now().Add(-cfg.UserAPITokenDuration().Duration())
+ _, err := db.Exec("INSERT INTO ldap_user_api_tokens values ($1, 'edit', false, $2, '', '', $3)", testEmail, apiToken, expiredTime)
+ require.NoError(t, err)
+
+ // Token found, but expired. Expect error
+ _, err = ldapAuthProvider.FindUserByAPIToken(apiToken)
+ require.Equal(t, sessions.ErrUserSessionExpired, err)
+}
+
+func TestORM_ListUsers_Full(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ user1 := cltest.MustRandomUser(t)
+ user2 := cltest.MustRandomUser(t)
+ user3 := cltest.MustRandomUser(t)
+ user4 := cltest.MustRandomUser(t)
+ user5 := cltest.MustRandomUser(t)
+ user6 := cltest.MustRandomUser(t)
+
+ // LDAP Group queries per role - admin
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeAdminsGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapauth.UniqueMemberAttribute,
+ Values: []string{
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user1.Email),
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user2.Email),
+ },
+ },
+ },
+ },
+ },
+ }, nil).Once()
+ // LDAP Group queries per role - edit
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeEditorsGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapauth.UniqueMemberAttribute,
+ Values: []string{
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user3.Email),
+ },
+ },
+ },
+ },
+ },
+ }, nil).Once()
+ // LDAP Group queries per role - run
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=NodeRunners,ou=Groups,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapauth.UniqueMemberAttribute,
+ Values: []string{
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user4.Email),
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user4.Email), // Test deduped
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user5.Email),
+ },
+ },
+ },
+ },
+ },
+ }, nil).Once()
+ // LDAP Group queries per role - view
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=NodeReadOnly,ou=Groups,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapauth.UniqueMemberAttribute,
+ Values: []string{
+ fmt.Sprintf("uid=%s,ou=users,dc=example,dc=com", user6.Email),
+ },
+ },
+ },
+ },
+ },
+ }, nil).Once()
+ // Lastly followed by IsActive lookup
+ type userActivePair struct {
+ email string
+ active string
+ }
+ emailsActive := []userActivePair{
+ {user1.Email, "ACTIVE"},
+ {user2.Email, "INACTIVE"},
+ {user3.Email, "ACTIVE"},
+ {user4.Email, "ACTIVE"},
+ {user5.Email, "INACTIVE"},
+ {user6.Email, "ACTIVE"},
+ }
+ listUpstreamUsersQuery := ldap.SearchResult{}
+ for _, upstreamUser := range emailsActive {
+ listUpstreamUsersQuery.Entries = append(listUpstreamUsersQuery.Entries, &ldap.Entry{
+ DN: "cn=User,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "organizationalStatus",
+ Values: []string{upstreamUser.active},
+ },
+ {
+ Name: "uid",
+ Values: []string{upstreamUser.email},
+ },
+ },
+ },
+ )
+ }
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&listUpstreamUsersQuery, nil).Once()
+
+ // Asserts 'uid=' parsing log in ldapGroupMembersListToUser
+ // Expected full list of users above, including local admin user, excluding 'inactive' and duplicate users
+ users, err := ldapAuthProvider.ListUsers()
+ require.NoError(t, err)
+ require.Equal(t, users[0].Email, user1.Email)
+ require.Equal(t, users[0].Role, sessions.UserRoleAdmin)
+ require.Equal(t, users[1].Email, user3.Email) // User 2 inactive
+ require.Equal(t, users[1].Role, sessions.UserRoleEdit)
+ require.Equal(t, users[2].Email, user4.Email)
+ require.Equal(t, users[2].Role, sessions.UserRoleRun)
+ require.Equal(t, users[3].Email, user6.Email) // User 5 inactive
+ require.Equal(t, users[3].Role, sessions.UserRoleView)
+ require.Equal(t, users[4].Email, cltest.APIEmailAdmin) // Text fixture user is local admin included as well
+ require.Equal(t, users[4].Role, sessions.UserRoleAdmin)
+}
+
+func TestORM_CreateSession_UpstreamBind(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // Upsream user present
+ user1 := cltest.MustRandomUser(t)
+ expectedResults := ldap.SearchResult{ // Users query
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=User One,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "organizationalStatus",
+ Values: []string{"ACTIVE"},
+ },
+ {
+ Name: "uid",
+ Values: []string{user1.Email},
+ },
+ },
+ },
+ },
+ }
+ expectedGroupResults := ldap.SearchResult{ // Groups query
+ Entries: []*ldap.Entry{
+ {
+ DN: "cn=NodeEditors,ou=Users,dc=example,dc=com",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{"NodeEditors"},
+ },
+ },
+ },
+ },
+ }
+
+ // On search performed for validateUsersActive
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedResults, nil).Once()
+
+ // Second call on user groups search
+ mockLdapConnProvider.On("Search", mock.AnythingOfType("*ldap.SearchRequest")).Return(&expectedGroupResults, nil).Once()
+
+ // User active, and has editor group. Expect success
+ mockLdapConnProvider.On("Bind", mock.Anything, cltest.Password).Return(nil)
+ sessionRequest := sessions.SessionRequest{
+ Email: user1.Email,
+ Password: cltest.Password,
+ }
+
+ _, err := ldapAuthProvider.CreateSession(sessionRequest)
+ require.NoError(t, err)
+}
+
+func TestORM_CreateSession_LocalAdminFallbackLogin(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // Fail the bind to trigger 'localLoginFallback' - local admin users should still be able to login
+ // regardless of whether the authentication provider is remote or not
+ mockLdapConnProvider.On("Bind", mock.Anything, cltest.Password).Return(errors.New("unable to login via LDAP server")).Once()
+
+ // User active, and has editor group. Expect success
+ sessionRequest := sessions.SessionRequest{
+ Email: cltest.APIEmailAdmin,
+ Password: cltest.Password,
+ }
+
+ _, err := ldapAuthProvider.CreateSession(sessionRequest)
+ require.NoError(t, err)
+
+ // Finally, assert login failing altogether
+ // User active, and has editor group. Expect success
+ mockLdapConnProvider.On("Bind", mock.Anything, "incorrect-password").Return(errors.New("unable to login via LDAP server")).Once()
+ sessionRequest = sessions.SessionRequest{
+ Email: cltest.APIEmailAdmin,
+ Password: "incorrect-password",
+ }
+
+ _, err = ldapAuthProvider.CreateSession(sessionRequest)
+ require.ErrorContains(t, err, "invalid password")
+}
+
+func TestORM_SetPassword_LocalAdminFallbackLogin(t *testing.T) {
+ t.Parallel()
+
+ mockLdapClient := mocks.NewLDAPClient(t)
+ mockLdapConnProvider := mocks.NewLDAPConn(t)
+ mockLdapClient.On("CreateEphemeralConnection").Return(mockLdapConnProvider, nil)
+ mockLdapConnProvider.On("Close").Return(nil)
+
+ // Initilaize LDAP Authentication Provider with mock client
+ _, ldapAuthProvider := setupAuthenticationProvider(t, mockLdapClient)
+
+ // Fail the bind to trigger 'localLoginFallback' - local admin users should still be able to login
+ // regardless of whether the authentication provider is remote or not
+ mockLdapConnProvider.On("Bind", mock.Anything, cltest.Password).Return(errors.New("unable to login via LDAP server")).Once()
+
+ // User active, and has editor group. Expect success
+ sessionRequest := sessions.SessionRequest{
+ Email: cltest.APIEmailAdmin,
+ Password: cltest.Password,
+ }
+
+ _, err := ldapAuthProvider.CreateSession(sessionRequest)
+ require.NoError(t, err)
+
+ // Finally, assert login failing altogether
+ // User active, and has editor group. Expect success
+ mockLdapConnProvider.On("Bind", mock.Anything, "incorrect-password").Return(errors.New("unable to login via LDAP server")).Once()
+ sessionRequest = sessions.SessionRequest{
+ Email: cltest.APIEmailAdmin,
+ Password: "incorrect-password",
+ }
+
+ _, err = ldapAuthProvider.CreateSession(sessionRequest)
+ require.ErrorContains(t, err, "invalid password")
+}
+
+func TestORM_MapSearchGroups(t *testing.T) {
+ t.Parallel()
+
+ cfg := ldapauth.TestConfig{}
+
+ tests := []struct {
+ name string
+ groupsQuerySearchResult []*ldap.Entry
+ wantMappedRole sessions.UserRole
+ wantErr error
+ }{
+ {
+ "user in admin group only",
+ []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeAdminsGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{ldapauth.NodeAdminsGroupCN},
+ },
+ },
+ },
+ },
+ sessions.UserRoleAdmin,
+ nil,
+ },
+ {
+ "user in edit group",
+ []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeEditorsGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{ldapauth.NodeEditorsGroupCN},
+ },
+ },
+ },
+ },
+ sessions.UserRoleEdit,
+ nil,
+ },
+ {
+ "user in run group",
+ []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeRunnersGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{ldapauth.NodeRunnersGroupCN},
+ },
+ },
+ },
+ },
+ sessions.UserRoleRun,
+ nil,
+ },
+ {
+ "user in view role",
+ []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeReadOnlyGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{ldapauth.NodeReadOnlyGroupCN},
+ },
+ },
+ },
+ },
+ sessions.UserRoleView,
+ nil,
+ },
+ {
+ "user in none",
+ []*ldap.Entry{},
+ sessions.UserRole(""), // ignored, error case
+ ldapauth.ErrUserNoLDAPGroups,
+ },
+ {
+ "user in run and view",
+ []*ldap.Entry{
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeRunnersGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{ldapauth.NodeRunnersGroupCN},
+ },
+ },
+ },
+ {
+ DN: fmt.Sprintf("cn=%s,ou=Groups,dc=example,dc=com", ldapauth.NodeReadOnlyGroupCN),
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: "cn",
+ Values: []string{ldapauth.NodeReadOnlyGroupCN},
+ },
+ },
+ },
+ },
+ sessions.UserRoleRun, // Take highest role
+ nil,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ role, err := ldapauth.GroupSearchResultsToUserRole(
+ test.groupsQuerySearchResult,
+ cfg.AdminUserGroupCN(),
+ cfg.EditUserGroupCN(),
+ cfg.RunUserGroupCN(),
+ cfg.ReadUserGroupCN(),
+ )
+ if test.wantErr != nil {
+ assert.Equal(t, test.wantErr, err)
+ } else {
+ assert.Equal(t, test.wantMappedRole, role)
+ }
+ })
+ }
+}
diff --git a/core/sessions/ldapauth/mocks/ldap_client.go b/core/sessions/ldapauth/mocks/ldap_client.go
new file mode 100644
index 0000000000..7a44778dca
--- /dev/null
+++ b/core/sessions/ldapauth/mocks/ldap_client.go
@@ -0,0 +1,53 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package mocks
+
+import (
+ ldapauth "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// LDAPClient is an autogenerated mock type for the LDAPClient type
+type LDAPClient struct {
+ mock.Mock
+}
+
+// CreateEphemeralConnection provides a mock function with given fields:
+func (_m *LDAPClient) CreateEphemeralConnection() (ldapauth.LDAPConn, error) {
+ ret := _m.Called()
+
+ var r0 ldapauth.LDAPConn
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (ldapauth.LDAPConn, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() ldapauth.LDAPConn); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(ldapauth.LDAPConn)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewLDAPClient creates a new instance of LDAPClient. 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 NewLDAPClient(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *LDAPClient {
+ mock := &LDAPClient{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/core/sessions/ldapauth/mocks/ldap_conn.go b/core/sessions/ldapauth/mocks/ldap_conn.go
new file mode 100644
index 0000000000..c05fb6c4fa
--- /dev/null
+++ b/core/sessions/ldapauth/mocks/ldap_conn.go
@@ -0,0 +1,82 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package mocks
+
+import (
+ ldap "github.com/go-ldap/ldap/v3"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// LDAPConn is an autogenerated mock type for the LDAPConn type
+type LDAPConn struct {
+ mock.Mock
+}
+
+// Bind provides a mock function with given fields: username, password
+func (_m *LDAPConn) Bind(username string, password string) error {
+ ret := _m.Called(username, password)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string) error); ok {
+ r0 = rf(username, password)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Close provides a mock function with given fields:
+func (_m *LDAPConn) Close() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Search provides a mock function with given fields: searchRequest
+func (_m *LDAPConn) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
+ ret := _m.Called(searchRequest)
+
+ var r0 *ldap.SearchResult
+ var r1 error
+ if rf, ok := ret.Get(0).(func(*ldap.SearchRequest) (*ldap.SearchResult, error)); ok {
+ return rf(searchRequest)
+ }
+ if rf, ok := ret.Get(0).(func(*ldap.SearchRequest) *ldap.SearchResult); ok {
+ r0 = rf(searchRequest)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*ldap.SearchResult)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(*ldap.SearchRequest) error); ok {
+ r1 = rf(searchRequest)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewLDAPConn creates a new instance of LDAPConn. 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 NewLDAPConn(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *LDAPConn {
+ mock := &LDAPConn{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/core/sessions/ldapauth/sync.go b/core/sessions/ldapauth/sync.go
new file mode 100644
index 0000000000..ce7a338f40
--- /dev/null
+++ b/core/sessions/ldapauth/sync.go
@@ -0,0 +1,343 @@
+package ldapauth
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/go-ldap/ldap/v3"
+ "github.com/lib/pq"
+ "github.com/smartcontractkit/sqlx"
+
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type LDAPServerStateSyncer struct {
+ q pg.Q
+ ldapClient LDAPClient
+ config config.LDAP
+ lggr logger.Logger
+ nextSyncTime time.Time
+}
+
+// NewLDAPServerStateSync creates a reaper that cleans stale sessions from the store.
+func NewLDAPServerStateSync(
+ db *sqlx.DB,
+ pgCfg pg.QConfig,
+ config config.LDAP,
+ lggr logger.Logger,
+) utils.SleeperTask {
+ namedLogger := lggr.Named("LDAPServerStateSync")
+ serverSync := LDAPServerStateSyncer{
+ q: pg.NewQ(db, namedLogger, pgCfg),
+ ldapClient: newLDAPClient(config),
+ config: config,
+ lggr: namedLogger,
+ nextSyncTime: time.Time{},
+ }
+ // If enabled, start a background task that calls the Sync/Work function on an
+ // interval without needing an auth event to trigger it
+ // Use IsInstant to check 0 value to omit functionality.
+ if !config.UpstreamSyncInterval().IsInstant() {
+ lggr.Info("LDAP Config UpstreamSyncInterval is non-zero, sync functionality will be called on a timer, respecting the UpstreamSyncRateLimit value")
+ serverSync.StartWorkOnTimer()
+ } else {
+ // Ensure upstream server state is synced on startup manually if interval check not set
+ serverSync.Work()
+ }
+
+ // Start background Sync call task reactive to auth related events
+ serverSyncSleeperTask := utils.NewSleeperTask(&serverSync)
+ return serverSyncSleeperTask
+}
+
+func (ldSync *LDAPServerStateSyncer) Name() string {
+ return "LDAPServerStateSync"
+}
+
+func (ldSync *LDAPServerStateSyncer) StartWorkOnTimer() {
+ time.AfterFunc(ldSync.config.UpstreamSyncInterval().Duration(), ldSync.StartWorkOnTimer)
+ ldSync.Work()
+}
+
+func (ldSync *LDAPServerStateSyncer) Work() {
+ // Purge expired ldap_sessions and ldap_user_api_tokens
+ recordCreationStaleThreshold := ldSync.config.SessionTimeout().Before(time.Now())
+ err := ldSync.deleteStaleSessions(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)
+ if err != nil {
+ ldSync.lggr.Error("unable to expire user API tokens: ", err)
+ }
+
+ // Optional rate limiting check to limit the amount of upstream LDAP server queries performed
+ if !ldSync.config.UpstreamSyncRateLimit().IsInstant() {
+ if !time.Now().After(ldSync.nextSyncTime) {
+ return
+ }
+
+ // Enough time has elapsed to sync again, store the time for when next sync is allowed and begin sync
+ ldSync.nextSyncTime = time.Now().Add(ldSync.config.UpstreamSyncRateLimit().Duration())
+ }
+
+ ldSync.lggr.Info("Begin Upstream LDAP provider state sync after checking time against config UpstreamSyncInterval and UpstreamSyncRateLimit")
+
+ // For each defined role/group, query for the list of group members to gather the full list of possible users
+ users := []sessions.User{}
+
+ conn, err := ldSync.ldapClient.CreateEphemeralConnection()
+ if err != nil {
+ ldSync.lggr.Errorf("Failed to Dial LDAP Server", err)
+ return
+ }
+ // Root level root user auth with credentials provided from config
+ bindStr := ldSync.config.BaseUserAttr() + "=" + ldSync.config.ReadOnlyUserLogin() + "," + ldSync.config.BaseDN()
+ if err = conn.Bind(bindStr, ldSync.config.ReadOnlyUserPass()); err != nil {
+ ldSync.lggr.Errorf("Unable to login as initial root LDAP user", err)
+ }
+ defer conn.Close()
+
+ // Query for list of uniqueMember IDs present in Admin group
+ adminUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.AdminUserGroupCN(), sessions.UserRoleAdmin)
+ if err != nil {
+ ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err)
+ return
+ }
+ // Query for list of uniqueMember IDs present in Edit group
+ editUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.EditUserGroupCN(), sessions.UserRoleEdit)
+ if err != nil {
+ ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err)
+ return
+ }
+ // Query for list of uniqueMember IDs present in Edit group
+ runUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.RunUserGroupCN(), sessions.UserRoleRun)
+ if err != nil {
+ ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err)
+ return
+ }
+ // Query for list of uniqueMember IDs present in Edit group
+ readUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.ReadUserGroupCN(), sessions.UserRoleView)
+ if err != nil {
+ ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err)
+ return
+ }
+
+ users = append(users, adminUsers...)
+ users = append(users, editUsers...)
+ users = append(users, runUsers...)
+ users = append(users, readUsers...)
+
+ // Dedupe preserving order of highest role (sorted)
+ // Preserve members as a map for future lookup
+ upstreamUserStateMap := make(map[string]sessions.User)
+ dedupedEmails := []string{}
+ for _, user := range users {
+ if _, ok := upstreamUserStateMap[user.Email]; !ok {
+ upstreamUserStateMap[user.Email] = user
+ dedupedEmails = append(dedupedEmails, user.Email)
+ }
+ }
+
+ // For each unique user in list of active sessions, check for 'Is Active' propery if defined in the config. Some LDAP providers
+ // list group members that are no longer marked as active
+ usersActiveFlags, err := ldSync.validateUsersActive(dedupedEmails, conn)
+ if err != nil {
+ ldSync.lggr.Errorf("Error validating supplied user list: ", err)
+ }
+ // Remove users in the upstreamUserStateMap source of truth who are part of groups but marked as deactivated/no-active
+ for i, active := range usersActiveFlags {
+ if !active {
+ delete(upstreamUserStateMap, dedupedEmails[i])
+ }
+ }
+
+ // 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 {
+ // 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 {
+ 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 {
+ return fmt.Errorf("unable to query ldap_user_api_tokens table: %w", err)
+ }
+
+ // Create existing sessions and API tokens lookup map for later
+ existingSessionsMap := make(map[string]LDAPSession)
+ for _, sess := range existingSessions {
+ existingSessionsMap[sess.UserEmail] = sess
+ }
+ existingAPITokensMap := make(map[string]LDAPSession)
+ for _, sess := range existingAPITokens {
+ existingAPITokensMap[sess.UserEmail] = sess
+ }
+
+ // Populate list of session emails present in the local session table but not in the upstream state
+ emailsToPurge := []interface{}{}
+ for _, ldapSession := range existingSessions {
+ if _, ok := upstreamUserStateMap[ldapSession.UserEmail]; !ok {
+ emailsToPurge = append(emailsToPurge, ldapSession.UserEmail)
+ }
+ }
+ // Likewise for API Tokens table
+ apiTokenEmailsToPurge := []interface{}{}
+ for _, ldapSession := range existingAPITokens {
+ if _, ok := upstreamUserStateMap[ldapSession.UserEmail]; !ok {
+ apiTokenEmailsToPurge = append(apiTokenEmailsToPurge, ldapSession.UserEmail)
+ }
+ }
+
+ // 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))
+ if err != nil {
+ return err
+ }
+ }
+
+ // 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))
+ if err != nil {
+ return err
+ }
+ }
+
+ // For each user session row, update role to match state of user map from upstream source
+ queryWhenClause := ""
+ emailValues := []interface{}{}
+ // Prepare CASE WHEN query statement with parameterized argument $n placeholders and matching role based on index
+ for email, user := range upstreamUserStateMap {
+ // Only build on SET CASE statement per local session and API token role, not for each upstream user value
+ _, sessionOk := existingSessionsMap[email]
+ _, tokenOk := existingAPITokensMap[email]
+ if !sessionOk && !tokenOk {
+ continue
+ }
+ emailValues = append(emailValues, email)
+ queryWhenClause += fmt.Sprintf("WHEN user_email = $%d THEN '%s' ", len(emailValues), user.Role)
+ }
+
+ // If there are remaining user entries to update
+ 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...)
+ 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...)
+ if err != nil {
+ return err
+ }
+ }
+
+ ldSync.lggr.Info("local ldap_sessions and ldap_user_api_tokens table successfully synced with upstream LDAP state")
+ return nil
+ })
+ if err != nil {
+ ldSync.lggr.Errorf("Error syncing local database state: ", err)
+ }
+ ldSync.lggr.Info("Upstream LDAP sync complete")
+}
+
+// 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)
+ 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)
+ return err
+}
+
+// ldapGroupMembersListToUser queries the LDAP server given a conn for a list of uniqueMember who are part of the parameterized group
+func (ldSync *LDAPServerStateSyncer) ldapGroupMembersListToUser(conn LDAPConn, groupNameCN string, roleToAssign sessions.UserRole) ([]sessions.User, error) {
+ users, err := ldapGroupMembersListToUser(
+ conn, groupNameCN, roleToAssign, ldSync.config.GroupsDN(),
+ ldSync.config.BaseDN(), ldSync.config.QueryTimeout(),
+ ldSync.lggr,
+ )
+ if err != nil {
+ ldSync.lggr.Errorf("Error listing members of group (%s): %v", groupNameCN, err)
+ return users, errors.New("error searching group members in LDAP directory")
+ }
+ return users, nil
+}
+
+// validateUsersActive performs an additional LDAP server query for the supplied emails, checking the
+// returned user data for an 'active' property defined optionally in the config.
+// Returns same length bool 'valid' array, order preserved
+func (ldSync *LDAPServerStateSyncer) validateUsersActive(emails []string, conn LDAPConn) ([]bool, error) {
+ validUsers := make([]bool, len(emails))
+ // If active attribute to check is not defined in config, skip
+ if ldSync.config.ActiveAttribute() == "" {
+ // pre fill with valids
+ for i := range emails {
+ validUsers[i] = true
+ }
+ return validUsers, nil
+ }
+
+ // Build the full email list query to pull all 'isActive' information for each user specified in one query
+ filterQuery := "(|"
+ for _, email := range emails {
+ escapedEmail := ldap.EscapeFilter(email)
+ filterQuery = fmt.Sprintf("%s(%s=%s)", filterQuery, ldSync.config.BaseUserAttr(), escapedEmail)
+ }
+ filterQuery = fmt.Sprintf("(&%s))", filterQuery)
+ searchBaseDN := fmt.Sprintf("%s,%s", ldSync.config.UsersDN(), ldSync.config.BaseDN())
+ searchRequest := ldap.NewSearchRequest(
+ searchBaseDN,
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
+ 0, int(ldSync.config.QueryTimeout().Seconds()), false,
+ filterQuery,
+ []string{ldSync.config.BaseUserAttr(), ldSync.config.ActiveAttribute()},
+ nil,
+ )
+ // Query LDAP server for the ActiveAttribute property of each specified user
+ results, err := conn.Search(searchRequest)
+ if err != nil {
+ ldSync.lggr.Errorf("Error searching user in LDAP query: %v", err)
+ return validUsers, errors.New("error searching users in LDAP directory")
+ }
+ // Ensure user response entries
+ if len(results.Entries) == 0 {
+ return validUsers, errors.New("no users matching email query")
+ }
+
+ // Pull expected ActiveAttribute value from list of string possible values
+ // keyed on email for final step to return flag bool list where order is preserved
+ emailToActiveMap := make(map[string]bool)
+ for _, result := range results.Entries {
+ isActiveAttribute := result.GetAttributeValue(ldSync.config.ActiveAttribute())
+ uidAttribute := result.GetAttributeValue(ldSync.config.BaseUserAttr())
+ emailToActiveMap[uidAttribute] = isActiveAttribute == ldSync.config.ActiveAttributeAllowedValue()
+ }
+ for i, email := range emails {
+ active, ok := emailToActiveMap[email]
+ if ok && active {
+ validUsers[i] = true
+ }
+ }
+
+ return validUsers, nil
+}
diff --git a/core/sessions/orm.go b/core/sessions/localauth/orm.go
similarity index 80%
rename from core/sessions/orm.go
rename to core/sessions/localauth/orm.go
index eaac211f24..d6fb8cd578 100644
--- a/core/sessions/orm.go
+++ b/core/sessions/localauth/orm.go
@@ -1,4 +1,4 @@
-package sessions
+package localauth
import (
"crypto/subtle"
@@ -14,34 +14,11 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/utils/mathutil"
)
-//go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore
-
-type ORM interface {
- FindUser(email string) (User, error)
- FindUserByAPIToken(apiToken string) (User, error)
- ListUsers() ([]User, error)
- AuthorizedUserWithSession(sessionID string) (User, error)
- DeleteUser(email string) error
- DeleteUserSession(sessionID string) error
- CreateSession(sr SessionRequest) (string, error)
- ClearNonCurrentSessions(sessionID string) error
- CreateUser(user *User) error
- UpdateRole(email, newRole string) (User, error)
- SetAuthToken(user *User, token *auth.Token) error
- CreateAndSetAuthToken(user *User) (*auth.Token, error)
- DeleteAuthToken(user *User) error
- SetPassword(user *User, newPassword string) error
- Sessions(offset, limit int) ([]Session, error)
- GetUserWebAuthn(email string) ([]WebAuthn, error)
- SaveWebAuthn(token *WebAuthn) error
-
- FindExternalInitiator(eia *auth.Token) (initiator *bridges.ExternalInitiator, err error)
-}
-
type orm struct {
q pg.Q
sessionDuration time.Duration
@@ -49,38 +26,40 @@ type orm struct {
auditLogger audit.AuditLogger
}
-var _ ORM = (*orm)(nil)
+// orm implements sessions.AuthenticationProvider and sessions.BasicAdminUsersORM interfaces
+var _ sessions.AuthenticationProvider = (*orm)(nil)
+var _ sessions.BasicAdminUsersORM = (*orm)(nil)
-func NewORM(db *sqlx.DB, sd time.Duration, lggr logger.Logger, cfg pg.QConfig, auditLogger audit.AuditLogger) ORM {
- lggr = lggr.Named("SessionsORM")
+func NewORM(db *sqlx.DB, sd time.Duration, lggr logger.Logger, cfg pg.QConfig, auditLogger audit.AuditLogger) sessions.AuthenticationProvider {
+ namedLogger := lggr.Named("LocalAuthAuthenticationProviderORM")
return &orm{
- q: pg.NewQ(db, lggr, cfg),
+ q: pg.NewQ(db, namedLogger, cfg),
sessionDuration: sd,
- lggr: lggr,
+ lggr: lggr.Named("LocalAuthAuthenticationProviderORM"),
auditLogger: auditLogger,
}
}
// FindUser will attempt to return an API user by email.
-func (o *orm) FindUser(email string) (User, error) {
+func (o *orm) FindUser(email string) (sessions.User, error) {
return o.findUser(email)
}
// FindUserByAPIToken will attempt to return an API user via the user's table token_key column.
-func (o *orm) FindUserByAPIToken(apiToken string) (user User, err error) {
+func (o *orm) FindUserByAPIToken(apiToken string) (user sessions.User, err error) {
sql := "SELECT * FROM users WHERE token_key = $1"
err = o.q.Get(&user, sql, apiToken)
return
}
-func (o *orm) findUser(email string) (user User, err error) {
+func (o *orm) findUser(email string) (user sessions.User, err error) {
sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
err = o.q.Get(&user, sql, email)
return
}
// ListUsers will load and return all user rows from the db.
-func (o *orm) ListUsers() (users []User, err error) {
+func (o *orm) ListUsers() (users []sessions.User, err error) {
sql := "SELECT * FROM users ORDER BY email ASC;"
err = o.q.Select(&users, sql)
return
@@ -100,31 +79,27 @@ func (o *orm) updateSessionLastUsed(sessionID string) error {
return o.q.ExecQ("UPDATE sessions SET last_used = now() WHERE id = $1", sessionID)
}
-// ErrUserSessionExpired defines the error triggered when the user session has expired
-var (
- ErrUserSessionExpired = errors.New("user session missing or expired, please login again")
- ErrEmptySessionID = errors.New("session ID cannot be empty")
-)
-
// AuthorizedUserWithSession will return the API user associated with the Session ID if it
// exists and hasn't expired, and update session's LastUsed field.
-func (o *orm) AuthorizedUserWithSession(sessionID string) (user User, err error) {
+// AuthorizedUserWithSession will return the API user associated with the Session ID if it
+// exists and hasn't expired, and update session's LastUsed field.
+func (o *orm) AuthorizedUserWithSession(sessionID string) (user sessions.User, err error) {
if len(sessionID) == 0 {
- return User{}, ErrEmptySessionID
+ return sessions.User{}, sessions.ErrEmptySessionID
}
email, err := o.findValidSession(sessionID)
if err != nil {
- return User{}, ErrUserSessionExpired
+ return sessions.User{}, sessions.ErrUserSessionExpired
}
user, err = o.findUser(email)
if err != nil {
- return User{}, ErrUserSessionExpired
+ return sessions.User{}, sessions.ErrUserSessionExpired
}
if err := o.updateSessionLastUsed(sessionID); err != nil {
- return User{}, err
+ return sessions.User{}, err
}
return user, nil
@@ -151,8 +126,8 @@ func (o *orm) DeleteUserSession(sessionID string) error {
// tokens for the user. This list must be used when logging in (for obvious reasons) but
// must also be used for registration to prevent the user from enrolling the same hardware
// token multiple times.
-func (o *orm) GetUserWebAuthn(email string) ([]WebAuthn, error) {
- var uwas []WebAuthn
+func (o *orm) GetUserWebAuthn(email string) ([]sessions.WebAuthn, error) {
+ var uwas []sessions.WebAuthn
err := o.q.Select(&uwas, "SELECT email, public_key_data FROM web_authns WHERE LOWER(email) = $1", strings.ToLower(email))
if err != nil {
return uwas, err
@@ -165,7 +140,7 @@ func (o *orm) GetUserWebAuthn(email string) ([]WebAuthn, error) {
// CreateSession will check the password in the SessionRequest against
// the hashed API User password in the db. Also will check WebAuthn if it's
// enabled for that user.
-func (o *orm) CreateSession(sr SessionRequest) (string, error) {
+func (o *orm) CreateSession(sr sessions.SessionRequest) (string, error) {
user, err := o.FindUser(sr.Email)
if err != nil {
return "", err
@@ -196,7 +171,7 @@ func (o *orm) CreateSession(sr SessionRequest) (string, error) {
// No webauthn tokens registered for the current user, so normal authentication is now complete
if len(uwas) == 0 {
lggr.Infof("No MFA for user. Creating Session")
- session := NewSession()
+ session := sessions.NewSession()
_, err = o.q.Exec("INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, now(), now())", session.ID, user.Email)
o.auditLogger.Audit(audit.AuthLoginSuccessNo2FA, map[string]interface{}{"email": sr.Email})
return session.ID, err
@@ -207,7 +182,7 @@ func (o *orm) CreateSession(sr SessionRequest) (string, error) {
// data in the next round trip request (tap key to include webauthn data on the login page)
if sr.WebAuthnData == "" {
lggr.Warnf("Attempted login to MFA user. Generating challenge for user.")
- options, webauthnError := BeginWebAuthnLogin(user, uwas, sr)
+ options, webauthnError := sessions.BeginWebAuthnLogin(user, uwas, sr)
if webauthnError != nil {
lggr.Errorf("Could not begin WebAuthn verification: %v", webauthnError)
return "", errors.New("MFA Error")
@@ -225,7 +200,7 @@ func (o *orm) CreateSession(sr SessionRequest) (string, error) {
// The user is at the final stage of logging in with MFA. We have an
// attestation back from the user, we now need to verify that it is
// correct.
- err = FinishWebAuthnLogin(user, uwas, sr)
+ err = sessions.FinishWebAuthnLogin(user, uwas, sr)
if err != nil {
// The user does have WebAuthn enabled but failed the check
@@ -236,7 +211,7 @@ func (o *orm) CreateSession(sr SessionRequest) (string, error) {
lggr.Infof("User passed MFA authentication and login will proceed")
// This is a success so we can create the sessions
- session := NewSession()
+ session := sessions.NewSession()
_, err = o.q.Exec("INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, now(), now())", session.ID, user.Email)
if err != nil {
return "", err
@@ -271,14 +246,14 @@ func (o *orm) ClearNonCurrentSessions(sessionID string) error {
}
// CreateUser creates a new API user
-func (o *orm) CreateUser(user *User) error {
+func (o *orm) CreateUser(user *sessions.User) error {
sql := "INSERT INTO users (email, hashed_password, role, created_at, updated_at) VALUES ($1, $2, $3, now(), now()) RETURNING *"
return o.q.Get(user, sql, strings.ToLower(user.Email), user.HashedPassword, user.Role)
}
// UpdateRole overwrites role field of the user specified by email.
-func (o *orm) UpdateRole(email, newRole string) (User, error) {
- var userToEdit User
+func (o *orm) UpdateRole(email, newRole string) (sessions.User, error) {
+ var userToEdit sessions.User
if newRole == "" {
return userToEdit, errors.New("user role must be specified")
@@ -291,7 +266,7 @@ func (o *orm) UpdateRole(email, newRole string) (User, error) {
}
// Patch validated role
- userRole, err := GetUserRole(newRole)
+ userRole, err := sessions.GetUserRole(newRole)
if err != nil {
return err
}
@@ -316,7 +291,7 @@ func (o *orm) UpdateRole(email, newRole string) (User, error) {
}
// SetAuthToken updates the user to use the given Authentication Token.
-func (o *orm) SetPassword(user *User, newPassword string) error {
+func (o *orm) SetPassword(user *sessions.User, newPassword string) error {
hashedPassword, err := utils.HashPassword(newPassword)
if err != nil {
return err
@@ -325,7 +300,19 @@ func (o *orm) SetPassword(user *User, newPassword string) error {
return o.q.Get(user, sql, hashedPassword, user.Email)
}
-func (o *orm) CreateAndSetAuthToken(user *User) (*auth.Token, error) {
+// TestPassword checks plaintext user provided password with hashed database password, returns nil if matched
+func (o *orm) TestPassword(email string, password string) error {
+ var hashedPassword string
+ if err := o.q.Get(&hashedPassword, "SELECT hashed_password FROM users WHERE lower(email) = lower($1)", email); err != nil {
+ return errors.New("no matching user for provided email")
+ }
+ if !utils.CheckPasswordHash(password, hashedPassword) {
+ return errors.New("passwords don't match")
+ }
+ return nil
+}
+
+func (o *orm) CreateAndSetAuthToken(user *sessions.User) (*auth.Token, error) {
newToken := auth.NewToken()
err := o.SetAuthToken(user, newToken)
@@ -337,7 +324,7 @@ func (o *orm) CreateAndSetAuthToken(user *User) (*auth.Token, error) {
}
// SetAuthToken updates the user to use the given Authentication Token.
-func (o *orm) SetAuthToken(user *User, token *auth.Token) error {
+func (o *orm) SetAuthToken(user *sessions.User, token *auth.Token) error {
salt := utils.NewSecret(utils.DefaultSecretSize)
hashedSecret, err := auth.HashedSecret(token, salt)
if err != nil {
@@ -348,20 +335,20 @@ func (o *orm) SetAuthToken(user *User, token *auth.Token) error {
}
// DeleteAuthToken clears and disables the users Authentication Token.
-func (o *orm) DeleteAuthToken(user *User) error {
+func (o *orm) DeleteAuthToken(user *sessions.User) error {
sql := "UPDATE users SET token_salt = '', token_key = '', token_hashed_secret = '', updated_at = now() WHERE email = $1 RETURNING *"
return o.q.Get(user, sql, user.Email)
}
// SaveWebAuthn saves new WebAuthn token information.
-func (o *orm) SaveWebAuthn(token *WebAuthn) error {
+func (o *orm) SaveWebAuthn(token *sessions.WebAuthn) error {
sql := "INSERT INTO web_authns (email, public_key_data) VALUES ($1, $2)"
_, err := o.q.Exec(sql, token.Email, token.PublicKeyData)
return err
}
// Sessions returns all sessions limited by the parameters.
-func (o *orm) Sessions(offset, limit int) (sessions []Session, err error) {
+func (o *orm) Sessions(offset, limit int) (sessions []sessions.Session, err error) {
sql := `SELECT * FROM sessions ORDER BY created_at, id LIMIT $1 OFFSET $2;`
if err = o.q.Select(&sessions, sql, limit, offset); err != nil {
return
diff --git a/core/sessions/orm_test.go b/core/sessions/localauth/orm_test.go
similarity index 95%
rename from core/sessions/orm_test.go
rename to core/sessions/localauth/orm_test.go
index 5decb82308..7868937ad0 100644
--- a/core/sessions/orm_test.go
+++ b/core/sessions/localauth/orm_test.go
@@ -1,4 +1,4 @@
-package sessions_test
+package localauth_test
import (
"encoding/json"
@@ -7,6 +7,7 @@ import (
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
+
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -18,14 +19,15 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
-func setupORM(t *testing.T) (*sqlx.DB, sessions.ORM) {
+func setupORM(t *testing.T) (*sqlx.DB, sessions.AuthenticationProvider) {
t.Helper()
db := pgtest.NewSqlxDB(t)
- orm := sessions.NewORM(db, time.Minute, logger.TestLogger(t), pgtest.NewQConfig(true), &audit.AuditLoggerService{})
+ orm := localauth.NewORM(db, time.Minute, logger.TestLogger(t), pgtest.NewQConfig(true), &audit.AuditLoggerService{})
return db, orm
}
@@ -66,7 +68,7 @@ func TestORM_AuthorizedUserWithSession(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
db := pgtest.NewSqlxDB(t)
- orm := sessions.NewORM(db, test.sessionDuration, logger.TestLogger(t), pgtest.NewQConfig(true), &audit.AuditLoggerService{})
+ orm := localauth.NewORM(db, test.sessionDuration, logger.TestLogger(t), pgtest.NewQConfig(true), &audit.AuditLoggerService{})
user := cltest.MustRandomUser(t)
require.NoError(t, orm.CreateUser(&user))
diff --git a/core/sessions/reaper.go b/core/sessions/localauth/reaper.go
similarity index 98%
rename from core/sessions/reaper.go
rename to core/sessions/localauth/reaper.go
index c4f0ed6796..77d1b1abef 100644
--- a/core/sessions/reaper.go
+++ b/core/sessions/localauth/reaper.go
@@ -1,4 +1,4 @@
-package sessions
+package localauth
import (
"database/sql"
diff --git a/core/sessions/reaper_test.go b/core/sessions/localauth/reaper_test.go
similarity index 69%
rename from core/sessions/reaper_test.go
rename to core/sessions/localauth/reaper_test.go
index a96c3822ef..43a263d032 100644
--- a/core/sessions/reaper_test.go
+++ b/core/sessions/localauth/reaper_test.go
@@ -1,4 +1,4 @@
-package sessions_test
+package localauth_test
import (
"testing"
@@ -9,8 +9,10 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/sessions"
+ "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
+ "github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -31,10 +33,9 @@ func TestSessionReaper_ReapSessions(t *testing.T) {
db := pgtest.NewSqlxDB(t)
config := sessionReaperConfig{}
lggr := logger.TestLogger(t)
- orm := sessions.NewORM(db, config.SessionTimeout().Duration(), lggr, pgtest.NewQConfig(true), audit.NoopLogger)
-
- r := sessions.NewSessionReaper(db.DB, config, lggr)
+ orm := localauth.NewORM(db, config.SessionTimeout().Duration(), lggr, pgtest.NewQConfig(true), audit.NoopLogger)
+ r := localauth.NewSessionReaper(db.DB, config, lggr)
t.Cleanup(func() {
assert.NoError(t, r.Stop())
})
@@ -53,31 +54,28 @@ func TestSessionReaper_ReapSessions(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- user := cltest.MustRandomUser(t)
- require.NoError(t, orm.CreateUser(&user))
-
- session := sessions.NewSession()
- session.Email = user.Email
-
- _, err := db.Exec("INSERT INTO sessions (last_used, email, id, created_at) VALUES ($1, $2, $3, now())", test.lastUsed, user.Email, test.name)
- require.NoError(t, err)
-
t.Cleanup(func() {
- _, err2 := db.Exec("DELETE FROM sessions where email = $1", user.Email)
+ _, err2 := db.Exec("DELETE FROM sessions where email = $1", cltest.APIEmailAdmin)
require.NoError(t, err2)
})
+ _, err := db.Exec("INSERT INTO sessions (last_used, email, id, created_at) VALUES ($1, $2, $3, now())", test.lastUsed, cltest.APIEmailAdmin, test.name)
+ require.NoError(t, err)
+
r.WakeUp()
- <-r.(interface {
- WorkDone() <-chan struct{}
- }).WorkDone()
- sessions, err := orm.Sessions(0, 10)
- assert.NoError(t, err)
if test.wantReap {
- assert.Len(t, sessions, 0)
+ gomega.NewWithT(t).Eventually(func() []sessions.Session {
+ sessions, err := orm.Sessions(0, 10)
+ assert.NoError(t, err)
+ return sessions
+ }).Should(gomega.HaveLen(0))
} else {
- assert.Len(t, sessions, 1)
+ gomega.NewWithT(t).Consistently(func() []sessions.Session {
+ sessions, err := orm.Sessions(0, 10)
+ assert.NoError(t, err)
+ return sessions
+ }).Should(gomega.HaveLen(1))
}
})
}
diff --git a/core/sessions/mocks/orm.go b/core/sessions/mocks/authentication_provider.go
similarity index 75%
rename from core/sessions/mocks/orm.go
rename to core/sessions/mocks/authentication_provider.go
index 5699b9f889..d6e33d11e4 100644
--- a/core/sessions/mocks/orm.go
+++ b/core/sessions/mocks/authentication_provider.go
@@ -11,13 +11,13 @@ import (
sessions "github.com/smartcontractkit/chainlink/v2/core/sessions"
)
-// ORM is an autogenerated mock type for the ORM type
-type ORM struct {
+// AuthenticationProvider is an autogenerated mock type for the AuthenticationProvider type
+type AuthenticationProvider struct {
mock.Mock
}
// AuthorizedUserWithSession provides a mock function with given fields: sessionID
-func (_m *ORM) AuthorizedUserWithSession(sessionID string) (sessions.User, error) {
+func (_m *AuthenticationProvider) AuthorizedUserWithSession(sessionID string) (sessions.User, error) {
ret := _m.Called(sessionID)
var r0 sessions.User
@@ -41,7 +41,7 @@ func (_m *ORM) AuthorizedUserWithSession(sessionID string) (sessions.User, error
}
// ClearNonCurrentSessions provides a mock function with given fields: sessionID
-func (_m *ORM) ClearNonCurrentSessions(sessionID string) error {
+func (_m *AuthenticationProvider) ClearNonCurrentSessions(sessionID string) error {
ret := _m.Called(sessionID)
var r0 error
@@ -55,7 +55,7 @@ func (_m *ORM) ClearNonCurrentSessions(sessionID string) error {
}
// CreateAndSetAuthToken provides a mock function with given fields: user
-func (_m *ORM) CreateAndSetAuthToken(user *sessions.User) (*auth.Token, error) {
+func (_m *AuthenticationProvider) CreateAndSetAuthToken(user *sessions.User) (*auth.Token, error) {
ret := _m.Called(user)
var r0 *auth.Token
@@ -81,7 +81,7 @@ func (_m *ORM) CreateAndSetAuthToken(user *sessions.User) (*auth.Token, error) {
}
// CreateSession provides a mock function with given fields: sr
-func (_m *ORM) CreateSession(sr sessions.SessionRequest) (string, error) {
+func (_m *AuthenticationProvider) CreateSession(sr sessions.SessionRequest) (string, error) {
ret := _m.Called(sr)
var r0 string
@@ -105,7 +105,7 @@ func (_m *ORM) CreateSession(sr sessions.SessionRequest) (string, error) {
}
// CreateUser provides a mock function with given fields: user
-func (_m *ORM) CreateUser(user *sessions.User) error {
+func (_m *AuthenticationProvider) CreateUser(user *sessions.User) error {
ret := _m.Called(user)
var r0 error
@@ -119,7 +119,7 @@ func (_m *ORM) CreateUser(user *sessions.User) error {
}
// DeleteAuthToken provides a mock function with given fields: user
-func (_m *ORM) DeleteAuthToken(user *sessions.User) error {
+func (_m *AuthenticationProvider) DeleteAuthToken(user *sessions.User) error {
ret := _m.Called(user)
var r0 error
@@ -133,7 +133,7 @@ func (_m *ORM) DeleteAuthToken(user *sessions.User) error {
}
// DeleteUser provides a mock function with given fields: email
-func (_m *ORM) DeleteUser(email string) error {
+func (_m *AuthenticationProvider) DeleteUser(email string) error {
ret := _m.Called(email)
var r0 error
@@ -147,7 +147,7 @@ func (_m *ORM) DeleteUser(email string) error {
}
// DeleteUserSession provides a mock function with given fields: sessionID
-func (_m *ORM) DeleteUserSession(sessionID string) error {
+func (_m *AuthenticationProvider) DeleteUserSession(sessionID string) error {
ret := _m.Called(sessionID)
var r0 error
@@ -161,7 +161,7 @@ func (_m *ORM) DeleteUserSession(sessionID string) error {
}
// FindExternalInitiator provides a mock function with given fields: eia
-func (_m *ORM) FindExternalInitiator(eia *auth.Token) (*bridges.ExternalInitiator, error) {
+func (_m *AuthenticationProvider) FindExternalInitiator(eia *auth.Token) (*bridges.ExternalInitiator, error) {
ret := _m.Called(eia)
var r0 *bridges.ExternalInitiator
@@ -187,7 +187,7 @@ func (_m *ORM) FindExternalInitiator(eia *auth.Token) (*bridges.ExternalInitiato
}
// FindUser provides a mock function with given fields: email
-func (_m *ORM) FindUser(email string) (sessions.User, error) {
+func (_m *AuthenticationProvider) FindUser(email string) (sessions.User, error) {
ret := _m.Called(email)
var r0 sessions.User
@@ -211,7 +211,7 @@ func (_m *ORM) FindUser(email string) (sessions.User, error) {
}
// FindUserByAPIToken provides a mock function with given fields: apiToken
-func (_m *ORM) FindUserByAPIToken(apiToken string) (sessions.User, error) {
+func (_m *AuthenticationProvider) FindUserByAPIToken(apiToken string) (sessions.User, error) {
ret := _m.Called(apiToken)
var r0 sessions.User
@@ -235,7 +235,7 @@ func (_m *ORM) FindUserByAPIToken(apiToken string) (sessions.User, error) {
}
// GetUserWebAuthn provides a mock function with given fields: email
-func (_m *ORM) GetUserWebAuthn(email string) ([]sessions.WebAuthn, error) {
+func (_m *AuthenticationProvider) GetUserWebAuthn(email string) ([]sessions.WebAuthn, error) {
ret := _m.Called(email)
var r0 []sessions.WebAuthn
@@ -261,7 +261,7 @@ func (_m *ORM) GetUserWebAuthn(email string) ([]sessions.WebAuthn, error) {
}
// ListUsers provides a mock function with given fields:
-func (_m *ORM) ListUsers() ([]sessions.User, error) {
+func (_m *AuthenticationProvider) ListUsers() ([]sessions.User, error) {
ret := _m.Called()
var r0 []sessions.User
@@ -287,7 +287,7 @@ func (_m *ORM) ListUsers() ([]sessions.User, error) {
}
// SaveWebAuthn provides a mock function with given fields: token
-func (_m *ORM) SaveWebAuthn(token *sessions.WebAuthn) error {
+func (_m *AuthenticationProvider) SaveWebAuthn(token *sessions.WebAuthn) error {
ret := _m.Called(token)
var r0 error
@@ -301,7 +301,7 @@ func (_m *ORM) SaveWebAuthn(token *sessions.WebAuthn) error {
}
// Sessions provides a mock function with given fields: offset, limit
-func (_m *ORM) Sessions(offset int, limit int) ([]sessions.Session, error) {
+func (_m *AuthenticationProvider) Sessions(offset int, limit int) ([]sessions.Session, error) {
ret := _m.Called(offset, limit)
var r0 []sessions.Session
@@ -327,7 +327,7 @@ func (_m *ORM) Sessions(offset int, limit int) ([]sessions.Session, error) {
}
// SetAuthToken provides a mock function with given fields: user, token
-func (_m *ORM) SetAuthToken(user *sessions.User, token *auth.Token) error {
+func (_m *AuthenticationProvider) SetAuthToken(user *sessions.User, token *auth.Token) error {
ret := _m.Called(user, token)
var r0 error
@@ -341,7 +341,7 @@ func (_m *ORM) SetAuthToken(user *sessions.User, token *auth.Token) error {
}
// SetPassword provides a mock function with given fields: user, newPassword
-func (_m *ORM) SetPassword(user *sessions.User, newPassword string) error {
+func (_m *AuthenticationProvider) SetPassword(user *sessions.User, newPassword string) error {
ret := _m.Called(user, newPassword)
var r0 error
@@ -354,8 +354,22 @@ func (_m *ORM) SetPassword(user *sessions.User, newPassword string) error {
return r0
}
+// TestPassword provides a mock function with given fields: email, password
+func (_m *AuthenticationProvider) TestPassword(email string, password string) error {
+ ret := _m.Called(email, password)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string) error); ok {
+ r0 = rf(email, password)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
// UpdateRole provides a mock function with given fields: email, newRole
-func (_m *ORM) UpdateRole(email string, newRole string) (sessions.User, error) {
+func (_m *AuthenticationProvider) UpdateRole(email string, newRole string) (sessions.User, error) {
ret := _m.Called(email, newRole)
var r0 sessions.User
@@ -378,13 +392,13 @@ func (_m *ORM) UpdateRole(email string, newRole string) (sessions.User, error) {
return r0, r1
}
-// 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.
+// NewAuthenticationProvider creates a new instance of AuthenticationProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
-func NewORM(t interface {
+func NewAuthenticationProvider(t interface {
mock.TestingT
Cleanup(func())
-}) *ORM {
- mock := &ORM{}
+}) *AuthenticationProvider {
+ mock := &AuthenticationProvider{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
diff --git a/core/sessions/mocks/basic_admin_users_orm.go b/core/sessions/mocks/basic_admin_users_orm.go
new file mode 100644
index 0000000000..845e2d8880
--- /dev/null
+++ b/core/sessions/mocks/basic_admin_users_orm.go
@@ -0,0 +1,91 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package mocks
+
+import (
+ sessions "github.com/smartcontractkit/chainlink/v2/core/sessions"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// BasicAdminUsersORM is an autogenerated mock type for the BasicAdminUsersORM type
+type BasicAdminUsersORM struct {
+ mock.Mock
+}
+
+// CreateUser provides a mock function with given fields: user
+func (_m *BasicAdminUsersORM) CreateUser(user *sessions.User) error {
+ ret := _m.Called(user)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(*sessions.User) error); ok {
+ r0 = rf(user)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// FindUser provides a mock function with given fields: email
+func (_m *BasicAdminUsersORM) FindUser(email string) (sessions.User, error) {
+ ret := _m.Called(email)
+
+ var r0 sessions.User
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) (sessions.User, error)); ok {
+ return rf(email)
+ }
+ if rf, ok := ret.Get(0).(func(string) sessions.User); ok {
+ r0 = rf(email)
+ } else {
+ r0 = ret.Get(0).(sessions.User)
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(email)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ListUsers provides a mock function with given fields:
+func (_m *BasicAdminUsersORM) ListUsers() ([]sessions.User, error) {
+ ret := _m.Called()
+
+ var r0 []sessions.User
+ var r1 error
+ if rf, ok := ret.Get(0).(func() ([]sessions.User, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() []sessions.User); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]sessions.User)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewBasicAdminUsersORM creates a new instance of BasicAdminUsersORM. 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 NewBasicAdminUsersORM(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *BasicAdminUsersORM {
+ mock := &BasicAdminUsersORM{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/core/sessions/session.go b/core/sessions/session.go
new file mode 100644
index 0000000000..90964596e9
--- /dev/null
+++ b/core/sessions/session.go
@@ -0,0 +1,74 @@
+package sessions
+
+import (
+ "crypto/subtle"
+ "time"
+
+ "github.com/pkg/errors"
+ "gopkg.in/guregu/null.v4"
+
+ "github.com/smartcontractkit/chainlink/v2/core/auth"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+// SessionRequest encapsulates the fields needed to generate a new SessionID,
+// including the hashed password.
+type SessionRequest struct {
+ Email string `json:"email"`
+ Password string `json:"password"`
+ WebAuthnData string `json:"webauthndata"`
+ WebAuthnConfig WebAuthnConfiguration
+ SessionStore *WebAuthnSessionStore
+}
+
+// Session holds the unique id for the authenticated session.
+type Session struct {
+ ID string `json:"id"`
+ Email string `json:"email"`
+ LastUsed time.Time `json:"lastUsed"`
+ CreatedAt time.Time `json:"createdAt"`
+}
+
+// NewSession returns a session instance with ID set to a random ID and
+// LastUsed to now.
+func NewSession() Session {
+ return Session{
+ ID: utils.NewBytes32ID(),
+ LastUsed: time.Now(),
+ }
+}
+
+// Changeauth.TokenRequest is sent when updating a User's authentication token.
+type ChangeAuthTokenRequest struct {
+ Password string `json:"password"`
+}
+
+// GenerateAuthToken randomly generates and sets the users Authentication
+// Token.
+func (u *User) GenerateAuthToken() (*auth.Token, error) {
+ token := auth.NewToken()
+ return token, u.SetAuthToken(token)
+}
+
+// SetAuthToken updates the user to use the given Authentication Token.
+func (u *User) SetAuthToken(token *auth.Token) error {
+ salt := utils.NewSecret(utils.DefaultSecretSize)
+ hashedSecret, err := auth.HashedSecret(token, salt)
+ if err != nil {
+ return errors.Wrap(err, "user")
+ }
+ u.TokenSalt = null.StringFrom(salt)
+ u.TokenKey = null.StringFrom(token.AccessKey)
+ u.TokenHashedSecret = null.StringFrom(hashedSecret)
+ return nil
+}
+
+// AuthenticateUserByToken returns true on successful authentication of the
+// user against the given Authentication Token.
+func AuthenticateUserByToken(token *auth.Token, user *User) (bool, error) {
+ hashedSecret, err := auth.HashedSecret(token, user.TokenSalt.ValueOrZero())
+ if err != nil {
+ return false, err
+ }
+ return subtle.ConstantTimeCompare([]byte(hashedSecret), []byte(user.TokenHashedSecret.ValueOrZero())) == 1, nil
+}
diff --git a/core/sessions/user.go b/core/sessions/user.go
index a120874432..f2e4827b92 100644
--- a/core/sessions/user.go
+++ b/core/sessions/user.go
@@ -1,7 +1,6 @@
package sessions
import (
- "crypto/subtle"
"fmt"
"net/mail"
"time"
@@ -9,7 +8,6 @@ import (
"github.com/pkg/errors"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -108,65 +106,3 @@ func GetUserRole(role string) (UserRole, error) {
)
return UserRole(""), errors.New(errStr)
}
-
-// SessionRequest encapsulates the fields needed to generate a new SessionID,
-// including the hashed password.
-type SessionRequest struct {
- Email string `json:"email"`
- Password string `json:"password"`
- WebAuthnData string `json:"webauthndata"`
- WebAuthnConfig WebAuthnConfiguration
- SessionStore *WebAuthnSessionStore
-}
-
-// Session holds the unique id for the authenticated session.
-type Session struct {
- ID string `json:"id"`
- Email string `json:"email"`
- LastUsed time.Time `json:"lastUsed"`
- CreatedAt time.Time `json:"createdAt"`
-}
-
-// NewSession returns a session instance with ID set to a random ID and
-// LastUsed to now.
-func NewSession() Session {
- return Session{
- ID: utils.NewBytes32ID(),
- LastUsed: time.Now(),
- }
-}
-
-// Changeauth.TokenRequest is sent when updating a User's authentication token.
-type ChangeAuthTokenRequest struct {
- Password string `json:"password"`
-}
-
-// GenerateAuthToken randomly generates and sets the users Authentication
-// Token.
-func (u *User) GenerateAuthToken() (*auth.Token, error) {
- token := auth.NewToken()
- return token, u.SetAuthToken(token)
-}
-
-// SetAuthToken updates the user to use the given Authentication Token.
-func (u *User) SetAuthToken(token *auth.Token) error {
- salt := utils.NewSecret(utils.DefaultSecretSize)
- hashedSecret, err := auth.HashedSecret(token, salt)
- if err != nil {
- return errors.Wrap(err, "user")
- }
- u.TokenSalt = null.StringFrom(salt)
- u.TokenKey = null.StringFrom(token.AccessKey)
- u.TokenHashedSecret = null.StringFrom(hashedSecret)
- return nil
-}
-
-// AuthenticateUserByToken returns true on successful authentication of the
-// user against the given Authentication Token.
-func AuthenticateUserByToken(token *auth.Token, user *User) (bool, error) {
- hashedSecret, err := auth.HashedSecret(token, user.TokenSalt.ValueOrZero())
- if err != nil {
- return false, err
- }
- return subtle.ConstantTimeCompare([]byte(hashedSecret), []byte(user.TokenHashedSecret.ValueOrZero())) == 1, nil
-}
diff --git a/core/sessions/webauthn.go b/core/sessions/webauthn.go
index 0dd8242dc8..41e31d7aaa 100644
--- a/core/sessions/webauthn.go
+++ b/core/sessions/webauthn.go
@@ -279,7 +279,7 @@ func (store *WebAuthnSessionStore) GetWebauthnSession(key string) (data webauthn
return
}
-func AddCredentialToUser(o ORM, email string, credential *webauthn.Credential) error {
+func AddCredentialToUser(ap AuthenticationProvider, email string, credential *webauthn.Credential) error {
credj, err := json.Marshal(credential)
if err != nil {
return err
@@ -289,5 +289,5 @@ func AddCredentialToUser(o ORM, email string, credential *webauthn.Credential) e
Email: email,
PublicKeyData: sqlxTypes.JSONText(credj),
}
- return o.SaveWebAuthn(&token)
+ return ap.SaveWebAuthn(&token)
}
diff --git a/core/store/migrate/migrations/0208_create_ldap_sessions_table.sql b/core/store/migrate/migrations/0208_create_ldap_sessions_table.sql
new file mode 100644
index 0000000000..f788cdab07
--- /dev/null
+++ b/core/store/migrate/migrations/0208_create_ldap_sessions_table.sql
@@ -0,0 +1,22 @@
+-- +goose Up
+CREATE TABLE IF NOT EXISTS ldap_sessions (
+ id text PRIMARY KEY,
+ user_email text NOT NULL,
+ user_role user_roles,
+ localauth_user BOOLEAN,
+ created_at timestamp with time zone NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS ldap_user_api_tokens (
+ user_email text PRIMARY KEY,
+ user_role user_roles,
+ localauth_user BOOLEAN,
+ token_key text UNIQUE NOT NULL,
+ token_salt text NOT NULL,
+ token_hashed_secret text NOT NULL,
+ created_at timestamp with time zone NOT NULL
+);
+
+-- +goose Down
+DROP TABLE ldap_sessions;
+DROP TABLE ldap_user_api_tokens;
diff --git a/core/web/auth/auth.go b/core/web/auth/auth.go
index a0a9df58c7..c2458f5262 100644
--- a/core/web/auth/auth.go
+++ b/core/web/auth/auth.go
@@ -78,6 +78,9 @@ func AuthenticateByToken(c *gin.Context, authr Authenticator) error {
AccessKey: c.GetHeader(APIKey),
Secret: c.GetHeader(APISecret),
}
+ if token.AccessKey == "" {
+ return auth.ErrorAuthFailed
+ }
if token.AccessKey == "" {
return auth.ErrorAuthFailed
@@ -86,7 +89,7 @@ func AuthenticateByToken(c *gin.Context, authr Authenticator) error {
// We need to first load the user row so we can compare tokens using the stored salt
user, err := authr.FindUserByAPIToken(token.AccessKey)
if err != nil {
- if errors.Is(err, sql.ErrNoRows) {
+ if errors.Is(err, sql.ErrNoRows) || errors.Is(err, clsessions.ErrUserSessionExpired) {
return auth.ErrorAuthFailed
}
return err
diff --git a/core/web/auth/auth_test.go b/core/web/auth/auth_test.go
index 896542915a..f0b4e5068f 100644
--- a/core/web/auth/auth_test.go
+++ b/core/web/auth/auth_test.go
@@ -33,7 +33,7 @@ func authSuccess(*gin.Context, webauth.Authenticator) error {
}
type userFindFailer struct {
- sessions.ORM
+ sessions.AuthenticationProvider
err error
}
@@ -46,7 +46,7 @@ func (u userFindFailer) FindUserByAPIToken(token string) (sessions.User, error)
}
type userFindSuccesser struct {
- sessions.ORM
+ sessions.AuthenticationProvider
user sessions.User
}
diff --git a/core/web/auth/gql_test.go b/core/web/auth/gql_test.go
index 4688f62a33..4f3f8e27ba 100644
--- a/core/web/auth/gql_test.go
+++ b/core/web/auth/gql_test.go
@@ -21,7 +21,7 @@ import (
func Test_AuthenticateGQL_Unauthenticated(t *testing.T) {
t.Parallel()
- sessionORM := mocks.NewORM(t)
+ sessionORM := mocks.NewAuthenticationProvider(t)
sessionStore := cookie.NewStore([]byte("secret"))
r := gin.Default()
@@ -44,7 +44,7 @@ func Test_AuthenticateGQL_Unauthenticated(t *testing.T) {
func Test_AuthenticateGQL_Authenticated(t *testing.T) {
t.Parallel()
- sessionORM := mocks.NewORM(t)
+ sessionORM := mocks.NewAuthenticationProvider(t)
sessionStore := cookie.NewStore([]byte(cltest.SessionSecret))
sessionID := "sessionID"
diff --git a/core/web/resolver/api_token_test.go b/core/web/resolver/api_token_test.go
index b5ed52be3c..fae0204caf 100644
--- a/core/web/resolver/api_token_test.go
+++ b/core/web/resolver/api_token_test.go
@@ -39,6 +39,11 @@ func TestResolver_CreateAPIToken(t *testing.T) {
"password": defaultPassword,
},
}
+ variablesIncorrect := map[string]interface{}{
+ "input": map[string]interface{}{
+ "password": "wrong-password",
+ },
+ }
gError := errors.New("error")
testCases := []GQLTestCase{
@@ -56,12 +61,13 @@ func TestResolver_CreateAPIToken(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("CreateAndSetAuthToken", session.User).Return(&auth.Token{
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("TestPassword", session.User.Email, defaultPassword).Return(nil)
+ f.Mocks.authProvider.On("CreateAndSetAuthToken", session.User).Return(&auth.Token{
Secret: "new-secret",
AccessKey: "new-access-key",
}, nil)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -83,13 +89,12 @@ func TestResolver_CreateAPIToken(t *testing.T) {
require.True(t, ok)
require.NotNil(t, session)
- session.User.HashedPassword = "wrong-password"
-
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("TestPassword", session.User.Email, "wrong-password").Return(gError)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
- variables: variables,
+ variables: variablesIncorrect,
result: `
{
"createAPIToken": {
@@ -114,8 +119,8 @@ func TestResolver_CreateAPIToken(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, gError)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, gError)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -142,9 +147,10 @@ func TestResolver_CreateAPIToken(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("CreateAndSetAuthToken", session.User).Return(nil, gError)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("TestPassword", session.User.Email, defaultPassword).Return(nil)
+ f.Mocks.authProvider.On("CreateAndSetAuthToken", session.User).Return(nil, gError)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -189,6 +195,11 @@ func TestResolver_DeleteAPIToken(t *testing.T) {
"password": defaultPassword,
},
}
+ variablesIncorrect := map[string]interface{}{
+ "input": map[string]interface{}{
+ "password": "wrong-password",
+ },
+ }
gError := errors.New("error")
testCases := []GQLTestCase{
@@ -208,9 +219,10 @@ func TestResolver_DeleteAPIToken(t *testing.T) {
err = session.User.TokenKey.UnmarshalText([]byte("new-access-key"))
require.NoError(t, err)
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("DeleteAuthToken", session.User).Return(nil)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("TestPassword", session.User.Email, defaultPassword).Return(nil)
+ f.Mocks.authProvider.On("DeleteAuthToken", session.User).Return(nil)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -231,13 +243,12 @@ func TestResolver_DeleteAPIToken(t *testing.T) {
require.True(t, ok)
require.NotNil(t, session)
- session.User.HashedPassword = "wrong-password"
-
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("TestPassword", session.User.Email, "wrong-password").Return(gError)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
- variables: variables,
+ variables: variablesIncorrect,
result: `
{
"deleteAPIToken": {
@@ -262,8 +273,8 @@ func TestResolver_DeleteAPIToken(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, gError)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, gError)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -290,9 +301,10 @@ func TestResolver_DeleteAPIToken(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("DeleteAuthToken", session.User).Return(gError)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("TestPassword", session.User.Email, defaultPassword).Return(nil)
+ f.Mocks.authProvider.On("DeleteAuthToken", session.User).Return(gError)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go
index 68cbb0b789..f9eee0734a 100644
--- a/core/web/resolver/mutation.go
+++ b/core/web/resolver/mutation.go
@@ -882,7 +882,7 @@ func (r *Resolver) UpdateUserPassword(ctx context.Context, args struct {
return nil, errors.New("couldn't retrieve user session")
}
- dbUser, err := r.App.SessionORM().FindUser(session.User.Email)
+ dbUser, err := r.App.AuthenticationProvider().FindUser(session.User.Email)
if err != nil {
return nil, err
}
@@ -895,11 +895,11 @@ func (r *Resolver) UpdateUserPassword(ctx context.Context, args struct {
}), nil
}
- if err = r.App.SessionORM().ClearNonCurrentSessions(session.SessionID); err != nil {
+ if err = r.App.AuthenticationProvider().ClearNonCurrentSessions(session.SessionID); err != nil {
return nil, clearSessionsError{}
}
- err = r.App.SessionORM().SetPassword(&dbUser, args.Input.NewPassword)
+ err = r.App.AuthenticationProvider().SetPassword(&dbUser, args.Input.NewPassword)
if err != nil {
return nil, failedPasswordUpdateError{}
}
@@ -937,12 +937,13 @@ func (r *Resolver) CreateAPIToken(ctx context.Context, args struct {
if !ok {
return nil, errors.New("Failed to obtain current user from context")
}
- dbUser, err := r.App.SessionORM().FindUser(session.User.Email)
+ dbUser, err := r.App.AuthenticationProvider().FindUser(session.User.Email)
if err != nil {
return nil, err
}
- if !utils.CheckPasswordHash(args.Input.Password, dbUser.HashedPassword) {
+ err = r.App.AuthenticationProvider().TestPassword(dbUser.Email, args.Input.Password)
+ if err != nil {
r.App.GetAuditLogger().Audit(audit.APITokenCreateAttemptPasswordMismatch, map[string]interface{}{"user": dbUser.Email})
return NewCreateAPITokenPayload(nil, map[string]string{
@@ -950,7 +951,7 @@ func (r *Resolver) CreateAPIToken(ctx context.Context, args struct {
}), nil
}
- newToken, err := r.App.SessionORM().CreateAndSetAuthToken(&dbUser)
+ newToken, err := r.App.AuthenticationProvider().CreateAndSetAuthToken(&dbUser)
if err != nil {
return nil, err
}
@@ -970,12 +971,13 @@ func (r *Resolver) DeleteAPIToken(ctx context.Context, args struct {
if !ok {
return nil, errors.New("Failed to obtain current user from context")
}
- dbUser, err := r.App.SessionORM().FindUser(session.User.Email)
+ dbUser, err := r.App.AuthenticationProvider().FindUser(session.User.Email)
if err != nil {
return nil, err
}
- if !utils.CheckPasswordHash(args.Input.Password, dbUser.HashedPassword) {
+ err = r.App.AuthenticationProvider().TestPassword(dbUser.Email, args.Input.Password)
+ if err != nil {
r.App.GetAuditLogger().Audit(audit.APITokenDeleteAttemptPasswordMismatch, map[string]interface{}{"user": dbUser.Email})
return NewDeleteAPITokenPayload(nil, map[string]string{
@@ -983,7 +985,7 @@ func (r *Resolver) DeleteAPIToken(ctx context.Context, args struct {
}), nil
}
- err = r.App.SessionORM().DeleteAuthToken(&dbUser)
+ err = r.App.AuthenticationProvider().DeleteAuthToken(&dbUser)
if err != nil {
return nil, err
}
diff --git a/core/web/resolver/resolver_test.go b/core/web/resolver/resolver_test.go
index fa8471c5e2..85c495faaa 100644
--- a/core/web/resolver/resolver_test.go
+++ b/core/web/resolver/resolver_test.go
@@ -27,7 +27,7 @@ import (
pipelineMocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks"
webhookmocks "github.com/smartcontractkit/chainlink/v2/core/services/webhook/mocks"
clsessions "github.com/smartcontractkit/chainlink/v2/core/sessions"
- sessionsMocks "github.com/smartcontractkit/chainlink/v2/core/sessions/mocks"
+ authProviderMocks "github.com/smartcontractkit/chainlink/v2/core/sessions/mocks"
"github.com/smartcontractkit/chainlink/v2/core/web/auth"
"github.com/smartcontractkit/chainlink/v2/core/web/loader"
"github.com/smartcontractkit/chainlink/v2/core/web/schema"
@@ -37,7 +37,7 @@ type mocks struct {
bridgeORM *bridgeORMMocks.ORM
evmORM *evmtest.TestConfigs
jobORM *jobORMMocks.ORM
- sessionsORM *sessionsMocks.ORM
+ authProvider *authProviderMocks.AuthenticationProvider
pipelineORM *pipelineMocks.ORM
feedsSvc *feedsMocks.Service
cfg *chainlinkMocks.GeneralConfig
@@ -97,7 +97,7 @@ func setupFramework(t *testing.T) *gqlTestFramework {
evmORM: evmtest.NewTestConfigs(),
jobORM: jobORMMocks.NewORM(t),
feedsSvc: feedsMocks.NewService(t),
- sessionsORM: sessionsMocks.NewORM(t),
+ authProvider: authProviderMocks.NewAuthenticationProvider(t),
pipelineORM: pipelineMocks.NewORM(t),
cfg: chainlinkMocks.NewGeneralConfig(t),
scfg: evmConfigMocks.NewChainScopedConfig(t),
diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml
index 48d432138a..f5d775fe74 100644
--- a/core/web/resolver/testdata/config-empty-effective.toml
+++ b/core/web/resolver/testdata/config-empty-effective.toml
@@ -61,6 +61,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -73,6 +74,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml
index f44f119075..95d898c353 100644
--- a/core/web/resolver/testdata/config-full.toml
+++ b/core/web/resolver/testdata/config-full.toml
@@ -67,6 +67,7 @@ MaxAgeDays = 17
MaxBackups = 9
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = '*'
BridgeResponseURL = 'https://bridge.response'
BridgeCacheTTL = '10s'
@@ -79,6 +80,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '192.158.1.37'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = 'test-rpid'
RPOrigin = 'test-rp-origin'
diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml
index 1dcbfe3a83..9dd0be8f5d 100644
--- a/core/web/resolver/testdata/config-multi-chain-effective.toml
+++ b/core/web/resolver/testdata/config-multi-chain-effective.toml
@@ -61,6 +61,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -73,6 +74,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/core/web/resolver/user_test.go b/core/web/resolver/user_test.go
index e3808eebcb..bc64beeb45 100644
--- a/core/web/resolver/user_test.go
+++ b/core/web/resolver/user_test.go
@@ -53,10 +53,10 @@ func TestResolver_UpdateUserPassword(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("SetPassword", session.User, "new").Return(nil)
- f.Mocks.sessionsORM.On("ClearNonCurrentSessions", session.SessionID).Return(nil)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("SetPassword", session.User, "new").Return(nil)
+ f.Mocks.authProvider.On("ClearNonCurrentSessions", session.SessionID).Return(nil)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -79,8 +79,8 @@ func TestResolver_UpdateUserPassword(t *testing.T) {
session.User.HashedPassword = "random-string"
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -108,11 +108,11 @@ func TestResolver_UpdateUserPassword(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("ClearNonCurrentSessions", session.SessionID).Return(
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("ClearNonCurrentSessions", session.SessionID).Return(
clearSessionsError{},
)
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
@@ -139,10 +139,10 @@ func TestResolver_UpdateUserPassword(t *testing.T) {
session.User.HashedPassword = pwd
- f.Mocks.sessionsORM.On("FindUser", session.User.Email).Return(*session.User, nil)
- f.Mocks.sessionsORM.On("ClearNonCurrentSessions", session.SessionID).Return(nil)
- f.Mocks.sessionsORM.On("SetPassword", session.User, "new").Return(failedPasswordUpdateError{})
- f.App.On("SessionORM").Return(f.Mocks.sessionsORM)
+ f.Mocks.authProvider.On("FindUser", session.User.Email).Return(*session.User, nil)
+ f.Mocks.authProvider.On("ClearNonCurrentSessions", session.SessionID).Return(nil)
+ f.Mocks.authProvider.On("SetPassword", session.User, "new").Return(failedPasswordUpdateError{})
+ f.App.On("AuthenticationProvider").Return(f.Mocks.authProvider)
},
query: mutation,
variables: variables,
diff --git a/core/web/router.go b/core/web/router.go
index a873f14b70..28bd4f2170 100644
--- a/core/web/router.go
+++ b/core/web/router.go
@@ -90,7 +90,7 @@ func NewRouter(app chainlink.Application, prometheus *ginprom.Prometheus) (*gin.
guiAssetRoutes(engine, config.Insecure().DisableRateLimiting(), app.GetLogger())
api.POST("/query",
- auth.AuthenticateGQL(app.SessionORM(), app.GetLogger().Named("GQLHandler")),
+ auth.AuthenticateGQL(app.AuthenticationProvider(), app.GetLogger().Named("GQLHandler")),
loader.Middleware(app),
graphqlHandler(app),
)
@@ -170,7 +170,7 @@ func secureMiddleware(tlsRedirect bool, tlsHost string, devWebServer bool) gin.H
}
func debugRoutes(app chainlink.Application, r *gin.RouterGroup) {
- group := r.Group("/debug", auth.Authenticate(app.SessionORM(), auth.AuthenticateBySession))
+ group := r.Group("/debug", auth.Authenticate(app.AuthenticationProvider(), auth.AuthenticateBySession))
group.GET("/vars", expvar.Handler())
}
@@ -207,7 +207,7 @@ func sessionRoutes(app chainlink.Application, r *gin.RouterGroup) {
))
sc := NewSessionsController(app)
unauth.POST("/sessions", sc.Create)
- auth := r.Group("/", auth.Authenticate(app.SessionORM(), auth.AuthenticateBySession))
+ auth := r.Group("/", auth.Authenticate(app.AuthenticationProvider(), auth.AuthenticateBySession))
auth.DELETE("/sessions", sc.Destroy)
}
@@ -231,7 +231,7 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) {
psec := PipelineJobSpecErrorsController{app}
unauthedv2.PATCH("/resume/:runID", prc.Resume)
- authv2 := r.Group("/v2", auth.Authenticate(app.SessionORM(),
+ authv2 := r.Group("/v2", auth.Authenticate(app.AuthenticationProvider(),
auth.AuthenticateByToken,
auth.AuthenticateBySession,
))
@@ -301,7 +301,7 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) {
// duplicated from above, with `evm` instead of `eth`
// legacy ones remain for backwards compatibility
- ethKeysGroup := authv2.Group("", auth.Authenticate(app.SessionORM(),
+ ethKeysGroup := authv2.Group("", auth.Authenticate(app.AuthenticationProvider(),
auth.AuthenticateByToken,
auth.AuthenticateBySession,
))
@@ -427,7 +427,7 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) {
}
ping := PingController{app}
- userOrEI := r.Group("/v2", auth.Authenticate(app.SessionORM(),
+ userOrEI := r.Group("/v2", auth.Authenticate(app.AuthenticationProvider(),
auth.AuthenticateExternalInitiator,
auth.AuthenticateByToken,
auth.AuthenticateBySession,
diff --git a/core/web/sessions_controller.go b/core/web/sessions_controller.go
index 6f029456bd..23ecfd3b79 100644
--- a/core/web/sessions_controller.go
+++ b/core/web/sessions_controller.go
@@ -39,7 +39,7 @@ func (sc *SessionsController) Create(c *gin.Context) {
}
// Does this user have 2FA enabled?
- userWebAuthnTokens, err := sc.App.SessionORM().GetUserWebAuthn(sr.Email)
+ userWebAuthnTokens, err := sc.App.AuthenticationProvider().GetUserWebAuthn(sr.Email)
if err != nil {
sc.App.GetLogger().Errorf("Error loading user WebAuthn data: %s", err)
jsonAPIError(c, http.StatusInternalServerError, errors.New("internal Server Error"))
@@ -53,7 +53,7 @@ func (sc *SessionsController) Create(c *gin.Context) {
sr.WebAuthnConfig = sc.App.GetWebAuthnConfiguration()
}
- sid, err := sc.App.SessionORM().CreateSession(sr)
+ sid, err := sc.App.AuthenticationProvider().CreateSession(sr)
if err != nil {
jsonAPIError(c, http.StatusUnauthorized, err)
return
@@ -78,7 +78,7 @@ func (sc *SessionsController) Destroy(c *gin.Context) {
jsonAPIResponse(c, Session{Authenticated: false}, "session")
return
}
- if err := sc.App.SessionORM().DeleteUserSession(sessionID); err != nil {
+ if err := sc.App.AuthenticationProvider().DeleteUserSession(sessionID); err != nil {
jsonAPIError(c, http.StatusInternalServerError, err)
return
}
diff --git a/core/web/sessions_controller_test.go b/core/web/sessions_controller_test.go
index 7184e3f95b..c2950caf3d 100644
--- a/core/web/sessions_controller_test.go
+++ b/core/web/sessions_controller_test.go
@@ -27,7 +27,7 @@ func TestSessionsController_Create(t *testing.T) {
require.NoError(t, app.Start(testutils.Context(t)))
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.AuthenticationProvider().CreateUser(&user))
client := clhttptest.NewTestLocalOnlyHTTPClient()
tests := []struct {
@@ -59,7 +59,7 @@ func TestSessionsController_Create(t *testing.T) {
decrypted, err := cltest.DecodeSessionCookie(sessionCookie.Value)
require.NoError(t, err)
- user, err := app.SessionORM().AuthorizedUserWithSession(decrypted)
+ user, err := app.AuthenticationProvider().AuthorizedUserWithSession(decrypted)
assert.NoError(t, err)
assert.Equal(t, test.email, user.Email)
@@ -69,7 +69,7 @@ func TestSessionsController_Create(t *testing.T) {
} else {
require.True(t, resp.StatusCode >= 400, "Should not be able to create session")
// Ignore fixture session
- sessions, err := app.SessionORM().Sessions(1, 2)
+ sessions, err := app.AuthenticationProvider().Sessions(1, 2)
assert.NoError(t, err)
assert.Empty(t, sessions)
}
@@ -90,7 +90,7 @@ func TestSessionsController_Create_ReapSessions(t *testing.T) {
require.NoError(t, app.Start(testutils.Context(t)))
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.AuthenticationProvider().CreateUser(&user))
staleSession := cltest.NewSession()
staleSession.LastUsed = time.Now().Add(-cltest.MustParseDuration(t, "241h"))
@@ -107,7 +107,7 @@ func TestSessionsController_Create_ReapSessions(t *testing.T) {
var s []sessions.Session
gomega.NewWithT(t).Eventually(func() []sessions.Session {
- s, err = app.SessionORM().Sessions(0, 10)
+ s, err = app.AuthenticationProvider().Sessions(0, 10)
assert.NoError(t, err)
return s
}).Should(gomega.HaveLen(1))
@@ -124,7 +124,7 @@ func TestSessionsController_Destroy(t *testing.T) {
require.NoError(t, app.Start(testutils.Context(t)))
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.AuthenticationProvider().CreateUser(&user))
correctSession := sessions.NewSession()
correctSession.Email = user.Email
@@ -150,7 +150,7 @@ func TestSessionsController_Destroy(t *testing.T) {
resp, err := client.Do(request)
assert.NoError(t, err)
- _, err = app.SessionORM().AuthorizedUserWithSession(test.sessionID)
+ _, err = app.AuthenticationProvider().AuthorizedUserWithSession(test.sessionID)
assert.Error(t, err)
if test.success {
assert.Equal(t, http.StatusOK, resp.StatusCode)
@@ -170,7 +170,7 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) {
require.NoError(t, app.Start(testutils.Context(t)))
user := cltest.MustRandomUser(t)
- require.NoError(t, app.SessionORM().CreateUser(&user))
+ require.NoError(t, app.AuthenticationProvider().CreateUser(&user))
correctSession := sessions.NewSession()
correctSession.Email = user.Email
@@ -192,7 +192,7 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.StatusCode)
gomega.NewWithT(t).Eventually(func() []sessions.Session {
- sessions, err := app.SessionORM().Sessions(0, 10)
+ sessions, err := app.AuthenticationProvider().Sessions(0, 10)
assert.NoError(t, err)
return sessions
}).Should(gomega.HaveLen(0))
diff --git a/core/web/user_controller.go b/core/web/user_controller.go
index 115971eafc..857fff7b37 100644
--- a/core/web/user_controller.go
+++ b/core/web/user_controller.go
@@ -30,10 +30,16 @@ type UpdatePasswordRequest struct {
NewPassword string `json:"newPassword"`
}
+var errUnsupportedForAuth = errors.New("action is unsupported with configured authentication provider")
+
// Index lists all API users
func (c *UserController) Index(ctx *gin.Context) {
- users, err := c.App.SessionORM().ListUsers()
+ users, err := c.App.AuthenticationProvider().ListUsers()
if err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
c.App.GetLogger().Errorf("Unable to list users", "err", err)
jsonAPIError(ctx, http.StatusInternalServerError, err)
return
@@ -76,7 +82,7 @@ func (c *UserController) Create(ctx *gin.Context) {
jsonAPIError(ctx, http.StatusBadRequest, errors.Errorf("error creating API user: %s", err))
return
}
- if err = c.App.SessionORM().CreateUser(&user); err != nil {
+ if err = c.App.AuthenticationProvider().CreateUser(&user); err != nil {
// If this is a duplicate key error (code 23505), return a nicer error message
var pgErr *pgconn.PgError
if ok := errors.As(err, &pgErr); ok {
@@ -85,6 +91,10 @@ func (c *UserController) Create(ctx *gin.Context) {
return
}
}
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
c.App.GetLogger().Errorf("Error creating new API user", "err", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("error creating API user"))
return
@@ -132,8 +142,12 @@ func (c *UserController) UpdateRole(ctx *gin.Context) {
return
}
- user, err := c.App.SessionORM().UpdateRole(request.Email, request.NewRole)
+ user, err := c.App.AuthenticationProvider().UpdateRole(request.Email, request.NewRole)
if err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
jsonAPIError(ctx, http.StatusInternalServerError, errors.Wrap(err, "error updating API user"))
return
}
@@ -146,8 +160,12 @@ func (c *UserController) Delete(ctx *gin.Context) {
email := ctx.Param("email")
// Attempt find user by email
- user, err := c.App.SessionORM().FindUser(email)
+ user, err := c.App.AuthenticationProvider().FindUser(email)
if err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
jsonAPIError(ctx, http.StatusBadRequest, errors.Errorf("specified user not found: %s", email))
return
}
@@ -163,7 +181,11 @@ func (c *UserController) Delete(ctx *gin.Context) {
return
}
- if err = c.App.SessionORM().DeleteUser(email); err != nil {
+ if err = c.App.AuthenticationProvider().DeleteUser(email); err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
c.App.GetLogger().Errorf("Error deleting API user", "err", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("error deleting API user"))
return
@@ -185,8 +207,12 @@ func (c *UserController) UpdatePassword(ctx *gin.Context) {
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("failed to obtain current user from context"))
return
}
- user, err := c.App.SessionORM().FindUser(sessionUser.Email)
+ user, err := c.App.AuthenticationProvider().FindUser(sessionUser.Email)
if err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
c.App.GetLogger().Errorf("failed to obtain current user record: %s", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("unable to update password"))
return
@@ -222,19 +248,29 @@ func (c *UserController) NewAPIToken(ctx *gin.Context) {
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("failed to obtain current user from context"))
return
}
- user, err := c.App.SessionORM().FindUser(sessionUser.Email)
+ user, err := c.App.AuthenticationProvider().FindUser(sessionUser.Email)
if err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
c.App.GetLogger().Errorf("failed to obtain current user record: %s", err)
- jsonAPIError(ctx, http.StatusInternalServerError, errors.New("unable to creatae API token"))
+ jsonAPIError(ctx, http.StatusInternalServerError, errors.New("unable to create API token"))
return
}
- if !utils.CheckPasswordHash(request.Password, user.HashedPassword) {
+ // In order to create an API token, login validation with provided password must succeed
+ err = c.App.AuthenticationProvider().TestPassword(sessionUser.Email, request.Password)
+ if err != nil {
c.App.GetAuditLogger().Audit(audit.APITokenCreateAttemptPasswordMismatch, map[string]interface{}{"user": user.Email})
jsonAPIError(ctx, http.StatusUnauthorized, errors.New("incorrect password"))
return
}
newToken := auth.NewToken()
- if err := c.App.SessionORM().SetAuthToken(&user, newToken); err != nil {
+ if err := c.App.AuthenticationProvider().SetAuthToken(&user, newToken); err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
jsonAPIError(ctx, http.StatusInternalServerError, err)
return
}
@@ -256,18 +292,27 @@ func (c *UserController) DeleteAPIToken(ctx *gin.Context) {
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("failed to obtain current user from context"))
return
}
- user, err := c.App.SessionORM().FindUser(sessionUser.Email)
+ user, err := c.App.AuthenticationProvider().FindUser(sessionUser.Email)
if err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
c.App.GetLogger().Errorf("failed to obtain current user record: %s", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("unable to delete API token"))
return
}
- if !utils.CheckPasswordHash(request.Password, user.HashedPassword) {
+ err = c.App.AuthenticationProvider().TestPassword(sessionUser.Email, request.Password)
+ if err != nil {
c.App.GetAuditLogger().Audit(audit.APITokenDeleteAttemptPasswordMismatch, map[string]interface{}{"user": user.Email})
jsonAPIError(ctx, http.StatusUnauthorized, errors.New("incorrect password"))
return
}
- if err := c.App.SessionORM().DeleteAuthToken(&user); err != nil {
+ if err := c.App.AuthenticationProvider().DeleteAuthToken(&user); err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ jsonAPIError(ctx, http.StatusBadRequest, errUnsupportedForAuth)
+ return
+ }
jsonAPIError(ctx, http.StatusInternalServerError, err)
return
}
@@ -291,12 +336,15 @@ func (c *UserController) updateUserPassword(ctx *gin.Context, user *clsession.Us
if err != nil {
return err
}
- orm := c.App.SessionORM()
+ orm := c.App.AuthenticationProvider()
if err := orm.ClearNonCurrentSessions(sessionID); err != nil {
c.App.GetLogger().Errorf("failed to clear non current user sessions: %s", err)
return errors.New("unable to update password")
}
if err := orm.SetPassword(user, newPassword); err != nil {
+ if errors.Is(err, clsession.ErrNotSupported) {
+ return errUnsupportedForAuth
+ }
c.App.GetLogger().Errorf("failed to update current user password: %s", err)
return errors.New("unable to update password")
}
diff --git a/core/web/user_controller_test.go b/core/web/user_controller_test.go
index a11082ff6a..6baab1c396 100644
--- a/core/web/user_controller_test.go
+++ b/core/web/user_controller_test.go
@@ -188,7 +188,7 @@ func TestUserController_UpdateRole(t *testing.T) {
client := app.NewHTTPClient(nil)
user := cltest.MustRandomUser(t)
- err := app.SessionORM().CreateUser(&user)
+ err := app.AuthenticationProvider().CreateUser(&user)
require.NoError(t, err)
testCases := []struct {
@@ -235,7 +235,7 @@ func TestUserController_DeleteUser(t *testing.T) {
client := app.NewHTTPClient(nil)
user := cltest.MustRandomUser(t)
- err := app.SessionORM().CreateUser(&user)
+ err := app.AuthenticationProvider().CreateUser(&user)
require.NoError(t, err)
resp, cleanup := client.Delete(fmt.Sprintf("/v2/users/%s", url.QueryEscape(user.Email)))
diff --git a/core/web/webauthn_controller.go b/core/web/webauthn_controller.go
index 0509001323..41c8f268ad 100644
--- a/core/web/webauthn_controller.go
+++ b/core/web/webauthn_controller.go
@@ -36,7 +36,7 @@ func (c *WebAuthnController) BeginRegistration(ctx *gin.Context) {
return
}
- orm := c.App.SessionORM()
+ orm := c.App.AuthenticationProvider()
uwas, err := orm.GetUserWebAuthn(user.Email)
if err != nil {
c.App.GetLogger().Errorf("failed to obtain current user MFA tokens: error in GetUserWebAuthn: %+v", err)
@@ -66,7 +66,7 @@ func (c *WebAuthnController) FinishRegistration(ctx *gin.Context) {
return
}
- orm := c.App.SessionORM()
+ orm := c.App.AuthenticationProvider()
uwas, err := orm.GetUserWebAuthn(user.Email)
if err != nil {
c.App.GetLogger().Errorf("failed to obtain current user MFA tokens: error in GetUserWebAuthn: %s", err)
@@ -83,7 +83,7 @@ func (c *WebAuthnController) FinishRegistration(ctx *gin.Context) {
return
}
- if sessions.AddCredentialToUser(c.App.SessionORM(), user.Email, credential) != nil {
+ if sessions.AddCredentialToUser(c.App.AuthenticationProvider(), user.Email, credential) != nil {
c.App.GetLogger().Errorf("Could not save WebAuthn credential to DB for user: %s", user.Email)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("internal Server Error"))
return
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 8f3b16c132..b5b393542b 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [dev]
+### Added
+
+- Added a new, optional WebServer authentication option that supports LDAP as a user identity provider. This enables user login access and user roles to be managed and provisioned via a centralized remote server that supports the LDAP protocol, which can be helpful when running multiple nodes. See the documentation for more information and config setup instructions. There is a new `[WebServer].AuthenticationMethod` config option, when set to `ldap` requires the new `[WebServer.LDAP]` config section to be defined, see the reference `docs/core.toml`.
+
+
### Changed
- `L2Suggested` mode is now called `SuggestedPrice`
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 313e7b46aa..23508df172 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -459,6 +459,7 @@ MaxBackups determines the maximum number of old log files to retain. Keeping thi
## WebServer
```toml
[WebServer]
+AuthenticationMethod = 'local' # Default
AllowOrigins = 'http://localhost:3000,http://localhost:6688' # Default
BridgeCacheTTL = '0s' # Default
BridgeResponseURL = 'https://my-chainlink-node.example.com:6688' # Example
@@ -473,6 +474,12 @@ ListenIP = '0.0.0.0' # Default
```
+### AuthenticationMethod
+```toml
+AuthenticationMethod = 'local' # Default
+```
+AuthenticationMethod defines which pluggable auth interface to use for user login and role assumption. Options include 'local' and 'ldap'. See docs for more details
+
### AllowOrigins
```toml
AllowOrigins = 'http://localhost:3000,http://localhost:6688' # Default
@@ -546,6 +553,132 @@ ListenIP = '0.0.0.0' # Default
```
ListenIP specifies the IP to bind the HTTP server to
+## WebServer.LDAP
+```toml
+[WebServer.LDAP]
+ServerTLS = true # Default
+SessionTimeout = '15m0s' # Default
+QueryTimeout = '2m0s' # Default
+BaseUserAttr = 'uid' # Default
+BaseDN = 'dc=custom,dc=example,dc=com' # Example
+UsersDN = 'ou=users' # Default
+GroupsDN = 'ou=groups' # Default
+ActiveAttribute = '' # Default
+ActiveAttributeAllowedValue = '' # Default
+AdminUserGroupCN = 'NodeAdmins' # Default
+EditUserGroupCN = 'NodeEditors' # Default
+RunUserGroupCN = 'NodeRunners' # Default
+ReadUserGroupCN = 'NodeReadOnly' # Default
+UserApiTokenEnabled = false # Default
+UserAPITokenDuration = '240h0m0s' # Default
+UpstreamSyncInterval = '0s' # Default
+UpstreamSyncRateLimit = '2m0s' # Default
+```
+Optional LDAP config if WebServer.AuthenticationMethod is set to 'ldap'
+LDAP queries are all parameterized to support custom LDAP 'dn', 'cn', and attributes
+
+### ServerTLS
+```toml
+ServerTLS = true # Default
+```
+ServerTLS defines the option to require the secure ldaps
+
+### SessionTimeout
+```toml
+SessionTimeout = '15m0s' # Default
+```
+SessionTimeout determines the amount of idle time to elapse before session cookies expire. This signs out GUI users from their sessions.
+
+### QueryTimeout
+```toml
+QueryTimeout = '2m0s' # Default
+```
+QueryTimeout defines how long queries should wait before timing out, defined in seconds
+
+### BaseUserAttr
+```toml
+BaseUserAttr = 'uid' # Default
+```
+BaseUserAttr defines the base attribute used to populate LDAP queries such as "uid=$", default is example
+
+### BaseDN
+```toml
+BaseDN = 'dc=custom,dc=example,dc=com' # Example
+```
+BaseDN defines the base LDAP 'dn' search filter to apply to every LDAP query, replace example,com with the appropriate LDAP server's structure
+
+### UsersDN
+```toml
+UsersDN = 'ou=users' # Default
+```
+UsersDN defines the 'dn' query to use when querying for the 'users' 'ou' group
+
+### GroupsDN
+```toml
+GroupsDN = 'ou=groups' # Default
+```
+GroupsDN defines the 'dn' query to use when querying for the 'groups' 'ou' group
+
+### ActiveAttribute
+```toml
+ActiveAttribute = '' # Default
+```
+ActiveAttribute is an optional user field to check truthiness for if a user is valid/active. This is only required if the LDAP provider lists inactive users as members of groups
+
+### ActiveAttributeAllowedValue
+```toml
+ActiveAttributeAllowedValue = '' # Default
+```
+ActiveAttributeAllowedValue is the value to check against for the above optional user attribute
+
+### AdminUserGroupCN
+```toml
+AdminUserGroupCN = 'NodeAdmins' # Default
+```
+AdminUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Admin' role
+
+### EditUserGroupCN
+```toml
+EditUserGroupCN = 'NodeEditors' # Default
+```
+EditUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Edit' role
+
+### RunUserGroupCN
+```toml
+RunUserGroupCN = 'NodeRunners' # Default
+```
+RunUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Run' role
+
+### ReadUserGroupCN
+```toml
+ReadUserGroupCN = 'NodeReadOnly' # Default
+```
+ReadUserGroupCN is the LDAP 'cn' of the LDAP group that maps the core node's 'Read' role
+
+### UserApiTokenEnabled
+```toml
+UserApiTokenEnabled = false # Default
+```
+UserApiTokenEnabled enables the users to issue API tokens with the same access of their role
+
+### UserAPITokenDuration
+```toml
+UserAPITokenDuration = '240h0m0s' # Default
+```
+UserAPITokenDuration is the duration of time an API token is active for before expiring
+
+### UpstreamSyncInterval
+```toml
+UpstreamSyncInterval = '0s' # Default
+```
+UpstreamSyncInterval is the interval at which the background LDAP sync task will be called. A '0s' value disables the background sync being run on an interval. This check is already performed during login/logout actions, all sessions and API tokens stored in the local ldap tables are updated to match the remote server
+
+### UpstreamSyncRateLimit
+```toml
+UpstreamSyncRateLimit = '2m0s' # Default
+```
+UpstreamSyncRateLimit defines a duration to limit the number of query/API calls to the upstream LDAP provider. It prevents the sync functionality from being called multiple times within the defined duration
+
## WebServer.RateLimit
```toml
[WebServer.RateLimit]
diff --git a/docs/SECRETS.md b/docs/SECRETS.md
index af316cab14..fa7ba76df4 100644
--- a/docs/SECRETS.md
+++ b/docs/SECRETS.md
@@ -51,6 +51,33 @@ AllowSimplePasswords skips the password complexity check normally enforced on UR
Environment variable: `CL_DATABASE_ALLOW_SIMPLE_PASSWORDS`
+## WebServer.LDAP
+```toml
+[WebServer.LDAP]
+ServerAddress = 'ldaps://127.0.0.1' # Example
+ReadOnlyUserLogin = 'viewer@example.com' # Example
+ReadOnlyUserPass = 'password' # Example
+```
+Optional LDAP config
+
+### ServerAddress
+```toml
+ServerAddress = 'ldaps://127.0.0.1' # Example
+```
+ServerAddress is the full ldaps:// address of the ldap server to authenticate with and query
+
+### ReadOnlyUserLogin
+```toml
+ReadOnlyUserLogin = 'viewer@example.com' # Example
+```
+ReadOnlyUserLogin is the username of the read only root user used to authenticate the requested LDAP queries
+
+### ReadOnlyUserPass
+```toml
+ReadOnlyUserPass = 'password' # Example
+```
+ReadOnlyUserPass is the password for the above account
+
## Password
```toml
[Password]
diff --git a/go.mod b/go.mod
index 820e42c330..999c1b0402 100644
--- a/go.mod
+++ b/go.mod
@@ -114,6 +114,7 @@ require (
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
+ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/CosmWasm/wasmd v0.40.1 // indirect
github.com/CosmWasm/wasmvm v1.2.4 // indirect
@@ -169,8 +170,10 @@ require (
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
+ github.com/go-ldap/ldap/v3 v3.4.5
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
diff --git a/go.sum b/go.sum
index 155e54646d..ee06cc9b75 100644
--- a/go.sum
+++ b/go.sum
@@ -79,6 +79,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOv
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -129,6 +131,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
+github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@@ -419,6 +423,8 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
+github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@@ -433,6 +439,8 @@ github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEai
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-ldap/ldap/v3 v3.4.5 h1:ekEKmaDrpvR2yf5Nc/DClsGG9lAmdDixe44mLzlW5r8=
+github.com/go-ldap/ldap/v3 v3.4.5/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
@@ -1748,6 +1756,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1788,6 +1797,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1850,6 +1860,7 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1876,6 +1887,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1980,6 +1992,7 @@ golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1993,6 +2006,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2068,6 +2082,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 127980a2cb..93820c6ebf 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -58,6 +58,7 @@ require (
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
+ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/CosmWasm/wasmd v0.40.1 // indirect
github.com/CosmWasm/wasmvm v1.2.4 // indirect
@@ -152,9 +153,11 @@ require (
github.com/gin-contrib/sessions v0.0.5 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
+ github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
+ github.com/go-ldap/ldap/v3 v3.4.5 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 24da946717..60805eae82 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -575,6 +575,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -641,6 +643,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
+github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
+github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@@ -1027,6 +1031,8 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
+github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@@ -1047,6 +1053,8 @@ github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
+github.com/go-ldap/ldap/v3 v3.4.5 h1:ekEKmaDrpvR2yf5Nc/DClsGG9lAmdDixe44mLzlW5r8=
+github.com/go-ldap/ldap/v3 v3.4.5/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
@@ -2713,6 +2721,7 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar
index 189476bfa8..8a3b1af96f 100644
--- a/testdata/scripts/node/validate/default.txtar
+++ b/testdata/scripts/node/validate/default.txtar
@@ -73,6 +73,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -85,6 +86,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
index 593aa0b21d..31fded1b42 100644
--- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
@@ -117,6 +117,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -129,6 +130,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
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 7b8aa5e383..78fc976912 100644
--- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar
@@ -117,6 +117,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -129,6 +130,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar
index ef6548619e..226a7bbb3b 100644
--- a/testdata/scripts/node/validate/disk-based-logging.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging.txtar
@@ -117,6 +117,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -129,6 +130,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar
index 87b877bc88..5cd3d56746 100644
--- a/testdata/scripts/node/validate/invalid.txtar
+++ b/testdata/scripts/node/validate/invalid.txtar
@@ -107,6 +107,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -119,6 +120,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar
index c607da1064..fd24150b58 100644
--- a/testdata/scripts/node/validate/valid.txtar
+++ b/testdata/scripts/node/validate/valid.txtar
@@ -114,6 +114,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -126,6 +127,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar
index ee7926f8f5..828d953da9 100644
--- a/testdata/scripts/node/validate/warnings.txtar
+++ b/testdata/scripts/node/validate/warnings.txtar
@@ -110,6 +110,7 @@ MaxAgeDays = 0
MaxBackups = 1
[WebServer]
+AuthenticationMethod = 'local'
AllowOrigins = 'http://localhost:3000,http://localhost:6688'
BridgeResponseURL = ''
BridgeCacheTTL = '0s'
@@ -122,6 +123,25 @@ HTTPMaxSize = '32.77kb'
StartTimeout = '15s'
ListenIP = '0.0.0.0'
+[WebServer.LDAP]
+ServerTLS = true
+SessionTimeout = '15m0s'
+QueryTimeout = '2m0s'
+BaseUserAttr = 'uid'
+BaseDN = ''
+UsersDN = 'ou=users'
+GroupsDN = 'ou=groups'
+ActiveAttribute = ''
+ActiveAttributeAllowedValue = ''
+AdminUserGroupCN = 'NodeAdmins'
+EditUserGroupCN = 'NodeEditors'
+RunUserGroupCN = 'NodeRunners'
+ReadUserGroupCN = 'NodeReadOnly'
+UserApiTokenEnabled = false
+UserAPITokenDuration = '240h0m0s'
+UpstreamSyncInterval = '0s'
+UpstreamSyncRateLimit = '2m0s'
+
[WebServer.MFA]
RPID = ''
RPOrigin = ''
From 59bf37c5f8ebfb368e93ef7b6f2ccad4b50b246d Mon Sep 17 00:00:00 2001
From: Ilja Pavlovs
Date: Mon, 6 Nov 2023 11:03:45 +0200
Subject: [PATCH 073/327] =?UTF-8?q?VRF-669:=20adding=20CTF=20tests=20for?=
=?UTF-8?q?=20VRF=20v2.5=20cancel=20subscription,=20oracle=20wi=E2=80=A6?=
=?UTF-8?q?=20(#11159)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* VRF-669: adding CTF tests for VRF v2.5 cancel subscription, oracle withdraw; added fund return as a teardown for the WASP load test
* VRF-669: updating tests to have better balance calculation
* VRF-669: small update
* VRF-669: enabling tests; making use of big.Int Cmp() method
* VRF-669: adding sub cancellation test for the coordinator owner; code refactoring; fixing load test
---
.github/workflows/integration-tests.yml | 2 +-
integration-tests/actions/actions.go | 16 +
.../vrfv2plus/vrfv2plus_config/config.go | 6 +-
.../actions/vrfv2plus/vrfv2plus_steps.go | 118 +++-
.../contracts/contract_vrf_models.go | 6 +
.../contracts/ethereum_vrfv2plus_contracts.go | 101 ++++
integration-tests/load/vrfv2plus/config.go | 4 +-
integration-tests/load/vrfv2plus/config.toml | 8 +-
integration-tests/load/vrfv2plus/gun.go | 5 +-
.../load/vrfv2plus/vrfv2plus_test.go | 62 +-
integration-tests/smoke/vrfv2plus_test.go | 530 ++++++++++++++----
integration-tests/utils/common.go | 10 +
12 files changed, 737 insertions(+), 131 deletions(-)
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 0456c5f9d4..928c716dd1 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -303,7 +303,7 @@ jobs:
pyroscope_env: ci-smoke-vrf2-evm-simulated
- name: vrfv2plus
nodes: 1
- os: ubuntu-latest
+ os: ubuntu20.04-8cores-32GB
pyroscope_env: ci-smoke-vrf2plus-evm-simulated
- name: forwarder_ocr
nodes: 1
diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go
index 010b431b56..b45b8e83b9 100644
--- a/integration-tests/actions/actions.go
+++ b/integration-tests/actions/actions.go
@@ -2,8 +2,10 @@
package actions
import (
+ "crypto/ecdsa"
"encoding/json"
"fmt"
+ "github.com/ethereum/go-ethereum/crypto"
"math/big"
"strings"
"testing"
@@ -443,3 +445,17 @@ func DeployMockETHLinkFeed(cd contracts.ContractDeployer, answer *big.Int) (cont
}
return mockETHLINKFeed, err
}
+
+// todo - move to CTF
+func GenerateWallet() (common.Address, error) {
+ privateKey, err := crypto.GenerateKey()
+ if err != nil {
+ return common.Address{}, err
+ }
+ publicKey := privateKey.Public()
+ publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
+ if !ok {
+ return common.Address{}, errors.New("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
+ }
+ return crypto.PubkeyToAddress(*publicKeyECDSA), nil
+}
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
index 10d4f19c24..a47103a8a1 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go
@@ -7,8 +7,8 @@ type VRFV2PlusConfig struct {
IsNativePayment bool `envconfig:"IS_NATIVE_PAYMENT" default:"false"` // Whether to use native payment or LINK token
LinkNativeFeedResponse int64 `envconfig:"LINK_NATIVE_FEED_RESPONSE" default:"1000000000000000000"` // Response of the LINK/ETH feed
MinimumConfirmations uint16 `envconfig:"MINIMUM_CONFIRMATIONS" default:"3"` // Minimum number of confirmations for the VRF Coordinator
- SubscriptionFundingAmountLink int64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_LINK" default:"10"` // Amount of LINK to fund the subscription with
- SubscriptionFundingAmountNative int64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_NATIVE" default:"1"` // Amount of native currency to fund the subscription with
+ SubscriptionFundingAmountLink float64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_LINK" default:"5"` // Amount of LINK to fund the subscription with
+ SubscriptionFundingAmountNative float64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_NATIVE" default:"1"` // Amount of native currency to fund the subscription with
NumberOfWords uint32 `envconfig:"NUMBER_OF_WORDS" default:"3"` // Number of words to request
CallbackGasLimit uint32 `envconfig:"CALLBACK_GAS_LIMIT" default:"1000000"` // Gas limit for the callback
MaxGasLimitCoordinatorConfig uint32 `envconfig:"MAX_GAS_LIMIT_COORDINATOR_CONFIG" default:"2500000"` // Max gas limit for the VRF Coordinator config
@@ -23,6 +23,8 @@ type VRFV2PlusConfig struct {
RandomnessRequestCountPerRequest uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST" default:"1"` // How many randomness requests to send per request
RandomnessRequestCountPerRequestDeviation uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST_DEVIATION" default:"0"` // How many randomness requests to send per request
+ RandomWordsFulfilledEventTimeout time.Duration `envconfig:"RANDOM_WORDS_FULFILLED_EVENT_TIMEOUT" default:"2m"` // How long to wait for the RandomWordsFulfilled event to be emitted
+
//Wrapper Config
WrapperGasOverhead uint32 `envconfig:"WRAPPER_GAS_OVERHEAD" default:"50000"`
CoordinatorGasOverhead uint32 `envconfig:"COORDINATOR_GAS_OVERHEAD" default:"52000"`
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index 46f0ca58e6..e720116c21 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -3,6 +3,7 @@ package vrfv2plus
import (
"context"
"fmt"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils"
"math/big"
"sync"
"time"
@@ -221,12 +222,18 @@ func VRFV2PlusUpgradedVersionRegisterProvingKey(
return provingKey, nil
}
-func FundVRFCoordinatorV2_5Subscription(linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, chainClient blockchain.EVMClient, subscriptionID *big.Int, linkFundingAmount *big.Int) error {
+func FundVRFCoordinatorV2_5Subscription(
+ linkToken contracts.LinkToken,
+ coordinator contracts.VRFCoordinatorV2_5,
+ chainClient blockchain.EVMClient,
+ subscriptionID *big.Int,
+ linkFundingAmountJuels *big.Int,
+) error {
encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint256"}]`, subscriptionID)
if err != nil {
return errors.Wrap(err, ErrABIEncodingFunding)
}
- _, err = linkToken.TransferAndCall(coordinator.Address(), big.NewInt(0).Mul(linkFundingAmount, big.NewInt(1e18)), encodedSubId)
+ _, err = linkToken.TransferAndCall(coordinator.Address(), linkFundingAmountJuels, encodedSubId)
if err != nil {
return errors.Wrap(err, ErrSendingLinkToken)
}
@@ -236,9 +243,10 @@ func FundVRFCoordinatorV2_5Subscription(linkToken contracts.LinkToken, coordinat
// SetupVRFV2_5Environment will create specified number of subscriptions and add the same conumer/s to each of them
func SetupVRFV2_5Environment(
env *test_env.CLClusterTestEnv,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
linkToken contracts.LinkToken,
mockNativeLINKFeed contracts.MockETHLINKFeed,
+ registerProvingKeyAgainstAddress string,
numberOfConsumers int,
numberOfSubToCreate int,
l zerolog.Logger,
@@ -275,8 +283,12 @@ func SetupVRFV2_5Environment(
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
}
- l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Creating and funding subscriptions, adding consumers")
- subIDs, err := CreateFundSubsAndAddConsumers(env, vrfv2PlusConfig, linkToken, vrfv2_5Contracts.Coordinator, vrfv2_5Contracts.LoadTestConsumers, numberOfSubToCreate)
+ l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Int("Number of Subs to create", numberOfSubToCreate).Msg("Creating and funding subscriptions, adding consumers")
+ subIDs, err := CreateFundSubsAndAddConsumers(
+ env,
+ vrfv2PlusConfig,
+ linkToken,
+ vrfv2_5Contracts.Coordinator, vrfv2_5Contracts.LoadTestConsumers, numberOfSubToCreate)
if err != nil {
return nil, nil, nil, err
}
@@ -287,12 +299,8 @@ func SetupVRFV2_5Environment(
}
pubKeyCompressed := vrfKey.Data.ID
- nativeTokenPrimaryKeyAddress, err := env.ClCluster.NodeAPIs()[0].PrimaryEthAddress()
- if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrNodePrimaryKey)
- }
l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Registering Proving Key")
- provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, nativeTokenPrimaryKeyAddress, vrfv2_5Contracts.Coordinator)
+ provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, registerProvingKeyAgainstAddress, vrfv2_5Contracts.Coordinator)
if err != nil {
return nil, nil, nil, errors.Wrap(err, ErrRegisteringProvingKey)
}
@@ -303,6 +311,11 @@ func SetupVRFV2_5Environment(
chainID := env.EVMClient.GetChainID()
+ nativeTokenPrimaryKeyAddress, err := env.ClCluster.NodeAPIs()[0].PrimaryEthAddress()
+ if err != nil {
+ return nil, nil, nil, errors.Wrap(err, ErrNodePrimaryKey)
+ }
+
l.Info().Msg("Creating VRFV2 Plus Job")
job, err := CreateVRFV2PlusJob(
env.ClCluster.NodeAPIs()[0],
@@ -351,7 +364,7 @@ func SetupVRFV2_5Environment(
func CreateFundSubsAndAddConsumers(
env *test_env.CLClusterTestEnv,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
linkToken contracts.LinkToken,
coordinator contracts.VRFCoordinatorV2_5,
consumers []contracts.VRFv2PlusLoadTestConsumer,
@@ -385,7 +398,7 @@ func CreateFundSubsAndAddConsumers(
func CreateSubsAndFund(
env *test_env.CLClusterTestEnv,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
linkToken contracts.LinkToken,
coordinator contracts.VRFCoordinatorV2_5,
subAmountToCreate int,
@@ -439,7 +452,7 @@ func AddConsumersToSubs(
func SetupVRFV2PlusWrapperEnvironment(
env *test_env.CLClusterTestEnv,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
linkToken contracts.LinkToken,
mockNativeLINKFeed contracts.MockETHLINKFeed,
coordinator contracts.VRFCoordinatorV2_5,
@@ -574,19 +587,24 @@ func GetCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2_5) (linkT
func FundSubscriptions(
env *test_env.CLClusterTestEnv,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
linkAddress contracts.LinkToken,
coordinator contracts.VRFCoordinatorV2_5,
subIDs []*big.Int,
) error {
for _, subID := range subIDs {
//Native Billing
- err := coordinator.FundSubscriptionWithNative(subID, big.NewInt(0).Mul(big.NewInt(vrfv2PlusConfig.SubscriptionFundingAmountNative), big.NewInt(1e18)))
+ amountWei := utils.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountNative))
+ err := coordinator.FundSubscriptionWithNative(
+ subID,
+ amountWei,
+ )
if err != nil {
return errors.Wrap(err, ErrFundSubWithNativeToken)
}
//Link Billing
- err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, big.NewInt(vrfv2PlusConfig.SubscriptionFundingAmountLink))
+ amountJuels := utils.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountLink))
+ err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, amountJuels)
if err != nil {
return errors.Wrap(err, ErrFundSubWithLinkToken)
}
@@ -605,7 +623,8 @@ func RequestRandomnessAndWaitForFulfillment(
subID *big.Int,
isNativeBilling bool,
randomnessRequestCountPerRequest uint16,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
+ randomWordsFulfilledEventTimeout time.Duration,
l zerolog.Logger,
) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) {
logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l)
@@ -622,7 +641,15 @@ func RequestRandomnessAndWaitForFulfillment(
return nil, errors.Wrap(err, ErrRequestRandomness)
}
- return WaitForRequestAndFulfillmentEvents(consumer.Address(), coordinator, vrfv2PlusData, subID, isNativeBilling, l)
+ return WaitForRequestAndFulfillmentEvents(
+ consumer.Address(),
+ coordinator,
+ vrfv2PlusData,
+ subID,
+ isNativeBilling,
+ randomWordsFulfilledEventTimeout,
+ l,
+ )
}
func RequestRandomnessAndWaitForFulfillmentUpgraded(
@@ -631,7 +658,7 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded(
vrfv2PlusData *VRFV2PlusData,
subID *big.Int,
isNativeBilling bool,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
l zerolog.Logger,
) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) {
logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l)
@@ -679,7 +706,8 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment(
vrfv2PlusData *VRFV2PlusData,
subID *big.Int,
isNativeBilling bool,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
+ randomWordsFulfilledEventTimeout time.Duration,
l zerolog.Logger,
) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) {
logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l)
@@ -708,7 +736,15 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment(
if err != nil {
return nil, errors.Wrap(err, "error getting wrapper address")
}
- return WaitForRequestAndFulfillmentEvents(wrapperAddress.String(), coordinator, vrfv2PlusData, subID, isNativeBilling, l)
+ return WaitForRequestAndFulfillmentEvents(
+ wrapperAddress.String(),
+ coordinator,
+ vrfv2PlusData,
+ subID,
+ isNativeBilling,
+ randomWordsFulfilledEventTimeout,
+ l,
+ )
}
func WaitForRequestAndFulfillmentEvents(
@@ -717,6 +753,7 @@ func WaitForRequestAndFulfillmentEvents(
vrfv2PlusData *VRFV2PlusData,
subID *big.Int,
isNativeBilling bool,
+ randomWordsFulfilledEventTimeout time.Duration,
l zerolog.Logger,
) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) {
randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent(
@@ -734,7 +771,7 @@ func WaitForRequestAndFulfillmentEvents(
randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent(
[]*big.Int{subID},
[]*big.Int{randomWordsRequestedEvent.RequestId},
- time.Minute*2,
+ randomWordsFulfilledEventTimeout,
)
if err != nil {
return nil, errors.Wrap(err, ErrWaitRandomWordsFulfilledEvent)
@@ -777,6 +814,41 @@ func WaitForRequestCountEqualToFulfilmentCount(consumer contracts.VRFv2PlusLoadT
}
}
+func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator contracts.VRFCoordinatorV2_5, l zerolog.Logger) error {
+ linkTotalBalance, err := coordinator.GetLinkTotalBalance(context.Background())
+ if err != nil {
+ return errors.Wrap(err, "Error getting LINK total balance")
+ }
+ defaultWallet := client.GetDefaultWallet().Address()
+ l.Info().
+ Str("LINK amount", linkTotalBalance.String()).
+ Str("Returning to", defaultWallet).
+ Msg("Returning LINK for fulfilled requests")
+ err = coordinator.OracleWithdraw(
+ common.HexToAddress(defaultWallet),
+ linkTotalBalance,
+ )
+ if err != nil {
+ return errors.Wrap(err, "Error withdrawing LINK from coordinator to default wallet")
+ }
+ nativeTotalBalance, err := coordinator.GetNativeTokenTotalBalance(context.Background())
+ if err != nil {
+ return errors.Wrap(err, "Error getting NATIVE total balance")
+ }
+ l.Info().
+ Str("Native Token amount", linkTotalBalance.String()).
+ Str("Returning to", defaultWallet).
+ Msg("Returning Native Token for fulfilled requests")
+ err = coordinator.OracleWithdrawNative(
+ common.HexToAddress(defaultWallet),
+ nativeTotalBalance,
+ )
+ if err != nil {
+ return errors.Wrap(err, "Error withdrawing NATIVE from coordinator to default wallet")
+ }
+ return nil
+}
+
func getLoadTestMetrics(
consumer contracts.VRFv2PlusLoadTestConsumer,
metricsChannel chan *contracts.VRFLoadTestMetrics,
@@ -934,7 +1006,7 @@ func logRandRequest(
coordinator string,
subID *big.Int,
isNativeBilling bool,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
l zerolog.Logger) {
l.Debug().
Str("Consumer", consumer).
diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go
index f0f57f58e7..c82924143b 100644
--- a/integration-tests/contracts/contract_vrf_models.go
+++ b/integration-tests/contracts/contract_vrf_models.go
@@ -80,11 +80,17 @@ type VRFCoordinatorV2_5 interface {
AddConsumer(subId *big.Int, consumerAddress string) error
FundSubscriptionWithNative(subId *big.Int, nativeTokenAmount *big.Int) error
Address() string
+ PendingRequestsExist(ctx context.Context, subID *big.Int) (bool, error)
GetSubscription(ctx context.Context, subID *big.Int) (vrf_coordinator_v2_5.GetSubscription, error)
+ OwnerCancelSubscription(subID *big.Int) (*types.Transaction, error)
+ CancelSubscription(subID *big.Int, to common.Address) (*types.Transaction, error)
+ OracleWithdraw(recipient common.Address, amount *big.Int) error
+ OracleWithdrawNative(recipient common.Address, amount *big.Int) error
GetNativeTokenTotalBalance(ctx context.Context) (*big.Int, error)
GetLinkTotalBalance(ctx context.Context) (*big.Int, error)
FindSubscriptionID(subID *big.Int) (*big.Int, error)
WaitForSubscriptionCreatedEvent(timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCreated, error)
+ WaitForSubscriptionCanceledEvent(subID *big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCanceled, error)
WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error)
WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []*big.Int, sender []common.Address, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, error)
WaitForMigrationCompletedEvent(timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25MigrationCompleted, error)
diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go
index 1488f97131..330166dc79 100644
--- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go
+++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go
@@ -96,6 +96,18 @@ func (v *EthereumVRFCoordinatorV2_5) GetActiveSubscriptionIds(ctx context.Contex
return activeSubscriptionIds, nil
}
+func (v *EthereumVRFCoordinatorV2_5) PendingRequestsExist(ctx context.Context, subID *big.Int) (bool, error) {
+ opts := &bind.CallOpts{
+ From: common.HexToAddress(v.client.GetDefaultWallet().Address()),
+ Context: ctx,
+ }
+ pendingRequestExists, err := v.coordinator.PendingRequestExists(opts, subID)
+ if err != nil {
+ return false, err
+ }
+ return pendingRequestExists, nil
+}
+
func (v *EthereumVRFCoordinatorV2_5) GetSubscription(ctx context.Context, subID *big.Int) (vrf_coordinator_v2_5.GetSubscription, error) {
opts := &bind.CallOpts{
From: common.HexToAddress(v.client.GetDefaultWallet().Address()),
@@ -131,6 +143,75 @@ func (v *EthereumVRFCoordinatorV2_5) GetNativeTokenTotalBalance(ctx context.Cont
return totalBalance, nil
}
+// OwnerCancelSubscription cancels subscription by Coordinator owner
+// return funds to sub owner,
+// does not check if pending requests for a sub exist
+func (v *EthereumVRFCoordinatorV2_5) OwnerCancelSubscription(subID *big.Int) (*types.Transaction, error) {
+ opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
+ if err != nil {
+ return nil, err
+ }
+ tx, err := v.coordinator.OwnerCancelSubscription(
+ opts,
+ subID,
+ )
+ if err != nil {
+ return nil, err
+ }
+ return tx, v.client.ProcessTransaction(tx)
+}
+
+// CancelSubscription cancels subscription by Sub owner,
+// return funds to specified address,
+// checks if pending requests for a sub exist
+func (v *EthereumVRFCoordinatorV2_5) CancelSubscription(subID *big.Int, to common.Address) (*types.Transaction, error) {
+ opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
+ if err != nil {
+ return nil, err
+ }
+ tx, err := v.coordinator.CancelSubscription(
+ opts,
+ subID,
+ to,
+ )
+ if err != nil {
+ return nil, err
+ }
+ return tx, v.client.ProcessTransaction(tx)
+}
+
+func (v *EthereumVRFCoordinatorV2_5) OracleWithdraw(recipient common.Address, amount *big.Int) error {
+ opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
+ if err != nil {
+ return err
+ }
+ tx, err := v.coordinator.OracleWithdraw(
+ opts,
+ recipient,
+ amount,
+ )
+ if err != nil {
+ return err
+ }
+ return v.client.ProcessTransaction(tx)
+}
+
+func (v *EthereumVRFCoordinatorV2_5) OracleWithdrawNative(recipient common.Address, amount *big.Int) error {
+ opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
+ if err != nil {
+ return err
+ }
+ tx, err := v.coordinator.OracleWithdrawNative(
+ opts,
+ recipient,
+ amount,
+ )
+ if err != nil {
+ return err
+ }
+ return v.client.ProcessTransaction(tx)
+}
+
func (v *EthereumVRFCoordinatorV2_5) SetConfig(minimumRequestConfirmations uint16, maxGasLimit uint32, stalenessSeconds uint32, gasAfterPaymentCalculation uint32, fallbackWeiPerUnitLink *big.Int, feeConfig vrf_coordinator_v2_5.VRFCoordinatorV25FeeConfig) error {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
@@ -287,6 +368,26 @@ func (v *EthereumVRFCoordinatorV2_5) WaitForSubscriptionCreatedEvent(timeout tim
}
}
+func (v *EthereumVRFCoordinatorV2_5) WaitForSubscriptionCanceledEvent(subID *big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCanceled, error) {
+ eventsChannel := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCanceled)
+ subscription, err := v.coordinator.WatchSubscriptionCanceled(nil, eventsChannel, []*big.Int{subID})
+ if err != nil {
+ return nil, err
+ }
+ defer subscription.Unsubscribe()
+
+ for {
+ select {
+ case err := <-subscription.Err():
+ return nil, err
+ case <-time.After(timeout):
+ return nil, fmt.Errorf("timeout waiting for SubscriptionCanceled event")
+ case sub := <-eventsChannel:
+ return sub, nil
+ }
+ }
+}
+
func (v *EthereumVRFCoordinatorV2_5) WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) {
randomWordsFulfilledEventsChannel := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled)
subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, requestID, subID)
diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go
index 50003c8286..a5439210c2 100644
--- a/integration-tests/load/vrfv2plus/config.go
+++ b/integration-tests/load/vrfv2plus/config.go
@@ -57,8 +57,8 @@ type Funding struct {
}
type SubFunding struct {
- SubFundsLink int64 `toml:"sub_funds_link"`
- SubFundsNative int64 `toml:"sub_funds_native"`
+ SubFundsLink float64 `toml:"sub_funds_link"`
+ SubFundsNative float64 `toml:"sub_funds_native"`
}
type Soak struct {
diff --git a/integration-tests/load/vrfv2plus/config.toml b/integration-tests/load/vrfv2plus/config.toml
index 05e22bd51e..e3200fafe2 100644
--- a/integration-tests/load/vrfv2plus/config.toml
+++ b/integration-tests/load/vrfv2plus/config.toml
@@ -9,8 +9,8 @@ node_funds = 10
[ExistingEnvConfig]
coordinator_address = "0x27b61f155F772b291D1d9B478BeAd37B2Ae447b0"
-consumer_address = "0x087F232165D9bA1A602f148025e5D0666953F64a"
-sub_id = "52116875585187328970776211988181422347535732407068188096422095950800466618218"
+#consumer_address = "0x087F232165D9bA1A602f148025e5D0666953F64a"
+#sub_id = "52116875585187328970776211988181422347535732407068188096422095950800466618218"
key_hash = "0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae"
create_fund_subs_and_add_consumers = true
link_address = "0x779877A7B0D9E8603169DdbD7836e478b4624789"
@@ -31,7 +31,7 @@ rate_limit_unit_duration = "3s"
rps = 1
randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting
-number_of_sub_to_create = 5
+number_of_sub_to_create = 1
# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx
[Stress]
@@ -39,7 +39,7 @@ rate_limit_unit_duration = "1s"
rps = 3
randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request
randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting
-number_of_sub_to_create = 5
+number_of_sub_to_create = 1
# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds
[Spike]
diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go
index c9947fa32f..21be1c74ca 100644
--- a/integration-tests/load/vrfv2plus/gun.go
+++ b/integration-tests/load/vrfv2plus/gun.go
@@ -15,7 +15,7 @@ type SingleHashGun struct {
contracts *vrfv2plus.VRFV2_5Contracts
keyHash [32]byte
subIDs []*big.Int
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig
logger zerolog.Logger
}
@@ -23,7 +23,7 @@ func NewSingleHashGun(
contracts *vrfv2plus.VRFV2_5Contracts,
keyHash [32]byte,
subIDs []*big.Int,
- vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig,
+ vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig,
logger zerolog.Logger,
) *SingleHashGun {
return &SingleHashGun{
@@ -52,6 +52,7 @@ func (m *SingleHashGun) Call(l *wasp.Generator) *wasp.CallResult {
randBool(),
randomnessRequestCountPerRequest,
m.vrfv2PlusConfig,
+ m.vrfv2PlusConfig.RandomWordsFulfilledEventTimeout,
m.logger,
)
if err != nil {
diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
index e619cf78fd..4d3de014bc 100644
--- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go
+++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
@@ -27,6 +27,7 @@ var (
vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts
vrfv2PlusData *vrfv2plus.VRFV2PlusData
subIDs []*big.Int
+ eoaWalletAddress string
labels = map[string]string{
"branch": "vrfv2Plus_healthcheck",
@@ -85,6 +86,32 @@ func TestVRFV2PlusPerformance(t *testing.T) {
WithCustomCleanup(
func() {
teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig)
+ if env.EVMClient.NetworkSimulated() {
+ l.Info().
+ Str("Network Name", env.EVMClient.GetNetworkName()).
+ Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.")
+ } else {
+ //cancel subs and return funds to sub owner
+ for _, subID := range subIDs {
+ l.Info().
+ Str("Returning funds from SubID", subID.String()).
+ Str("Returning funds to", eoaWalletAddress).
+ Msg("Canceling subscription and returning funds to subscription owner")
+ pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(context.Background(), subID)
+ if err != nil {
+ l.Error().Err(err).Msg("Error checking if pending requests exist")
+ }
+ if !pendingRequestsExist {
+ _, err := vrfv2PlusContracts.Coordinator.CancelSubscription(subID, common.HexToAddress(eoaWalletAddress))
+ if err != nil {
+ l.Error().Err(err).Msg("Error canceling subscription")
+ }
+ } else {
+ l.Error().Str("Sub ID", subID.String()).Msg("Pending requests exist for subscription, cannot cancel subscription and return funds")
+ }
+
+ }
+ }
}).
Build()
@@ -99,7 +126,14 @@ func TestVRFV2PlusPerformance(t *testing.T) {
require.NoError(t, err)
consumers, err = vrfv2plus.DeployVRFV2PlusConsumers(env.ContractDeployer, coordinator, 1)
require.NoError(t, err)
- subIDs, err = vrfv2plus.CreateFundSubsAndAddConsumers(env, &vrfv2PlusConfig, linkToken, coordinator, consumers, vrfv2PlusConfig.NumberOfSubToCreate)
+ subIDs, err = vrfv2plus.CreateFundSubsAndAddConsumers(
+ env,
+ vrfv2PlusConfig,
+ linkToken,
+ coordinator,
+ consumers,
+ vrfv2PlusConfig.NumberOfSubToCreate,
+ )
require.NoError(t, err)
} else {
consumer, err := env.ContractLoader.LoadVRFv2PlusLoadTestConsumer(vrfv2PlusConfig.ConsumerAddress)
@@ -141,6 +175,25 @@ func TestVRFV2PlusPerformance(t *testing.T) {
WithCustomCleanup(
func() {
teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig)
+
+ if env.EVMClient.NetworkSimulated() {
+ l.Info().
+ Str("Network Name", env.EVMClient.GetNetworkName()).
+ Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.")
+ } else {
+ for _, subID := range subIDs {
+ l.Info().
+ Str("Returning funds from SubID", subID.String()).
+ Str("Returning funds to", eoaWalletAddress).
+ Msg("Canceling subscription and returning funds to subscription owner")
+ _, err := vrfv2PlusContracts.Coordinator.CancelSubscription(subID, common.HexToAddress(eoaWalletAddress))
+ if err != nil {
+ l.Error().Err(err).Msg("Error canceling subscription")
+ }
+ }
+ //err = vrfv2plus.ReturnFundsForFulfilledRequests(env.EVMClient, vrfv2PlusContracts.Coordinator, l)
+ //l.Error().Err(err).Msg("Error returning funds for fulfilled requests")
+ }
if err := env.Cleanup(); err != nil {
l.Error().Err(err).Msg("Error cleaning up test environment")
}
@@ -160,15 +213,18 @@ func TestVRFV2PlusPerformance(t *testing.T) {
vrfv2PlusContracts, subIDs, vrfv2PlusData, err = vrfv2plus.SetupVRFV2_5Environment(
env,
- &vrfv2PlusConfig,
+ vrfv2PlusConfig,
linkToken,
mockETHLinkFeed,
+ //register proving key against EOA address in order to return funds to this address
+ env.EVMClient.GetDefaultWallet().Address(),
1,
vrfv2PlusConfig.NumberOfSubToCreate,
l,
)
require.NoError(t, err, "error setting up VRF v2_5 env")
}
+ eoaWalletAddress = env.EVMClient.GetDefaultWallet().Address()
l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test")
for _, subID := range subIDs {
@@ -186,7 +242,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
vrfv2PlusContracts,
vrfv2PlusData.KeyHash,
subIDs,
- &vrfv2PlusConfig,
+ vrfv2PlusConfig,
l,
),
Labels: labels,
diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go
index d7381c9cd3..acd548c88e 100644
--- a/integration-tests/smoke/vrfv2plus_test.go
+++ b/integration-tests/smoke/vrfv2plus_test.go
@@ -2,6 +2,8 @@ package smoke
import (
"context"
+ "fmt"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
"math/big"
"testing"
"time"
@@ -45,7 +47,10 @@ func TestVRFv2Plus(t *testing.T) {
linkToken, err := actions.DeployLINKToken(env.ContractDeployer)
require.NoError(t, err, "error deploying LINK contract")
- vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkToken, mockETHLinkFeed, 1, 1, l)
+ // register proving key against oracle address (sending key) in order to test oracleWithdraw
+ defaultWalletAddress := env.EVMClient.GetDefaultWallet().Address()
+
+ vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, vrfv2PlusConfig, linkToken, mockETHLinkFeed, defaultWalletAddress, 1, 1, l)
require.NoError(t, err, "error setting up VRF v2_5 env")
subID := subIDs[0]
@@ -55,7 +60,8 @@ func TestVRFv2Plus(t *testing.T) {
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
- t.Run("VRFV2 Plus With Link Billing", func(t *testing.T) {
+ t.Run("Link Billing", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
var isNativeBilling = false
subBalanceBeforeRequest := subscription.Balance
@@ -69,8 +75,9 @@ func TestVRFv2Plus(t *testing.T) {
vrfv2PlusData,
subID,
isNativeBilling,
- vrfv2PlusConfig.RandomnessRequestCountPerRequest,
- &vrfv2PlusConfig,
+ testConfig.RandomnessRequestCountPerRequest,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
l,
)
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
@@ -90,14 +97,14 @@ func TestVRFv2Plus(t *testing.T) {
require.True(t, status.Fulfilled)
l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
- require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(status.RandomWords)))
+ require.Equal(t, testConfig.NumberOfWords, uint32(len(status.RandomWords)))
for _, w := range status.RandomWords {
l.Info().Str("Output", w.String()).Msg("Randomness fulfilled")
require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0")
}
})
-
- t.Run("VRFV2 Plus With Native Billing", func(t *testing.T) {
+ t.Run("Native Billing", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
var isNativeBilling = true
subNativeTokenBalanceBeforeRequest := subscription.NativeBalance
@@ -111,8 +118,9 @@ func TestVRFv2Plus(t *testing.T) {
vrfv2PlusData,
subID,
isNativeBilling,
- vrfv2PlusConfig.RandomnessRequestCountPerRequest,
- &vrfv2PlusConfig,
+ testConfig.RandomnessRequestCountPerRequest,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
l,
)
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
@@ -131,120 +139,451 @@ func TestVRFv2Plus(t *testing.T) {
require.True(t, status.Fulfilled)
l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
- require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(status.RandomWords)))
+ require.Equal(t, testConfig.NumberOfWords, uint32(len(status.RandomWords)))
for _, w := range status.RandomWords {
l.Info().Str("Output", w.String()).Msg("Randomness fulfilled")
require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0")
}
})
+ t.Run("Direct Funding (VRFV2PlusWrapper)", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
+ wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment(
+ env,
+ testConfig,
+ linkToken,
+ mockETHLinkFeed,
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusData.KeyHash,
+ 1,
+ )
+ require.NoError(t, err)
- wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment(
- env,
- &vrfv2PlusConfig,
- linkToken,
- mockETHLinkFeed,
- vrfv2PlusContracts.Coordinator,
- vrfv2PlusData.KeyHash,
- 1,
- )
- require.NoError(t, err)
+ t.Run("Link Billing", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
+ var isNativeBilling = false
+
+ wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(context.Background(), wrapperContracts.LoadTestConsumers[0].Address())
+ require.NoError(t, err, "error getting wrapper consumer balance")
+
+ wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ require.NoError(t, err, "error getting subscription information")
+ subBalanceBeforeRequest := wrapperSubscription.Balance
+
+ randomWordsFulfilledEvent, err := vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillment(
+ wrapperContracts.LoadTestConsumers[0],
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusData,
+ wrapperSubID,
+ isNativeBilling,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
+ l,
+ )
+ require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
+
+ expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
+ wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ require.NoError(t, err, "error getting subscription information")
+ subBalanceAfterRequest := wrapperSubscription.Balance
+ require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest)
+
+ consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
+ require.NoError(t, err, "error getting rand request status")
+ require.True(t, consumerStatus.Fulfilled)
+
+ expectedWrapperConsumerJuelsBalance := new(big.Int).Sub(wrapperConsumerJuelsBalanceBeforeRequest, consumerStatus.Paid)
+
+ wrapperConsumerJuelsBalanceAfterRequest, err := linkToken.BalanceOf(context.Background(), wrapperContracts.LoadTestConsumers[0].Address())
+ require.NoError(t, err, "error getting wrapper consumer balance")
+ require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest)
+
+ //todo: uncomment when VRF-651 will be fixed
+ //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub")
+ vrfv2plus.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent)
+
+ require.Equal(t, testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords)))
+ for _, w := range consumerStatus.RandomWords {
+ l.Info().Str("Output", w.String()).Msg("Randomness fulfilled")
+ require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0")
+ }
+ })
+ t.Run("Native Billing", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
+ var isNativeBilling = true
+
+ wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
+ require.NoError(t, err, "error getting wrapper consumer balance")
+
+ wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ require.NoError(t, err, "error getting subscription information")
+ subBalanceBeforeRequest := wrapperSubscription.NativeBalance
+
+ randomWordsFulfilledEvent, err := vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillment(
+ wrapperContracts.LoadTestConsumers[0],
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusData,
+ wrapperSubID,
+ isNativeBilling,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
+ l,
+ )
+ require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
+
+ expectedSubBalanceWei := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
+ wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ require.NoError(t, err, "error getting subscription information")
+ subBalanceAfterRequest := wrapperSubscription.NativeBalance
+ require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest)
+
+ consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
+ require.NoError(t, err, "error getting rand request status")
+ require.True(t, consumerStatus.Fulfilled)
+
+ expectedWrapperConsumerWeiBalance := new(big.Int).Sub(wrapperConsumerBalanceBeforeRequestWei, consumerStatus.Paid)
+
+ wrapperConsumerBalanceAfterRequestWei, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
+ require.NoError(t, err, "error getting wrapper consumer balance")
+ require.Equal(t, expectedWrapperConsumerWeiBalance, wrapperConsumerBalanceAfterRequestWei)
+
+ //todo: uncomment when VRF-651 will be fixed
+ //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub")
+ vrfv2plus.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent)
+
+ require.Equal(t, testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords)))
+ for _, w := range consumerStatus.RandomWords {
+ l.Info().Str("Output", w.String()).Msg("Randomness fulfilled")
+ require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0")
+ }
+ })
+ })
+ t.Run("Canceling Sub And Returning Funds", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
+ subIDsForCancelling, err := vrfv2plus.CreateFundSubsAndAddConsumers(
+ env,
+ testConfig,
+ linkToken,
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusContracts.LoadTestConsumers,
+ 1,
+ )
+ require.NoError(t, err)
+ subIDForCancelling := subIDsForCancelling[0]
- t.Run("VRFV2 Plus With Direct Funding (VRFV2PlusWrapper) - Link Billing", func(t *testing.T) {
- var isNativeBilling = false
+ testWalletAddress, err := actions.GenerateWallet()
- wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(context.Background(), wrapperContracts.LoadTestConsumers[0].Address())
- require.NoError(t, err, "error getting wrapper consumer balance")
+ testWalletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), testWalletAddress)
+ require.NoError(t, err)
+
+ testWalletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(context.Background(), testWalletAddress.String())
+ require.NoError(t, err)
- wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
- subBalanceBeforeRequest := wrapperSubscription.Balance
- randomWordsFulfilledEvent, err := vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillment(
- wrapperContracts.LoadTestConsumers[0],
+ subBalanceLink := subscriptionForCancelling.Balance
+ subBalanceNative := subscriptionForCancelling.NativeBalance
+ l.Info().
+ Str("Subscription Amount Native", subBalanceNative.String()).
+ Str("Subscription Amount Link", subBalanceLink.String()).
+ Str("Returning funds from SubID", subIDForCancelling.String()).
+ Str("Returning funds to", testWalletAddress.String()).
+ Msg("Canceling subscription and returning funds to subscription owner")
+ tx, err := vrfv2PlusContracts.Coordinator.CancelSubscription(subIDForCancelling, testWalletAddress)
+ require.NoError(t, err, "Error canceling subscription")
+
+ subscriptionCanceledEvent, err := vrfv2PlusContracts.Coordinator.WaitForSubscriptionCanceledEvent(subIDForCancelling, time.Second*30)
+ require.NoError(t, err, "error waiting for subscription canceled event")
+
+ cancellationTxReceipt, err := env.EVMClient.GetTxReceipt(tx.Hash())
+ require.NoError(t, err, "error getting tx cancellation Tx Receipt")
+
+ txGasUsed := new(big.Int).SetUint64(cancellationTxReceipt.GasUsed)
+ cancellationTxFeeWei := new(big.Int).Mul(txGasUsed, cancellationTxReceipt.EffectiveGasPrice)
+
+ l.Info().
+ Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()).
+ Str("Effective Gas Price", cancellationTxReceipt.EffectiveGasPrice.String()).
+ Uint64("Gas Used", cancellationTxReceipt.GasUsed).
+ Msg("Cancellation TX Receipt")
+
+ l.Info().
+ Str("Returned Subscription Amount Native", subscriptionCanceledEvent.AmountNative.String()).
+ Str("Returned Subscription Amount Link", subscriptionCanceledEvent.AmountLink.String()).
+ Str("SubID", subscriptionCanceledEvent.SubId.String()).
+ Str("Returned to", subscriptionCanceledEvent.To.String()).
+ Msg("Subscription Canceled Event")
+
+ require.Equal(t, subBalanceNative, subscriptionCanceledEvent.AmountNative, "SubscriptionCanceled event native amount is not equal to sub amount while canceling subscription")
+ require.Equal(t, subBalanceLink, subscriptionCanceledEvent.AmountLink, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription")
+
+ testWalletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), testWalletAddress)
+ require.NoError(t, err)
+
+ testWalletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(context.Background(), testWalletAddress.String())
+ require.NoError(t, err)
+
+ //Verify that sub was deleted from Coordinator
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
+
+ subFundsReturnedNativeActual := new(big.Int).Sub(testWalletBalanceNativeAfterSubCancelling, testWalletBalanceNativeBeforeSubCancelling)
+ subFundsReturnedLinkActual := new(big.Int).Sub(testWalletBalanceLinkAfterSubCancelling, testWalletBalanceLinkBeforeSubCancelling)
+
+ subFundsReturnedNativeExpected := new(big.Int).Sub(subBalanceNative, cancellationTxFeeWei)
+ deltaSpentOnCancellationTxFee := new(big.Int).Sub(subBalanceNative, subFundsReturnedNativeActual)
+ l.Info().
+ Str("Sub Balance - Native", subBalanceNative.String()).
+ Str("Delta Spent On Cancellation Tx Fee - `NativeBalance - subFundsReturnedNativeActual`", deltaSpentOnCancellationTxFee.String()).
+ Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()).
+ Str("Sub Funds Returned Actual - Native", subFundsReturnedNativeActual.String()).
+ Str("Sub Funds Returned Expected - `NativeBalance - cancellationTxFeeWei`", subFundsReturnedNativeExpected.String()).
+ Str("Sub Funds Returned Actual - Link", subFundsReturnedLinkActual.String()).
+ Str("Sub Balance - Link", subBalanceLink.String()).
+ Msg("Sub funds returned")
+
+ //todo - this fails on SIMULATED env as tx cost is calculated different as for testnets and it's not receipt.EffectiveGasPrice*receipt.GasUsed
+ //require.Equal(t, subFundsReturnedNativeExpected, subFundsReturnedNativeActual, "Returned funds are not equal to sub balance that was cancelled")
+ require.Equal(t, 1, testWalletBalanceNativeAfterSubCancelling.Cmp(testWalletBalanceNativeBeforeSubCancelling), "Native funds were not returned after sub cancellation")
+ require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled")
+
+ })
+ t.Run("Owner Canceling Sub And Returning Funds While Having Pending Requests", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
+ //underfund subs in order rand fulfillments to fail
+ testConfig.SubscriptionFundingAmountNative = float64(0.000000000000000001) //1 Wei
+ testConfig.SubscriptionFundingAmountLink = float64(0.000000000000000001) //1 Juels
+
+ subIDsForCancelling, err := vrfv2plus.CreateFundSubsAndAddConsumers(
+ env,
+ testConfig,
+ linkToken,
vrfv2PlusContracts.Coordinator,
- vrfv2PlusData,
- wrapperSubID,
- isNativeBilling,
- &vrfv2PlusConfig,
- l,
+ vrfv2PlusContracts.LoadTestConsumers,
+ 1,
)
- require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
+ require.NoError(t, err)
- expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ subIDForCancelling := subIDsForCancelling[0]
+
+ subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
- subBalanceAfterRequest := wrapperSubscription.Balance
- require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest)
- consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
- require.NoError(t, err, "error getting rand request status")
- require.True(t, consumerStatus.Fulfilled)
+ vrfv2plus.LogSubDetails(l, subscriptionForCancelling, subIDForCancelling, vrfv2PlusContracts.Coordinator)
- expectedWrapperConsumerJuelsBalance := new(big.Int).Sub(wrapperConsumerJuelsBalanceBeforeRequest, consumerStatus.Paid)
+ activeSubscriptionIdsBeforeSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ require.NoError(t, err)
- wrapperConsumerJuelsBalanceAfterRequest, err := linkToken.BalanceOf(context.Background(), wrapperContracts.LoadTestConsumers[0].Address())
- require.NoError(t, err, "error getting wrapper consumer balance")
- require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest)
+ require.True(t, utils.BigIntSliceContains(activeSubscriptionIdsBeforeSubCancellation, subIDForCancelling))
- //todo: uncomment when VRF-651 will be fixed
- //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub")
- vrfv2plus.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent)
+ pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(context.Background(), subIDForCancelling)
+ require.NoError(t, err)
+ require.False(t, pendingRequestsExist, "Pending requests should not exist")
- require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords)))
- for _, w := range consumerStatus.RandomWords {
- l.Info().Str("Output", w.String()).Msg("Randomness fulfilled")
- require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0")
- }
- })
+ _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment(
+ vrfv2PlusContracts.LoadTestConsumers[0],
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusData,
+ subIDForCancelling,
+ false,
+ testConfig.RandomnessRequestCountPerRequest,
+ testConfig,
+ 5*time.Second,
+ l,
+ )
- t.Run("VRFV2 Plus With Direct Funding (VRFV2PlusWrapper) - Native Billing", func(t *testing.T) {
- var isNativeBilling = true
+ require.Error(t, err, "error should occur for waiting for fulfilment due to low sub balance")
- wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
- require.NoError(t, err, "error getting wrapper consumer balance")
+ _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment(
+ vrfv2PlusContracts.LoadTestConsumers[0],
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusData,
+ subIDForCancelling,
+ true,
+ testConfig.RandomnessRequestCountPerRequest,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
+ l,
+ )
- wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ require.Error(t, err, "error should occur for waiting for fulfilment due to low sub balance")
+
+ pendingRequestsExist, err = vrfv2PlusContracts.Coordinator.PendingRequestsExist(context.Background(), subIDForCancelling)
+ require.NoError(t, err)
+ require.True(t, pendingRequestsExist, "Pending requests should exist after unfulfilled rand requests due to low sub balance")
+
+ walletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ require.NoError(t, err)
+
+ walletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ require.NoError(t, err)
+
+ subscriptionForCancelling, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
- subBalanceBeforeRequest := wrapperSubscription.NativeBalance
- randomWordsFulfilledEvent, err := vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillment(
- wrapperContracts.LoadTestConsumers[0],
+ subBalanceLink := subscriptionForCancelling.Balance
+ subBalanceNative := subscriptionForCancelling.NativeBalance
+ l.Info().
+ Str("Subscription Amount Native", subBalanceNative.String()).
+ Str("Subscription Amount Link", subBalanceLink.String()).
+ Str("Returning funds from SubID", subIDForCancelling.String()).
+ Str("Returning funds to", defaultWalletAddress).
+ Msg("Canceling subscription and returning funds to subscription owner")
+ tx, err := vrfv2PlusContracts.Coordinator.OwnerCancelSubscription(subIDForCancelling)
+ require.NoError(t, err, "Error canceling subscription")
+
+ subscriptionCanceledEvent, err := vrfv2PlusContracts.Coordinator.WaitForSubscriptionCanceledEvent(subIDForCancelling, time.Second*30)
+ require.NoError(t, err, "error waiting for subscription canceled event")
+
+ cancellationTxReceipt, err := env.EVMClient.GetTxReceipt(tx.Hash())
+ require.NoError(t, err, "error getting tx cancellation Tx Receipt")
+
+ txGasUsed := new(big.Int).SetUint64(cancellationTxReceipt.GasUsed)
+ cancellationTxFeeWei := new(big.Int).Mul(txGasUsed, cancellationTxReceipt.EffectiveGasPrice)
+
+ l.Info().
+ Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()).
+ Str("Effective Gas Price", cancellationTxReceipt.EffectiveGasPrice.String()).
+ Uint64("Gas Used", cancellationTxReceipt.GasUsed).
+ Msg("Cancellation TX Receipt")
+
+ l.Info().
+ Str("Returned Subscription Amount Native", subscriptionCanceledEvent.AmountNative.String()).
+ Str("Returned Subscription Amount Link", subscriptionCanceledEvent.AmountLink.String()).
+ Str("SubID", subscriptionCanceledEvent.SubId.String()).
+ Str("Returned to", subscriptionCanceledEvent.To.String()).
+ Msg("Subscription Canceled Event")
+
+ require.Equal(t, subBalanceNative, subscriptionCanceledEvent.AmountNative, "SubscriptionCanceled event native amount is not equal to sub amount while canceling subscription")
+ require.Equal(t, subBalanceLink, subscriptionCanceledEvent.AmountLink, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription")
+
+ walletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ require.NoError(t, err)
+
+ walletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ require.NoError(t, err)
+
+ //Verify that sub was deleted from Coordinator
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ fmt.Println("err", err)
+ require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
+
+ subFundsReturnedNativeActual := new(big.Int).Sub(walletBalanceNativeAfterSubCancelling, walletBalanceNativeBeforeSubCancelling)
+ subFundsReturnedLinkActual := new(big.Int).Sub(walletBalanceLinkAfterSubCancelling, walletBalanceLinkBeforeSubCancelling)
+
+ subFundsReturnedNativeExpected := new(big.Int).Sub(subBalanceNative, cancellationTxFeeWei)
+ deltaSpentOnCancellationTxFee := new(big.Int).Sub(subBalanceNative, subFundsReturnedNativeActual)
+ l.Info().
+ Str("Sub Balance - Native", subBalanceNative.String()).
+ Str("Delta Spent On Cancellation Tx Fee - `NativeBalance - subFundsReturnedNativeActual`", deltaSpentOnCancellationTxFee.String()).
+ Str("Cancellation Tx Fee Wei", cancellationTxFeeWei.String()).
+ Str("Sub Funds Returned Actual - Native", subFundsReturnedNativeActual.String()).
+ Str("Sub Funds Returned Expected - `NativeBalance - cancellationTxFeeWei`", subFundsReturnedNativeExpected.String()).
+ Str("Sub Funds Returned Actual - Link", subFundsReturnedLinkActual.String()).
+ Str("Sub Balance - Link", subBalanceLink.String()).
+ Str("walletBalanceNativeBeforeSubCancelling", walletBalanceNativeBeforeSubCancelling.String()).
+ Str("walletBalanceNativeAfterSubCancelling", walletBalanceNativeAfterSubCancelling.String()).
+ Msg("Sub funds returned")
+
+ //todo - need to use different wallet for each test to verify exact amount of Native/LINK returned
+ //todo - as defaultWallet is used in other tests in parallel which might affect the balance
+ //require.Equal(t, 1, walletBalanceNativeAfterSubCancelling.Cmp(walletBalanceNativeBeforeSubCancelling), "Native funds were not returned after sub cancellation")
+
+ //todo - this fails on SIMULATED env as tx cost is calculated different as for testnets and it's not receipt.EffectiveGasPrice*receipt.GasUsed
+ //require.Equal(t, subFundsReturnedNativeExpected, subFundsReturnedNativeActual, "Returned funds are not equal to sub balance that was cancelled")
+ require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled")
+
+ activeSubscriptionIdsAfterSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ require.NoError(t, err, "error getting active subscription ids")
+
+ require.False(
+ t,
+ utils.BigIntSliceContains(activeSubscriptionIdsAfterSubCancellation, subIDForCancelling),
+ "Active subscription ids should not contain sub id after sub cancellation",
+ )
+ })
+ t.Run("Oracle Withdraw", func(t *testing.T) {
+ testConfig := vrfv2PlusConfig
+ subIDsForOracleWithDraw, err := vrfv2plus.CreateFundSubsAndAddConsumers(
+ env,
+ testConfig,
+ linkToken,
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusContracts.LoadTestConsumers,
+ 1,
+ )
+ require.NoError(t, err)
+ subIDForOracleWithdraw := subIDsForOracleWithDraw[0]
+
+ fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment(
+ vrfv2PlusContracts.LoadTestConsumers[0],
vrfv2PlusContracts.Coordinator,
vrfv2PlusData,
- wrapperSubID,
- isNativeBilling,
- &vrfv2PlusConfig,
+ subIDForOracleWithdraw,
+ false,
+ testConfig.RandomnessRequestCountPerRequest,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
l,
)
- require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
+ require.NoError(t, err)
- expectedSubBalanceWei := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
- require.NoError(t, err, "error getting subscription information")
- subBalanceAfterRequest := wrapperSubscription.NativeBalance
- require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest)
+ fulfilledEventNative, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment(
+ vrfv2PlusContracts.LoadTestConsumers[0],
+ vrfv2PlusContracts.Coordinator,
+ vrfv2PlusData,
+ subIDForOracleWithdraw,
+ true,
+ testConfig.RandomnessRequestCountPerRequest,
+ testConfig,
+ testConfig.RandomWordsFulfilledEventTimeout,
+ l,
+ )
+ require.NoError(t, err)
+ amountToWithdrawLink := fulfilledEventLink.Payment
- consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
- require.NoError(t, err, "error getting rand request status")
- require.True(t, consumerStatus.Fulfilled)
+ defaultWalletBalanceNativeBeforeOracleWithdraw, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ require.NoError(t, err)
- expectedWrapperConsumerWeiBalance := new(big.Int).Sub(wrapperConsumerBalanceBeforeRequestWei, consumerStatus.Paid)
+ defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ require.NoError(t, err)
- wrapperConsumerBalanceAfterRequestWei, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
- require.NoError(t, err, "error getting wrapper consumer balance")
- require.Equal(t, expectedWrapperConsumerWeiBalance, wrapperConsumerBalanceAfterRequestWei)
+ l.Info().
+ Str("Returning to", defaultWalletAddress).
+ Str("Amount", amountToWithdrawLink.String()).
+ Msg("Invoking Oracle Withdraw for LINK")
- //todo: uncomment when VRF-651 will be fixed
- //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub")
- vrfv2plus.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent)
+ err = vrfv2PlusContracts.Coordinator.OracleWithdraw(
+ common.HexToAddress(defaultWalletAddress),
+ amountToWithdrawLink,
+ )
+ require.NoError(t, err, "error withdrawing LINK from coordinator to default wallet")
+ amountToWithdrawNative := fulfilledEventNative.Payment
- require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords)))
- for _, w := range consumerStatus.RandomWords {
- l.Info().Str("Output", w.String()).Msg("Randomness fulfilled")
- require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0")
- }
- })
+ l.Info().
+ Str("Returning to", defaultWalletAddress).
+ Str("Amount", amountToWithdrawNative.String()).
+ Msg("Invoking Oracle Withdraw for Native")
+
+ err = vrfv2PlusContracts.Coordinator.OracleWithdrawNative(
+ common.HexToAddress(defaultWalletAddress),
+ amountToWithdrawNative,
+ )
+ require.NoError(t, err, "error withdrawing Native tokens from coordinator to default wallet")
+
+ err = env.EVMClient.WaitForEvents()
+ require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete)
+ defaultWalletBalanceNativeAfterOracleWithdraw, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ require.NoError(t, err)
+
+ defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ require.NoError(t, err)
+
+ //not possible to verify exact amount of Native/LINK returned as defaultWallet is used in other tests in parallel which might affect the balance
+ require.Equal(t, 1, defaultWalletBalanceNativeAfterOracleWithdraw.Cmp(defaultWalletBalanceNativeBeforeOracleWithdraw), "Native funds were not returned after oracle withdraw native")
+ require.Equal(t, 1, defaultWalletBalanceLinkAfterOracleWithdraw.Cmp(defaultWalletBalanceLinkBeforeOracleWithdraw), "LINK funds were not returned after oracle withdraw")
+ })
}
func TestVRFv2PlusMigration(t *testing.T) {
@@ -270,7 +609,10 @@ func TestVRFv2PlusMigration(t *testing.T) {
linkAddress, err := actions.DeployLINKToken(env.ContractDeployer)
require.NoError(t, err, "error deploying LINK contract")
- vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, &vrfv2PlusConfig, linkAddress, mockETHLinkFeedAddress, 2, 1, l)
+ nativeTokenPrimaryKeyAddress, err := env.ClCluster.NodeAPIs()[0].PrimaryEthAddress()
+ require.NoError(t, err, "error getting primary eth address")
+
+ vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, vrfv2PlusConfig, linkAddress, mockETHLinkFeedAddress, nativeTokenPrimaryKeyAddress, 2, 1, l)
require.NoError(t, err, "error setting up VRF v2_5 env")
subID := subIDs[0]
@@ -395,10 +737,10 @@ func TestVRFv2PlusMigration(t *testing.T) {
expectedLinkTotalBalanceForOldCoordinator := new(big.Int).Sub(oldCoordinatorLinkTotalBalanceBeforeMigration, oldSubscriptionBeforeMigration.Balance)
expectedEthTotalBalanceForOldCoordinator := new(big.Int).Sub(oldCoordinatorEthTotalBalanceBeforeMigration, oldSubscriptionBeforeMigration.NativeBalance)
- require.Equal(t, expectedLinkTotalBalanceForMigratedCoordinator, migratedCoordinatorLinkTotalBalanceAfterMigration)
- require.Equal(t, expectedEthTotalBalanceForMigratedCoordinator, migratedCoordinatorEthTotalBalanceAfterMigration)
- require.Equal(t, expectedLinkTotalBalanceForOldCoordinator, oldCoordinatorLinkTotalBalanceAfterMigration)
- require.Equal(t, expectedEthTotalBalanceForOldCoordinator, oldCoordinatorEthTotalBalanceAfterMigration)
+ require.Equal(t, 0, expectedLinkTotalBalanceForMigratedCoordinator.Cmp(migratedCoordinatorLinkTotalBalanceAfterMigration))
+ require.Equal(t, 0, expectedEthTotalBalanceForMigratedCoordinator.Cmp(migratedCoordinatorEthTotalBalanceAfterMigration))
+ require.Equal(t, 0, expectedLinkTotalBalanceForOldCoordinator.Cmp(oldCoordinatorLinkTotalBalanceAfterMigration))
+ require.Equal(t, 0, expectedEthTotalBalanceForOldCoordinator.Cmp(oldCoordinatorEthTotalBalanceAfterMigration))
//Verify rand requests fulfills with Link Token billing
_, err = vrfv2plus.RequestRandomnessAndWaitForFulfillmentUpgraded(
@@ -407,7 +749,7 @@ func TestVRFv2PlusMigration(t *testing.T) {
vrfv2PlusData,
subID,
false,
- &vrfv2PlusConfig,
+ vrfv2PlusConfig,
l,
)
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
@@ -419,7 +761,7 @@ func TestVRFv2PlusMigration(t *testing.T) {
vrfv2PlusData,
subID,
true,
- &vrfv2PlusConfig,
+ vrfv2PlusConfig,
l,
)
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
diff --git a/integration-tests/utils/common.go b/integration-tests/utils/common.go
index c8243097a7..9aacaeed41 100644
--- a/integration-tests/utils/common.go
+++ b/integration-tests/utils/common.go
@@ -1,6 +1,7 @@
package utils
import (
+ "math/big"
"net"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
@@ -23,3 +24,12 @@ func MustIP(s string) *net.IP {
}
return &ip
}
+
+func BigIntSliceContains(slice []*big.Int, b *big.Int) bool {
+ for _, a := range slice {
+ if b.Cmp(a) == 0 {
+ return true
+ }
+ }
+ return false
+}
From e623afd8079d0875301df33acf74f75e989abcde Mon Sep 17 00:00:00 2001
From: Bartek Tofel
Date: Mon, 6 Nov 2023 11:22:13 +0100
Subject: [PATCH 074/327] move workflow to correct directory (#11168)
---
.../on-demand-log-poller.yml} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename .github/{log_poller_on_demand.yml => workflows/on-demand-log-poller.yml} (95%)
diff --git a/.github/log_poller_on_demand.yml b/.github/workflows/on-demand-log-poller.yml
similarity index 95%
rename from .github/log_poller_on_demand.yml
rename to .github/workflows/on-demand-log-poller.yml
index 856d1e0234..c5470a5a3d 100644
--- a/.github/log_poller_on_demand.yml
+++ b/.github/workflows/on-demand-log-poller.yml
@@ -31,7 +31,7 @@ on:
default: "Sepolia"
required: true
fundingKey:
- description: Private key used to fund the contracts
+ description: Private key used to fund the contracts (must have sufficient ETH and LINK!)
required: true
rpcURL:
description: RPC URL to use
From 28e959668484eeaac3e48ccb44a85b6e35ef21f8 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 6 Nov 2023 10:03:10 -0500
Subject: [PATCH 075/327] Include multiple blocks in observation (#11142)
* Include multiple blocks in observation
* Bump chainlink-relay
* Take the trash out
* Add prom metrics
* Bump chainlink-relay => c28841d7cd41b14fa1207586a905c44f735e9517
* Address PR comments
* Update core/services/relay/evm/mercury/v1/data_source.go
Co-authored-by: martin-cll <121895364+martin-cll@users.noreply.github.com>
* Address PR feedback
* Fix test
---------
Co-authored-by: martin-cll <121895364+martin-cll@users.noreply.github.com>
---
core/chains/evm/types/models.go | 15 ++
core/chains/evm/types/models_test.go | 23 +++
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
.../evm/mercury/mocks/chain_head_tracker.go | 30 +--
.../services/relay/evm/mercury/types/types.go | 2 -
.../relay/evm/mercury/v1/data_source.go | 90 ++++++---
.../relay/evm/mercury/v1/data_source_test.go | 183 ++++++++++--------
docs/CHANGELOG.md | 7 +
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
13 files changed, 221 insertions(+), 147 deletions(-)
diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go
index a71c9e8716..6db5d49575 100644
--- a/core/chains/evm/types/models.go
+++ b/core/chains/evm/types/models.go
@@ -227,6 +227,21 @@ func (h *Head) NextInt() *big.Int {
return new(big.Int).Add(h.ToInt(), big.NewInt(1))
}
+// AsSlice returns a slice of heads up to length k
+// len(heads) may be less than k if the available chain is not long enough
+func (h *Head) AsSlice(k int) (heads []*Head) {
+ if k < 1 || h == nil {
+ return
+ }
+ heads = make([]*Head, 1)
+ heads[0] = h
+ for len(heads) < k && h.Parent != nil {
+ h = h.Parent
+ heads = append(heads, h)
+ }
+ return
+}
+
func (h *Head) UnmarshalJSON(bs []byte) error {
type head struct {
Hash common.Hash `json:"hash"`
diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go
index 2f9dc7dd7c..2911e426e8 100644
--- a/core/chains/evm/types/models_test.go
+++ b/core/chains/evm/types/models_test.go
@@ -129,6 +129,29 @@ func TestHead_ChainLength(t *testing.T) {
assert.Equal(t, uint32(0), head2.ChainLength())
}
+func TestHead_AsSlice(t *testing.T) {
+ h1 := &evmtypes.Head{
+ Number: 1,
+ }
+ h2 := &evmtypes.Head{
+ Number: 2,
+ Parent: h1,
+ }
+ h3 := &evmtypes.Head{
+ Number: 3,
+ Parent: h2,
+ }
+
+ assert.Len(t, (*evmtypes.Head)(nil).AsSlice(0), 0)
+ assert.Len(t, (*evmtypes.Head)(nil).AsSlice(1), 0)
+
+ assert.Len(t, h3.AsSlice(0), 0)
+ assert.Equal(t, []*evmtypes.Head{h3}, h3.AsSlice(1))
+ assert.Equal(t, []*evmtypes.Head{h3, h2}, h3.AsSlice(2))
+ assert.Equal(t, []*evmtypes.Head{h3, h2, h1}, h3.AsSlice(3))
+ assert.Equal(t, []*evmtypes.Head{h3, h2, h1}, h3.AsSlice(4))
+}
+
func TestModels_HexToFunctionSelector(t *testing.T) {
t.Parallel()
fid := evmtypes.HexToFunctionSelector("0xb3f98adc")
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 17c2cff103..6b0a33451e 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -305,7 +305,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index ae1f924c0f..2cb0eb2582 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1466,8 +1466,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 h1:59vz5H52EpwWE/64ZQpNCs7Gtnyi7/ytjyoGjlbKhBA=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de h1:CeVpn5xEdmuEsYE8ss2b7bSq9h3BY4OPvpqXeYIPnHw=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/relay/evm/mercury/mocks/chain_head_tracker.go b/core/services/relay/evm/mercury/mocks/chain_head_tracker.go
index 1a5a7e47c5..b6f2981cf0 100644
--- a/core/services/relay/evm/mercury/mocks/chain_head_tracker.go
+++ b/core/services/relay/evm/mercury/mocks/chain_head_tracker.go
@@ -4,13 +4,11 @@ package mocks
import (
common "github.com/ethereum/go-ethereum/common"
- client "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
-
- commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
-
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
mock "github.com/stretchr/testify/mock"
+
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
)
// ChainHeadTracker is an autogenerated mock type for the ChainHeadTracker type
@@ -18,32 +16,16 @@ type ChainHeadTracker struct {
mock.Mock
}
-// Client provides a mock function with given fields:
-func (_m *ChainHeadTracker) Client() client.Client {
- ret := _m.Called()
-
- var r0 client.Client
- if rf, ok := ret.Get(0).(func() client.Client); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(client.Client)
- }
- }
-
- return r0
-}
-
// HeadTracker provides a mock function with given fields:
-func (_m *ChainHeadTracker) HeadTracker() commontypes.HeadTracker[*evmtypes.Head, common.Hash] {
+func (_m *ChainHeadTracker) HeadTracker() types.HeadTracker[*evmtypes.Head, common.Hash] {
ret := _m.Called()
- var r0 commontypes.HeadTracker[*evmtypes.Head, common.Hash]
- if rf, ok := ret.Get(0).(func() commontypes.HeadTracker[*evmtypes.Head, common.Hash]); ok {
+ var r0 types.HeadTracker[*evmtypes.Head, common.Hash]
+ if rf, ok := ret.Get(0).(func() types.HeadTracker[*evmtypes.Head, common.Hash]); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
- r0 = ret.Get(0).(commontypes.HeadTracker[*evmtypes.Head, common.Hash])
+ r0 = ret.Get(0).(types.HeadTracker[*evmtypes.Head, common.Hash])
}
}
diff --git a/core/services/relay/evm/mercury/types/types.go b/core/services/relay/evm/mercury/types/types.go
index ca266ca8cc..7059689939 100644
--- a/core/services/relay/evm/mercury/types/types.go
+++ b/core/services/relay/evm/mercury/types/types.go
@@ -8,14 +8,12 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
)
//go:generate mockery --quiet --name ChainHeadTracker --output ../mocks/ --case=underscore
type ChainHeadTracker interface {
- Client() evmclient.Client
HeadTracker() httypes.HeadTracker
}
diff --git a/core/services/relay/evm/mercury/v1/data_source.go b/core/services/relay/evm/mercury/v1/data_source.go
index d225dbee68..1b16dc76f9 100644
--- a/core/services/relay/evm/mercury/v1/data_source.go
+++ b/core/services/relay/evm/mercury/v1/data_source.go
@@ -8,6 +8,8 @@ import (
"sync"
pkgerrors "github.com/pkg/errors"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
@@ -25,6 +27,24 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
+var (
+ insufficientBlocksCount = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "mercury_insufficient_blocks_count",
+ Help: fmt.Sprintf("Count of times that there were not enough blocks in the chain during observation (need: %d)", nBlocksObservation),
+ },
+ []string{"feedID"},
+ )
+ zeroBlocksCount = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "mercury_zero_blocks_count",
+ Help: "Count of times that there were zero blocks in the chain during observation",
+ },
+ []string{"feedID"},
+ )
+)
+
+// nBlocksObservation controls how many blocks are included in the LatestBlocks observation
+const nBlocksObservation int = 5
+
type Runner interface {
ExecuteRun(ctx context.Context, spec pipeline.Spec, vars pipeline.Vars, l logger.Logger) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error)
}
@@ -51,18 +71,31 @@ type datasource struct {
chainHeadTracker types.ChainHeadTracker
fetcher Fetcher
initialBlockNumber *int64
+
+ insufficientBlocksCounter prometheus.Counter
+ zeroBlocksCounter prometheus.Counter
}
var _ relaymercuryv1.DataSource = &datasource{}
-func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec pipeline.Spec, lggr logger.Logger, rr chan *pipeline.Run, enhancedTelemChan chan ocrcommon.EnhancedTelemetryMercuryData, chainHeadTracker types.ChainHeadTracker, fetcher Fetcher, initialBlockNumber *int64, feedID [32]byte) *datasource {
- return &datasource{pr, jb, spec, lggr, rr, orm, reportcodec.ReportCodec{}, feedID, sync.RWMutex{}, enhancedTelemChan, chainHeadTracker, fetcher, initialBlockNumber}
+func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec pipeline.Spec, lggr logger.Logger, rr chan *pipeline.Run, enhancedTelemChan chan ocrcommon.EnhancedTelemetryMercuryData, chainHeadTracker types.ChainHeadTracker, fetcher Fetcher, initialBlockNumber *int64, feedID mercuryutils.FeedID) *datasource {
+ return &datasource{pr, jb, spec, lggr, rr, orm, reportcodec.ReportCodec{}, feedID, sync.RWMutex{}, enhancedTelemChan, chainHeadTracker, fetcher, initialBlockNumber, insufficientBlocksCount.WithLabelValues(feedID.String()), zeroBlocksCount.WithLabelValues(feedID.String())}
+}
+
+type ErrEmptyLatestReport struct {
+ Err error
+}
+
+func (e ErrEmptyLatestReport) Unwrap() error { return e.Err }
+
+func (e ErrEmptyLatestReport) Error() string {
+ return fmt.Sprintf("FetchInitialMaxFinalizedBlockNumber returned empty LatestReport; this is a new feed. No initialBlockNumber was set, tried to use current block number to determine maxFinalizedBlockNumber but got error: %v", e.Err)
}
func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedBlockNum bool) (obs relaymercuryv1.Observation, pipelineExecutionErr error) {
- // setCurrentBlock must come first, along with observationTimestamp, to
- // avoid front-running
- ds.setCurrentBlock(ctx, &obs)
+ // setLatestBlocks must come chronologically before observations, along
+ // with observationTimestamp, to avoid front-running
+ ds.setLatestBlocks(ctx, &obs)
var wg sync.WaitGroup
if fetchMaxFinalizedBlockNum {
@@ -89,7 +122,7 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam
}
if ds.initialBlockNumber == nil {
if obs.CurrentBlockNum.Err != nil {
- obs.MaxFinalizedBlockNumber.Err = fmt.Errorf("FetchInitialMaxFinalizedBlockNumber returned empty LatestReport; this is a new feed. No initialBlockNumber was set, tried to use current block number to determine maxFinalizedBlockNumber but got error: %w", obs.CurrentBlockNum.Err)
+ obs.MaxFinalizedBlockNumber.Err = ErrEmptyLatestReport{Err: obs.CurrentBlockNum.Err}
} else {
// Subract 1 here because we will later add 1 to the
// maxFinalizedBlockNumber to get the first validFromBlockNum, which
@@ -258,37 +291,40 @@ func (ds *datasource) executeRun(ctx context.Context) (*pipeline.Run, pipeline.T
return run, trrs, err
}
-func (ds *datasource) setCurrentBlock(ctx context.Context, obs *relaymercuryv1.Observation) {
- latestHead, err := ds.getCurrentBlock(ctx)
- if err != nil {
+func (ds *datasource) setLatestBlocks(ctx context.Context, obs *relaymercuryv1.Observation) {
+ latestBlocks := ds.getLatestBlocks(ctx, nBlocksObservation)
+ if len(latestBlocks) < nBlocksObservation {
+ ds.insufficientBlocksCounter.Inc()
+ ds.lggr.Warnw("Insufficient blocks", "latestBlocks", latestBlocks, "lenLatestBlocks", len(latestBlocks), "nBlocksObservation", nBlocksObservation)
+ }
+
+ // TODO: remove with https://smartcontract-it.atlassian.net/browse/BCF-2209
+ if len(latestBlocks) == 0 {
+ ds.zeroBlocksCounter.Inc()
+ err := errors.New("no blocks available")
obs.CurrentBlockNum.Err = err
obs.CurrentBlockHash.Err = err
obs.CurrentBlockTimestamp.Err = err
- return
+ } else {
+ obs.CurrentBlockNum.Val = latestBlocks[0].Number
+ obs.CurrentBlockHash.Val = latestBlocks[0].Hash.Bytes()
+ if latestBlocks[0].Timestamp.IsZero() {
+ obs.CurrentBlockTimestamp.Val = 0
+ } else {
+ obs.CurrentBlockTimestamp.Val = uint64(latestBlocks[0].Timestamp.Unix())
+ }
}
- obs.CurrentBlockNum.Val = latestHead.Number
- obs.CurrentBlockHash.Val = latestHead.Hash.Bytes()
- if latestHead.Timestamp.IsZero() {
- obs.CurrentBlockTimestamp.Val = 0
- } else {
- obs.CurrentBlockTimestamp.Val = uint64(latestHead.Timestamp.Unix())
+ for _, block := range latestBlocks {
+ obs.LatestBlocks = append(obs.LatestBlocks, relaymercuryv1.NewBlock(block.Number, block.Hash.Bytes(), uint64(block.Timestamp.Unix())))
}
}
-func (ds *datasource) getCurrentBlock(ctx context.Context) (*evmtypes.Head, error) {
- // Use the headtracker's view of the latest block, this is very fast since
+func (ds *datasource) getLatestBlocks(ctx context.Context, k int) (blocks []*evmtypes.Head) {
+ // Use the headtracker's view of the chain, this is very fast since
// it doesn't make any external network requests, and it is the
// headtracker's job to ensure it has an up-to-date view of the chain based
// on responses from all available RPC nodes
latestHead := ds.chainHeadTracker.HeadTracker().LatestChain()
- if latestHead == nil {
- logger.Sugared(ds.lggr).AssumptionViolation("HeadTracker unexpectedly returned nil head, falling back to RPC call")
- var err error
- latestHead, err = ds.chainHeadTracker.Client().HeadByNumber(ctx, nil)
- if err != nil {
- return nil, err
- }
- }
- return latestHead, nil
+ return latestHead.AsSlice(k)
}
diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go
index 6e46095130..42983fa002 100644
--- a/core/services/relay/evm/mercury/v1/data_source_test.go
+++ b/core/services/relay/evm/mercury/v1/data_source_test.go
@@ -11,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
@@ -19,17 +18,17 @@ import (
relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
- evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"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/services/pipeline"
mercurymocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/types"
+ mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
reportcodecv1 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/reportcodec"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -56,11 +55,9 @@ func (m *mockFetcher) LatestTimestamp(context.Context) (int64, error) {
var _ types.ChainHeadTracker = &mockHeadTracker{}
type mockHeadTracker struct {
- c evmclient.Client
h httypes.HeadTracker
}
-func (m *mockHeadTracker) Client() evmclient.Client { return m.c }
func (m *mockHeadTracker) HeadTracker() httypes.HeadTracker { return m.h }
type mockORM struct {
@@ -74,7 +71,8 @@ func (m *mockORM) LatestReport(ctx context.Context, feedID [32]byte, qopts ...pg
func TestMercury_Observe(t *testing.T) {
orm := &mockORM{}
- ds := &datasource{lggr: logger.TestLogger(t), orm: orm, codec: (reportcodecv1.ReportCodec{})}
+ lggr := logger.TestLogger(t)
+ ds := NewDataSource(orm, nil, job.Job{}, pipeline.Spec{}, lggr, nil, nil, nil, nil, nil, mercuryutils.FeedID{})
ctx := testutils.Context(t)
repts := ocrtypes.ReportTimestamp{}
@@ -108,9 +106,7 @@ func TestMercury_Observe(t *testing.T) {
ds.spec = spec
h := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
- c := evmclimocks.NewClient(t)
ht := &mockHeadTracker{
- c: c,
h: h,
}
ds.chainHeadTracker = ht
@@ -202,25 +198,21 @@ func TestMercury_Observe(t *testing.T) {
assert.NoError(t, obs.MaxFinalizedBlockNumber.Err)
assert.Equal(t, head.Number-1, obs.MaxFinalizedBlockNumber.Val)
})
- t.Run("if current block num errored", func(t *testing.T) {
+ t.Run("if no current block available", func(t *testing.T) {
h2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
h2.On("LatestChain").Return((*evmtypes.Head)(nil))
ht.h = h2
- c2 := evmclimocks.NewClient(t)
- c2.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, errors.New("head retrieval failed"))
- ht.c = c2
obs, err := ds.Observe(ctx, repts, true)
assert.NoError(t, err)
- assert.EqualError(t, obs.MaxFinalizedBlockNumber.Err, "FetchInitialMaxFinalizedBlockNumber returned empty LatestReport; this is a new feed. No initialBlockNumber was set, tried to use current block number to determine maxFinalizedBlockNumber but got error: head retrieval failed")
+ assert.EqualError(t, obs.MaxFinalizedBlockNumber.Err, "FetchInitialMaxFinalizedBlockNumber returned empty LatestReport; this is a new feed. No initialBlockNumber was set, tried to use current block number to determine maxFinalizedBlockNumber but got error: no blocks available")
})
})
})
})
ht.h = h
- ht.c = c
t.Run("when fetchMaxFinalizedBlockNum=false", func(t *testing.T) {
t.Run("when run execution fails, returns error", func(t *testing.T) {
@@ -322,52 +314,96 @@ func TestMercury_Observe(t *testing.T) {
t.Fatal("expected run on channel")
}
})
- t.Run("if head tracker returns nil, falls back to RPC method", func(t *testing.T) {
- t.Run("if call succeeds", func(t *testing.T) {
- h = commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
- h.On("LatestChain").Return((*evmtypes.Head)(nil))
- ht.h = h
- c.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once()
-
- obs, err := ds.Observe(ctx, repts, false)
- assert.NoError(t, err)
+ })
- assert.Equal(t, head.Number, obs.CurrentBlockNum.Val)
- assert.NoError(t, obs.CurrentBlockNum.Err)
- assert.Equal(t, fmt.Sprintf("%x", head.Hash), fmt.Sprintf("%x", obs.CurrentBlockHash.Val))
- assert.NoError(t, obs.CurrentBlockHash.Err)
- assert.Equal(t, uint64(head.Timestamp.Unix()), obs.CurrentBlockTimestamp.Val)
- assert.NoError(t, obs.CurrentBlockTimestamp.Err)
+ t.Run("LatestBlocks is populated correctly", func(t *testing.T) {
+ t.Run("when chain length is zero", func(t *testing.T) {
+ ht2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
+ ht2.On("LatestChain").Return((*evmtypes.Head)(nil))
+ ht.h = ht2
- h.AssertExpectations(t)
- c.AssertExpectations(t)
- })
- t.Run("if call fails, returns error for that observation", func(t *testing.T) {
- c = evmclimocks.NewClient(t)
- ht.c = c
- c.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, errors.New("client call failed")).Once()
+ obs, err := ds.Observe(ctx, repts, true)
+ assert.NoError(t, err)
- obs, err := ds.Observe(ctx, repts, false)
- assert.NoError(t, err)
+ assert.Len(t, obs.LatestBlocks, 0)
- assert.Zero(t, obs.CurrentBlockNum.Val)
- assert.EqualError(t, obs.CurrentBlockNum.Err, "client call failed")
- assert.Zero(t, obs.CurrentBlockHash.Val)
- assert.EqualError(t, obs.CurrentBlockHash.Err, "client call failed")
- assert.Zero(t, obs.CurrentBlockTimestamp.Val)
- assert.EqualError(t, obs.CurrentBlockTimestamp.Err, "client call failed")
+ ht2.AssertExpectations(t)
+ })
+ t.Run("when chain is too short", func(t *testing.T) {
+ h4 := &evmtypes.Head{
+ Number: 4,
+ Parent: nil,
+ }
+ h5 := &evmtypes.Head{
+ Number: 5,
+ Parent: h4,
+ }
+ h6 := &evmtypes.Head{
+ Number: 6,
+ Parent: h5,
+ }
- c.AssertExpectations(t)
- })
+ ht2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
+ ht2.On("LatestChain").Return(h6)
+ ht.h = ht2
+
+ obs, err := ds.Observe(ctx, repts, true)
+ assert.NoError(t, err)
+
+ assert.Len(t, obs.LatestBlocks, 3)
+ assert.Equal(t, 6, int(obs.LatestBlocks[0].Num))
+ assert.Equal(t, 5, int(obs.LatestBlocks[1].Num))
+ assert.Equal(t, 4, int(obs.LatestBlocks[2].Num))
+
+ ht2.AssertExpectations(t)
+ })
+ t.Run("when chain is long enough", func(t *testing.T) {
+ h1 := &evmtypes.Head{
+ Number: 1,
+ }
+ h2 := &evmtypes.Head{
+ Number: 2,
+ Parent: h1,
+ }
+ h3 := &evmtypes.Head{
+ Number: 3,
+ Parent: h2,
+ }
+ h4 := &evmtypes.Head{
+ Number: 4,
+ Parent: h3,
+ }
+ h5 := &evmtypes.Head{
+ Number: 5,
+ Parent: h4,
+ }
+ h6 := &evmtypes.Head{
+ Number: 6,
+ Parent: h5,
+ }
+
+ ht2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
+ ht2.On("LatestChain").Return(h6)
+ ht.h = ht2
+
+ obs, err := ds.Observe(ctx, repts, true)
+ assert.NoError(t, err)
+
+ assert.Len(t, obs.LatestBlocks, 5)
+ assert.Equal(t, 6, int(obs.LatestBlocks[0].Num))
+ assert.Equal(t, 5, int(obs.LatestBlocks[1].Num))
+ assert.Equal(t, 4, int(obs.LatestBlocks[2].Num))
+ assert.Equal(t, 3, int(obs.LatestBlocks[3].Num))
+ assert.Equal(t, 2, int(obs.LatestBlocks[4].Num))
+
+ ht2.AssertExpectations(t)
})
})
}
-func TestMercury_SetCurrentBlock(t *testing.T) {
+func TestMercury_SetLatestBlocks(t *testing.T) {
lggr := logger.TestLogger(t)
- ds := datasource{
- lggr: lggr,
- }
+ ds := NewDataSource(nil, nil, job.Job{}, pipeline.Spec{}, lggr, nil, nil, nil, nil, nil, mercuryutils.FeedID{})
h := evmtypes.Head{
Number: testutils.NewRandomPositiveInt64(),
@@ -390,64 +426,41 @@ func TestMercury_SetCurrentBlock(t *testing.T) {
ds.chainHeadTracker = chainHeadTracker
obs := relaymercuryv1.Observation{}
- ds.setCurrentBlock(context.Background(), &obs)
+ ds.setLatestBlocks(context.Background(), &obs)
assert.Equal(t, h.Number, obs.CurrentBlockNum.Val)
assert.Equal(t, h.Hash.Bytes(), obs.CurrentBlockHash.Val)
assert.Equal(t, uint64(h.Timestamp.Unix()), obs.CurrentBlockTimestamp.Val)
- chainHeadTracker.AssertExpectations(t)
- headTracker.AssertExpectations(t)
- })
-
- t.Run("if headtracker returns nil head and eth call succeeds", func(t *testing.T) {
- ethClient := evmclimocks.NewClient(t)
- headTracker := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
- chainHeadTracker := mercurymocks.NewChainHeadTracker(t)
-
- chainHeadTracker.On("Client").Return(ethClient)
- chainHeadTracker.On("HeadTracker").Return(headTracker)
- // This can happen in some cases e.g. RPC node is offline
- headTracker.On("LatestChain").Return((*evmtypes.Head)(nil))
- ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(&h, nil)
-
- ds.chainHeadTracker = chainHeadTracker
-
- obs := relaymercuryv1.Observation{}
- ds.setCurrentBlock(context.Background(), &obs)
-
- assert.Equal(t, h.Number, obs.CurrentBlockNum.Val)
- assert.Equal(t, h.Hash.Bytes(), obs.CurrentBlockHash.Val)
- assert.Equal(t, uint64(h.Timestamp.Unix()), obs.CurrentBlockTimestamp.Val)
+ assert.Len(t, obs.LatestBlocks, 1)
chainHeadTracker.AssertExpectations(t)
- ethClient.AssertExpectations(t)
headTracker.AssertExpectations(t)
})
- t.Run("if headtracker returns nil head and eth call fails", func(t *testing.T) {
- ethClient := evmclimocks.NewClient(t)
+ t.Run("if headtracker returns nil head", func(t *testing.T) {
headTracker := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
chainHeadTracker := mercurymocks.NewChainHeadTracker(t)
- chainHeadTracker.On("Client").Return(ethClient)
chainHeadTracker.On("HeadTracker").Return(headTracker)
// This can happen in some cases e.g. RPC node is offline
headTracker.On("LatestChain").Return((*evmtypes.Head)(nil))
- err := errors.New("foo")
- ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, err)
ds.chainHeadTracker = chainHeadTracker
obs := relaymercuryv1.Observation{}
- ds.setCurrentBlock(context.Background(), &obs)
+ ds.setLatestBlocks(context.Background(), &obs)
+
+ assert.Zero(t, obs.CurrentBlockNum.Val)
+ assert.Zero(t, obs.CurrentBlockHash.Val)
+ assert.Zero(t, obs.CurrentBlockTimestamp.Val)
+ assert.EqualError(t, obs.CurrentBlockNum.Err, "no blocks available")
+ assert.EqualError(t, obs.CurrentBlockHash.Err, "no blocks available")
+ assert.EqualError(t, obs.CurrentBlockTimestamp.Err, "no blocks available")
- assert.Equal(t, err, obs.CurrentBlockNum.Err)
- assert.Equal(t, err, obs.CurrentBlockHash.Err)
- assert.Equal(t, err, obs.CurrentBlockTimestamp.Err)
+ assert.Len(t, obs.LatestBlocks, 0)
chainHeadTracker.AssertExpectations(t)
- ethClient.AssertExpectations(t)
headTracker.AssertExpectations(t)
})
}
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index b5b393542b..a9f9d080f4 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -22,6 +22,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed `Optimism2` as a supported gas estimator mode
+### Added
+
+- Mercury v0.2 has improved consensus around current block that uses the most recent 5 blocks instead of only the latest one
+- Two new prom metrics for mercury, nops should consider adding alerting on these:
+ - `mercury_insufficient_blocks_count`
+ - `mercury_zero_blocks_count`
+
...
## 2.7.0 - UNRELEASED
diff --git a/go.mod b/go.mod
index 999c1b0402..f271bf421f 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index ee06cc9b75..8426876e23 100644
--- a/go.sum
+++ b/go.sum
@@ -1467,8 +1467,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 h1:59vz5H52EpwWE/64ZQpNCs7Gtnyi7/ytjyoGjlbKhBA=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de h1:CeVpn5xEdmuEsYE8ss2b7bSq9h3BY4OPvpqXeYIPnHw=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 93820c6ebf..c4e6fd3848 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -388,7 +388,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 60805eae82..4744fc086a 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2370,8 +2370,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672 h1:59vz5H52EpwWE/64ZQpNCs7Gtnyi7/ytjyoGjlbKhBA=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231101203911-c686b4d48672/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de h1:CeVpn5xEdmuEsYE8ss2b7bSq9h3BY4OPvpqXeYIPnHw=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From b24af1367e5af984db6ebf8523e9949bad736516 Mon Sep 17 00:00:00 2001
From: Andrei Smirnov
Date: Mon, 6 Nov 2023 18:13:43 +0300
Subject: [PATCH 076/327] Functions: fixed subscriptions tracking logic
(#11167)
* Functions: fixed subscriptions tracking logic
* Addressed PR feedback
* Addressed PR feedback
* Addressed PR feedback
---
.../handlers/functions/handler.functions.go | 12 ++++-
.../handlers/functions/subscriptions.go | 22 ++++----
.../handlers/functions/subscriptions_test.go | 52 +++++++++++++++++--
3 files changed, 67 insertions(+), 19 deletions(-)
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index 01f450a4ea..d0011145d4 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "math/big"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -178,8 +179,15 @@ func (h *functionsHandler) HandleUserMessage(ctx context.Context, msg *api.Messa
return ErrRateLimited
}
if h.subscriptions != nil && h.minimumBalance != nil {
- if balance, err := h.subscriptions.GetMaxUserBalance(sender); err != nil || balance.Cmp(h.minimumBalance.ToInt()) < 0 {
- h.lggr.Debug("received a message from a user having insufficient balance", "sender", msg.Body.Sender, "balance", balance.String())
+ balance, err := h.subscriptions.GetMaxUserBalance(sender)
+ if err != nil {
+ h.lggr.Debugw("error getting max user balance", "sender", msg.Body.Sender, "err", err)
+ }
+ if balance == nil {
+ balance = big.NewInt(0)
+ }
+ if err != nil || balance.Cmp(h.minimumBalance.ToInt()) < 0 {
+ h.lggr.Debugw("received a message from a user having insufficient balance", "sender", msg.Body.Sender, "balance", balance.String())
return fmt.Errorf("sender has insufficient balance: %v juels", balance.String())
}
}
diff --git a/core/services/gateway/handlers/functions/subscriptions.go b/core/services/gateway/handlers/functions/subscriptions.go
index 79233b1031..c7a6519e69 100644
--- a/core/services/gateway/handlers/functions/subscriptions.go
+++ b/core/services/gateway/handlers/functions/subscriptions.go
@@ -130,19 +130,16 @@ func (s *onchainSubscriptions) queryLoop() {
blockNumber := big.NewInt(0).Sub(latestBlockHeight, s.blockConfirmations)
- updateLastKnownCount := func() {
+ if lastKnownCount == 0 || start > lastKnownCount {
count, err := s.getSubscriptionsCount(ctx, blockNumber)
if err != nil {
- s.lggr.Errorw("Error getting subscriptions count", "err", err)
- return
+ s.lggr.Errorw("Error getting new subscriptions count", "err", err)
+ } else {
+ s.lggr.Infow("Updated subscriptions count", "count", count, "blockNumber", blockNumber.Int64())
+ lastKnownCount = count
}
- s.lggr.Infow("Updated subscriptions count", "err", err, "count", count, "blockNumber", blockNumber.Int64())
- lastKnownCount = count
}
- if lastKnownCount == 0 {
- updateLastKnownCount()
- }
if lastKnownCount == 0 {
s.lggr.Info("Router has no subscriptions yet")
return
@@ -152,12 +149,9 @@ func (s *onchainSubscriptions) queryLoop() {
start = 1
}
- end := start + uint64(s.config.UpdateRangeSize)
+ end := start + uint64(s.config.UpdateRangeSize) - 1
if end > lastKnownCount {
- updateLastKnownCount()
- if end > lastKnownCount {
- end = lastKnownCount
- }
+ end = lastKnownCount
}
if err := s.querySubscriptionsRange(ctx, blockNumber, start, end); err != nil {
s.lggr.Errorw("Error querying subscriptions", "err", err, "start", start, "end", end)
@@ -180,6 +174,8 @@ func (s *onchainSubscriptions) queryLoop() {
}
func (s *onchainSubscriptions) querySubscriptionsRange(ctx context.Context, blockNumber *big.Int, start, end uint64) error {
+ s.lggr.Debugw("Querying subscriptions", "blockNumber", blockNumber, "start", start, "end", end)
+
subscriptions, err := s.router.GetSubscriptionsInRange(&bind.CallOpts{
Pending: false,
BlockNumber: blockNumber,
diff --git a/core/services/gateway/handlers/functions/subscriptions_test.go b/core/services/gateway/handlers/functions/subscriptions_test.go
index 1e46bff5c0..adbf637ad7 100644
--- a/core/services/gateway/handlers/functions/subscriptions_test.go
+++ b/core/services/gateway/handlers/functions/subscriptions_test.go
@@ -2,6 +2,7 @@ package functions_test
import (
"math/big"
+ "sync/atomic"
"testing"
"time"
@@ -24,9 +25,7 @@ const (
invalidUser = "0x6E2dc0F9DB014aE19888F539E59285D2Ea04244C"
)
-func TestSubscriptions(t *testing.T) {
- t.Parallel()
-
+func TestSubscriptions_OnePass(t *testing.T) {
getSubscriptionCount := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000003")
getSubscriptionsInRange := hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000109e6e1b12098cc8f3a1e9719a817ec53ab9b35c000000000000000000000000000000000000000000000000000034e23f515cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5340f0968ee8b7dfd97e3327a6139273cc2c4fa000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bc14b92364c75e20000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005439e5881a529f3ccbffc0e82d49f9db3950aefe")
@@ -46,7 +45,7 @@ func TestSubscriptions(t *testing.T) {
BlockConfirmations: 1,
UpdateFrequencySec: 1,
UpdateTimeoutSec: 1,
- UpdateRangeSize: 10,
+ UpdateRangeSize: 3,
}
subscriptions, err := functions.NewOnchainSubscriptions(client, config, logger.TestLogger(t))
require.NoError(t, err)
@@ -57,6 +56,7 @@ func TestSubscriptions(t *testing.T) {
assert.NoError(t, subscriptions.Close())
})
+ // initially we have 3 subs and range is 3, which needs one pass
gomega.NewGomegaWithT(t).Eventually(func() bool {
expectedBalance := big.NewInt(0).SetBytes(hexutil.MustDecode("0x01158e460913d00000"))
balance, err1 := subscriptions.GetMaxUserBalance(common.HexToAddress(validUser))
@@ -64,3 +64,47 @@ func TestSubscriptions(t *testing.T) {
return err1 == nil && err2 != nil && balance.Cmp(expectedBalance) == 0
}, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
}
+
+func TestSubscriptions_MultiPass(t *testing.T) {
+ const ncycles int32 = 5
+ var currentCycle atomic.Int32
+ getSubscriptionCount := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000006")
+ getSubscriptionsInRange := hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000109e6e1b12098cc8f3a1e9719a817ec53ab9b35c000000000000000000000000000000000000000000000000000034e23f515cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5340f0968ee8b7dfd97e3327a6139273cc2c4fa000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bc14b92364c75e20000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005439e5881a529f3ccbffc0e82d49f9db3950aefe")
+
+ ctx := testutils.Context(t)
+ client := mocks.NewClient(t)
+ client.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(42), nil)
+ client.On("CallContract", mock.Anything, ethereum.CallMsg{ // getSubscriptionCount
+ To: &common.Address{},
+ Data: hexutil.MustDecode("0x66419970"),
+ }, mock.Anything).Run(func(args mock.Arguments) {
+ currentCycle.Add(1)
+ }).Return(getSubscriptionCount, nil)
+ client.On("CallContract", mock.Anything, ethereum.CallMsg{ // GetSubscriptionsInRange(1,3)
+ To: &common.Address{},
+ Data: hexutil.MustDecode("0xec2454e500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003"),
+ }, mock.Anything).Return(getSubscriptionsInRange, nil)
+ client.On("CallContract", mock.Anything, ethereum.CallMsg{ // GetSubscriptionsInRange(4,6)
+ To: &common.Address{},
+ Data: hexutil.MustDecode("0xec2454e500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006"),
+ }, mock.Anything).Return(getSubscriptionsInRange, nil)
+ config := functions.OnchainSubscriptionsConfig{
+ ContractAddress: common.Address{},
+ BlockConfirmations: 1,
+ UpdateFrequencySec: 1,
+ UpdateTimeoutSec: 1,
+ UpdateRangeSize: 3,
+ }
+ subscriptions, err := functions.NewOnchainSubscriptions(client, config, logger.TestLogger(t))
+ require.NoError(t, err)
+
+ err = subscriptions.Start(ctx)
+ require.NoError(t, err)
+ t.Cleanup(func() {
+ assert.NoError(t, subscriptions.Close())
+ })
+
+ gomega.NewGomegaWithT(t).Eventually(func() bool {
+ return currentCycle.Load() == ncycles
+ }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue())
+}
From a7572683ba10864d98fd1d7cffd27889908d8e22 Mon Sep 17 00:00:00 2001
From: Sri Kidambi <1702865+kidambisrinivas@users.noreply.github.com>
Date: Mon, 6 Nov 2023 17:56:59 +0000
Subject: [PATCH 077/327] Update hardhat config for ArbSepolia and V2_5
(#11177)
* Update hardhat config for ArbSepolia and V2_5
* Prettier fix
* Minor fix
---
contracts/hardhat.config.ts | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts
index 521345ffc9..5306827b8e 100644
--- a/contracts/hardhat.config.ts
+++ b/contracts/hardhat.config.ts
@@ -105,6 +105,18 @@ let config = {
},
},
},
+ 'src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol': {
+ version: '0.8.6',
+ settings: {
+ optimizer: {
+ enabled: true,
+ runs: 50, // see native_solc_compile_all_vrf
+ },
+ metadata: {
+ bytecodeHash: 'none',
+ },
+ },
+ },
},
},
contractSizer: {
From bda4d5aba0cada85b4dceca88415718d3afd70a8 Mon Sep 17 00:00:00 2001
From: Kashif
Date: Tue, 7 Nov 2023 03:13:11 +0900
Subject: [PATCH 078/327] Add kroma support (#11179)
* Add kroma support
* Bump ctf for kroma client support
* add kroma l1 gas test
---
.github/workflows/on-demand-ocr-soak-test.yml | 2 +
.../config/toml/defaults/Kroma_Mainnet.toml | 26 +++
.../config/toml/defaults/Kroma_Sepolia.toml | 26 +++
core/chains/evm/gas/chain_specific.go | 2 +-
.../evm/gas/rollups/l1_gas_price_oracle.go | 12 +-
.../gas/rollups/l1_gas_price_oracle_test.go | 22 +++
core/config/chaintype.go | 4 +-
core/config/docs/chains-evm.toml | 2 +-
core/services/chainlink/config_test.go | 4 +-
core/services/ocr/contract_tracker.go | 2 +-
docs/CONFIG.md | 160 +++++++++++++++++-
.../contracts/contract_deployer.go | 6 +
integration-tests/go.mod | 4 +-
integration-tests/go.sum | 6 +-
14 files changed, 263 insertions(+), 15 deletions(-)
create mode 100644 core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml
create mode 100644 core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index 4a18aabf22..1e510c23be 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -26,6 +26,8 @@ on:
- "LINEA_MAINNET"
- "FANTOM_TESTNET"
- "FANTOM_MAINNET"
+ - "KROMA_MAINNET"
+ - "KROMA_SEPOLIA"
fundingPrivateKey:
description: Private funding key (Skip for Simulated)
required: false
diff --git a/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml b/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml
new file mode 100644
index 0000000000..55154bf766
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml
@@ -0,0 +1,26 @@
+ChainID = '255'
+ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture
+FinalityDepth = 400
+LogPollInterval = '2s'
+NoNewHeadsThreshold = '40s'
+MinIncomingConfirmations = 1
+
+[GasEstimator]
+EIP1559DynamicFees = true
+PriceMin = '1 wei'
+BumpMin = '100 wei'
+
+[GasEstimator.BlockHistory]
+BlockHistorySize = 24
+
+[Transactions]
+ResendAfterThreshold = '30s'
+
+[HeadTracker]
+HistoryDepth = 400
+
+[NodePool]
+SyncThreshold = 10
+
+[OCR]
+ContractConfirmations = 1
diff --git a/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml b/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml
new file mode 100644
index 0000000000..643b0556b3
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml
@@ -0,0 +1,26 @@
+ChainID = '2358'
+ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture
+FinalityDepth = 400
+LogPollInterval = '2s'
+NoNewHeadsThreshold = '40s'
+MinIncomingConfirmations = 1
+
+[GasEstimator]
+EIP1559DynamicFees = true
+PriceMin = '1 wei'
+BumpMin = '100 wei'
+
+[GasEstimator.BlockHistory]
+BlockHistorySize = 24
+
+[Transactions]
+ResendAfterThreshold = '30s'
+
+[HeadTracker]
+HistoryDepth = 400
+
+[NodePool]
+SyncThreshold = 10
+
+[OCR]
+ContractConfirmations = 1
diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go
index cd38f49ee0..4d87b8b454 100644
--- a/core/chains/evm/gas/chain_specific.go
+++ b/core/chains/evm/gas/chain_specific.go
@@ -19,7 +19,7 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy
return false
}
}
- if chainType == config.ChainOptimismBedrock {
+ if chainType == config.ChainOptimismBedrock || chainType == config.ChainKroma {
// This is a special deposit transaction type introduced in Bedrock upgrade.
// This is a system transaction that it will occur at least one time per block.
// We should discard this type before even processing it to avoid flooding the
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
index c15aa23c79..d990017bd0 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
@@ -57,11 +57,18 @@ const (
// `function l1BaseFee() external view returns (uint256);`
OPGasOracle_l1BaseFee = "519b4bd3"
+ // GasOracleAddress is the address of the precompiled contract that exists on Kroma chain.
+ // This is the case for Kroma.
+ KromaGasOracleAddress = "0x4200000000000000000000000000000000000005"
+ // GasOracle_l1BaseFee is the a hex encoded call to:
+ // `function l1BaseFee() external view returns (uint256);`
+ KromaGasOracle_l1BaseFee = "519b4bd3"
+
// Interval at which to poll for L1BaseFee. A good starting point is the L1 block time.
PollPeriod = 12 * time.Second
)
-var supportedChainTypes = []config.ChainType{config.ChainArbitrum, config.ChainOptimismBedrock}
+var supportedChainTypes = []config.ChainType{config.ChainArbitrum, config.ChainOptimismBedrock, config.ChainKroma}
func IsRollupWithL1Support(chainType config.ChainType) bool {
return slices.Contains(supportedChainTypes, chainType)
@@ -76,6 +83,9 @@ func NewL1GasPriceOracle(lggr logger.Logger, ethClient ethClient, chainType conf
case config.ChainOptimismBedrock:
address = OPGasOracleAddress
callArgs = OPGasOracle_l1BaseFee
+ case config.ChainKroma:
+ address = KromaGasOracleAddress
+ callArgs = KromaGasOracle_l1BaseFee
default:
panic(fmt.Sprintf("Received unspported chaintype %s", chainType))
}
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go
index 9fd2a66201..320c9cb71d 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go
@@ -59,6 +59,28 @@ func TestL1GasPriceOracle(t *testing.T) {
assert.Equal(t, assets.NewWei(l1BaseFee), gasPrice)
})
+ t.Run("Calling GasPrice on started Kroma L1Oracle returns Kroma l1GasPrice", func(t *testing.T) {
+ l1BaseFee := big.NewInt(200)
+
+ ethClient := mocks.NewETHClient(t)
+ ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
+ callMsg := args.Get(1).(ethereum.CallMsg)
+ blockNumber := args.Get(2).(*big.Int)
+ assert.Equal(t, KromaGasOracleAddress, callMsg.To.String())
+ assert.Equal(t, KromaGasOracle_l1BaseFee, fmt.Sprintf("%x", callMsg.Data))
+ assert.Nil(t, blockNumber)
+ }).Return(common.BigToHash(l1BaseFee).Bytes(), nil)
+
+ oracle := NewL1GasPriceOracle(logger.TestLogger(t), ethClient, config.ChainKroma)
+ require.NoError(t, oracle.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, oracle.Close()) })
+
+ gasPrice, err := oracle.GasPrice(testutils.Context(t))
+ require.NoError(t, err)
+
+ assert.Equal(t, assets.NewWei(l1BaseFee), gasPrice)
+ })
+
t.Run("Calling GasPrice on started OPStack L1Oracle returns OPStack l1GasPrice", func(t *testing.T) {
l1BaseFee := big.NewInt(200)
diff --git a/core/config/chaintype.go b/core/config/chaintype.go
index fe67b0925a..c99099ee61 100644
--- a/core/config/chaintype.go
+++ b/core/config/chaintype.go
@@ -15,16 +15,18 @@ const (
ChainOptimismBedrock ChainType = "optimismBedrock"
ChainXDai ChainType = "xdai"
ChainCelo ChainType = "celo"
+ ChainKroma ChainType = "kroma"
)
var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Join([]string{
string(ChainArbitrum), string(ChainMetis), string(ChainXDai), string(ChainOptimismBedrock), string(ChainCelo),
+ string(ChainKroma),
}, ", "))
// IsValid returns true if the ChainType value is known or empty.
func (c ChainType) IsValid() bool {
switch c {
- case "", ChainArbitrum, ChainMetis, ChainOptimismBedrock, ChainXDai, ChainCelo:
+ case "", ChainArbitrum, ChainMetis, ChainOptimismBedrock, ChainXDai, ChainCelo, ChainKroma:
return true
}
return false
diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml
index 0e0d0d0bd8..082bbd6cd1 100644
--- a/core/config/docs/chains-evm.toml
+++ b/core/config/docs/chains-evm.toml
@@ -14,7 +14,7 @@ BlockBackfillDepth = 10 # Default
# BlockBackfillSkip enables skipping of very long backfills.
BlockBackfillSkip = false # Default
# ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
-# Available types: arbitrum, metis, optimismBedrock, xdai
+# Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma
ChainType = 'arbitrum' # Example
# FinalityDepth is the number of blocks after which an ethereum transaction is considered "final". Note that the default is automatically set based on chain ID so it should not be necessary to change this under normal operation.
# BlocksConsideredFinal determines how deeply we look back to ensure that transactions are confirmed onto the longest chain
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 96e6db42c8..59a02f1dcf 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -1190,7 +1190,7 @@ func TestConfig_Validate(t *testing.T) {
- 1: 6 errors:
- ChainType: invalid value (Foo): must not be set with this chain id
- Nodes: missing: must have at least one node
- - ChainType: invalid value (Foo): must be one of arbitrum, metis, xdai, optimismBedrock, celo or omitted
+ - ChainType: invalid value (Foo): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma or omitted
- HeadTracker.HistoryDepth: invalid value (30): must be equal to or greater than FinalityDepth
- GasEstimator: 2 errors:
- FeeCapDefault: invalid value (101 wei): must be equal to PriceMax (99 wei) since you are using FixedPrice estimation with gas bumping disabled in EIP1559 mode - PriceMax will be used as the FeeCap for transactions instead of FeeCapDefault
@@ -1199,7 +1199,7 @@ func TestConfig_Validate(t *testing.T) {
- 2: 5 errors:
- ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id
- Nodes: missing: must have at least one node
- - ChainType: invalid value (Arbitrum): must be one of arbitrum, metis, xdai, optimismBedrock, celo or omitted
+ - ChainType: invalid value (Arbitrum): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma or omitted
- FinalityDepth: invalid value (0): must be greater than or equal to 1
- MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1
- 3.Nodes: 5 errors:
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index c5f3e431e4..3a216e025f 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -401,7 +401,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight
// care about the block height; we have no way of getting the L1 block
// height anyway
return 0, nil
- case "", config.ChainArbitrum, config.ChainCelo, config.ChainOptimismBedrock, config.ChainXDai:
+ case "", config.ChainArbitrum, config.ChainCelo, config.ChainOptimismBedrock, config.ChainXDai, config.ChainKroma:
// continue
}
latestBlockHeight := t.getLatestBlockHeight()
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 23508df172..4b55c804a3 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -2907,6 +2907,85 @@ GasLimit = 3800000
+Kroma Mainnet (255)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'kroma'
+FinalityDepth = 400
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '2s'
+LogKeepBlocksDepth = 100000
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '40s'
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '30s'
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'BlockHistory'
+PriceDefault = '20 gwei'
+PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+PriceMin = '1 wei'
+LimitDefault = 500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+BumpMin = '100 wei'
+BumpPercent = 20
+BumpThreshold = 3
+EIP1559DynamicFees = true
+FeeCapDefault = '100 gwei'
+TipCapDefault = '1 wei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 24
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[HeadTracker]
+HistoryDepth = 400
+MaxBufferSize = 3
+SamplingInterval = '1s'
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 10
+LeaseDuration = '0s'
+
+[OCR]
+ContractConfirmations = 1
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5300000
+```
+
+
+
Optimism Goerli (420)
```toml
@@ -3301,6 +3380,85 @@ GasLimit = 5300000
+Kroma Sepolia (2358)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'kroma'
+FinalityDepth = 400
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '2s'
+LogKeepBlocksDepth = 100000
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '40s'
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '30s'
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'BlockHistory'
+PriceDefault = '20 gwei'
+PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+PriceMin = '1 wei'
+LimitDefault = 500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+BumpMin = '100 wei'
+BumpPercent = 20
+BumpThreshold = 3
+EIP1559DynamicFees = true
+FeeCapDefault = '100 gwei'
+TipCapDefault = '1 wei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 24
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[HeadTracker]
+HistoryDepth = 400
+MaxBufferSize = 3
+SamplingInterval = '1s'
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 10
+LeaseDuration = '0s'
+
+[OCR]
+ContractConfirmations = 1
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5300000
+```
+
+
+
Fantom Testnet (4002)
```toml
@@ -4916,7 +5074,7 @@ BlockBackfillSkip enables skipping of very long backfills.
ChainType = 'arbitrum' # Example
```
ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
-Available types: arbitrum, metis, optimismBedrock, xdai
+Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma
### FinalityDepth
```toml
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index 5a3fad256e..0c36a26081 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -173,6 +173,8 @@ func NewContractDeployer(bcClient blockchain.EVMClient, logger zerolog.Logger) (
return &LineaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
case *blockchain.FantomClient:
return &FantomContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
+ case *blockchain.KromaClient:
+ return &KromaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
}
return nil, errors.New("unknown blockchain client implementation for contract deployer, register blockchain client in NewContractDeployer")
}
@@ -240,6 +242,10 @@ type FantomContractDeployer struct {
*EthereumContractDeployer
}
+type KromaContractDeployer struct {
+ *EthereumContractDeployer
+}
+
// NewEthereumContractDeployer returns an instantiated instance of the ETH contract deployer
func NewEthereumContractDeployer(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractDeployer {
return &EthereumContractDeployer{
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index c4e6fd3848..f73838f1ab 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,7 +22,7 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.2-0.20231030212542-5fb562e774a5
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.27
@@ -427,7 +427,6 @@ require (
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.1.0 // indirect
- github.com/yuin/goldmark v1.4.13 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/zondax/hid v0.9.1 // indirect
github.com/zondax/ledger-go v0.14.1 // indirect
@@ -455,7 +454,6 @@ require (
golang.org/x/arch v0.4.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
- golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 4744fc086a..843cef2690 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2376,8 +2376,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.2-0.20231030212542-5fb562e774a5 h1:4hTf8pvtdtwoaeKFSEYjBZPvDbZ05WgiHsb0TPL6HqQ=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.2-0.20231030212542-5fb562e774a5/go.mod h1:lMdEUTdSmzldCwqf+todFEyebE9Vlb23+5rvIHJBPOk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66 h1:AOqcHiAppMoIvM2WSJNIZzJDnOQNXyElbLFK3ZqoJeM=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
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=
@@ -2578,7 +2578,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
@@ -2765,7 +2764,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
From 0f66f7fd324fb0b8ecef07989eee7dd55bdcdf32 Mon Sep 17 00:00:00 2001
From: Dimitris Grigoriou
Date: Mon, 6 Nov 2023 20:28:52 +0200
Subject: [PATCH 079/327] Move common client models to correct path (#11169)
* Move common client models to correct path
* Drop unnecessary aliases
---
common/{chains => }/client/models.go | 0
common/client/multi_node.go | 7 +-
common/client/node.go | 5 +-
common/client/send_only_node.go | 3 +-
common/txmgr/broadcaster.go | 24 +++---
common/txmgr/confirmer.go | 20 ++---
common/txmgr/resender.go | 8 +-
common/txmgr/types/client.go | 6 +-
core/chains/evm/client/chain_client.go | 3 +-
core/chains/evm/client/client.go | 6 +-
core/chains/evm/client/client_test.go | 57 +++++++------
core/chains/evm/client/errors.go | 38 ++++-----
core/chains/evm/client/helpers_test.go | 5 +-
core/chains/evm/client/mocks/client.go | 14 ++--
core/chains/evm/client/null_client.go | 6 +-
core/chains/evm/client/rpc_client.go | 5 +-
.../evm/client/simulated_backend_client.go | 10 +--
core/chains/evm/txmgr/broadcaster_test.go | 82 +++++++++---------
core/chains/evm/txmgr/client.go | 20 ++---
core/chains/evm/txmgr/confirmer_test.go | 84 +++++++++----------
core/cmd/shell_local_test.go | 24 +++---
core/internal/cltest/cltest.go | 4 +-
22 files changed, 212 insertions(+), 219 deletions(-)
rename common/{chains => }/client/models.go (100%)
diff --git a/common/chains/client/models.go b/common/client/models.go
similarity index 100%
rename from common/chains/client/models.go
rename to common/client/models.go
diff --git a/common/client/multi_node.go b/common/client/multi_node.go
index 0da3b89076..f54e3115d9 100644
--- a/common/client/multi_node.go
+++ b/common/client/multi_node.go
@@ -13,7 +13,6 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/common/chains/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
@@ -121,7 +120,7 @@ type multiNode[
chStop utils.StopChan
wg sync.WaitGroup
- sendOnlyErrorParser func(err error) client.SendTxReturnCode
+ sendOnlyErrorParser func(err error) SendTxReturnCode
}
func NewMultiNode[
@@ -147,7 +146,7 @@ func NewMultiNode[
chainID CHAIN_ID,
chainType config.ChainType,
chainFamily string,
- sendOnlyErrorParser func(err error) client.SendTxReturnCode,
+ sendOnlyErrorParser func(err error) SendTxReturnCode,
) MultiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT] {
nodeSelector := func() NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] {
switch selectionMode {
@@ -605,7 +604,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP
txErr := n.RPC().SendTransaction(ctx, tx)
c.logger.Debugw("Sendonly node sent transaction", "name", n.String(), "tx", tx, "err", txErr)
sendOnlyError := c.sendOnlyErrorParser(txErr)
- if sendOnlyError != client.Successful {
+ if sendOnlyError != Successful {
c.logger.Warnw("RPC returned error", "name", n.String(), "tx", tx, "err", txErr)
}
}(n)
diff --git a/common/client/node.go b/common/client/node.go
index 71b34452f0..20d098e03f 100644
--- a/common/client/node.go
+++ b/common/client/node.go
@@ -13,7 +13,6 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/common/chains/client"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -136,7 +135,7 @@ func NewNode[
}
n.nodeCtx, n.cancelNodeCtx = context.WithCancel(context.Background())
lggr = lggr.Named("Node").With(
- "nodeTier", client.Primary.String(),
+ "nodeTier", Primary.String(),
"nodeName", name,
"node", n.String(),
"chainID", chainID,
@@ -150,7 +149,7 @@ func NewNode[
}
func (n *node[CHAIN_ID, HEAD, RPC]) String() string {
- s := fmt.Sprintf("(%s)%s:%s", client.Primary.String(), n.name, n.ws.String())
+ s := fmt.Sprintf("(%s)%s:%s", Primary.String(), n.name, n.ws.String())
if n.http != nil {
s = s + fmt.Sprintf(":%s", n.http.String())
}
diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go
index 3b382b2dcb..0051fb014d 100644
--- a/common/client/send_only_node.go
+++ b/common/client/send_only_node.go
@@ -8,7 +8,6 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/common/chains/client"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -159,7 +158,7 @@ func (s *sendOnlyNode[CHAIN_ID, RPC]) RPC() RPC {
}
func (s *sendOnlyNode[CHAIN_ID, RPC]) String() string {
- return fmt.Sprintf("(%s)%s:%s", client.Secondary.String(), s.name, s.uri.Redacted())
+ return fmt.Sprintf("(%s)%s:%s", Secondary.String(), s.name, s.uri.Redacted())
}
func (s *sendOnlyNode[CHAIN_ID, RPC]) setState(state nodeState) (changed bool) {
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index 4f6ffae2ad..80c7adbfc1 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -15,7 +15,7 @@ import (
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
@@ -553,19 +553,19 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
lgr.Infow("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", etx.FeeLimit, "attempt", attempt, "etx", etx)
errType, err := eb.client.SendTransactionReturnCode(ctx, etx, attempt, lgr)
- if errType != clienttypes.Fatal {
+ if errType != client.Fatal {
etx.InitialBroadcastAt = &initialBroadcastAt
etx.BroadcastAt = &initialBroadcastAt
}
switch errType {
- case clienttypes.Fatal:
+ case client.Fatal:
eb.SvcErrBuffer.Append(err)
etx.Error = null.StringFrom(err.Error())
return eb.saveFatallyErroredTransaction(lgr, &etx), true
- case clienttypes.TransactionAlreadyKnown:
+ case client.TransactionAlreadyKnown:
fallthrough
- case clienttypes.Successful:
+ case client.Successful:
// Either the transaction was successful or one of the following four scenarios happened:
//
// SCENARIO 1
@@ -618,9 +618,9 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
// Increment sequence if successfully broadcasted
eb.IncrementNextSequence(etx.FromAddress, sequence)
return err, true
- case clienttypes.Underpriced:
+ case client.Underpriced:
return eb.tryAgainBumpingGas(ctx, lgr, err, etx, attempt, initialBroadcastAt)
- case clienttypes.InsufficientFunds:
+ case client.InsufficientFunds:
// NOTE: This bails out of the entire cycle and essentially "blocks" on
// any transaction that gets insufficient_funds. This is OK if a
// transaction with a large VALUE blocks because this always comes last
@@ -630,13 +630,13 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
// theoretically be sent, but will instead be blocked.
eb.SvcErrBuffer.Append(err)
fallthrough
- case clienttypes.Retryable:
+ case client.Retryable:
return err, true
- case clienttypes.FeeOutOfValidRange:
+ case client.FeeOutOfValidRange:
return eb.tryAgainWithNewEstimation(ctx, lgr, err, etx, attempt, initialBroadcastAt)
- case clienttypes.Unsupported:
+ case client.Unsupported:
return err, false
- case clienttypes.ExceedsMaxFee:
+ case client.ExceedsMaxFee:
// Broadcaster: Note that we may have broadcast to multiple nodes and had it
// accepted by one of them! It is not guaranteed that all nodes share
// the same tx fee cap. That is why we must treat this as an unknown
@@ -649,7 +649,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
default:
// Every error that doesn't fall under one of the above categories will be treated as Unknown.
fallthrough
- case clienttypes.Unknown:
+ case client.Unknown:
eb.SvcErrBuffer.Append(err)
lgr.Criticalw(`Unknown error occurred while handling tx queue in ProcessUnstartedTxs. This chain/RPC client may not be supported. `+
`Urgent resolution required, Chainlink is currently operating in a degraded state and may miss transactions`, "err", err, "etx", etx, "attempt", attempt)
diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go
index c22a159457..1d92149094 100644
--- a/common/txmgr/confirmer.go
+++ b/common/txmgr/confirmer.go
@@ -15,7 +15,7 @@ import (
"go.uber.org/multierr"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/client"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
@@ -362,7 +362,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Che
for idx, txErr := range txErrs {
// Add to Unconfirm array, all tx where error wasn't TransactionAlreadyKnown.
if txErr != nil {
- if txCodes[idx] == clienttypes.TransactionAlreadyKnown {
+ if txCodes[idx] == client.TransactionAlreadyKnown {
continue
}
}
@@ -819,7 +819,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han
errType, sendError := ec.client.SendTransactionReturnCode(ctx, etx, attempt, lggr)
switch errType {
- case clienttypes.Underpriced:
+ case client.Underpriced:
// This should really not ever happen in normal operation since we
// already bumped above the required minimum in broadcaster.
ec.lggr.Warnw("Got terminally underpriced error for gas bump, this should never happen unless the remote RPC node changed its configuration on the fly, or you are using multiple RPC nodes with different minimum gas price requirements. This is not recommended", "err", sendError, "attempt", attempt)
@@ -854,12 +854,12 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han
return errors.Wrap(err, "saveReplacementInProgressAttempt failed")
}
return ec.handleInProgressAttempt(ctx, lggr, etx, replacementAttempt, blockHeight)
- case clienttypes.ExceedsMaxFee:
+ case client.ExceedsMaxFee:
// Confirmer: The gas price was bumped too high. This transaction attempt cannot be accepted.
// Best thing we can do is to re-send the previous attempt at the old
// price and discard this bumped version.
fallthrough
- case clienttypes.Fatal:
+ case client.Fatal:
// WARNING: This should never happen!
// Should NEVER be fatal this is an invariant violation. The
// Broadcaster can never create a TxAttempt that will
@@ -874,20 +874,20 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han
ec.SvcErrBuffer.Append(sendError)
// This will loop continuously on every new head so it must be handled manually by the node operator!
return ec.txStore.DeleteInProgressAttempt(ctx, attempt)
- case clienttypes.TransactionAlreadyKnown:
+ case client.TransactionAlreadyKnown:
// Sequence too low indicated that a transaction at this sequence was confirmed already.
// Mark confirmed_missing_receipt and wait for the next cycle to try to get a receipt
lggr.Debugw("Sequence already used", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String(), "err", sendError)
timeout := ec.dbConfig.DefaultQueryTimeout()
return ec.txStore.SaveConfirmedMissingReceiptAttempt(ctx, timeout, &attempt, now)
- case clienttypes.InsufficientFunds:
+ case client.InsufficientFunds:
timeout := ec.dbConfig.DefaultQueryTimeout()
return ec.txStore.SaveInsufficientFundsAttempt(ctx, timeout, &attempt, now)
- case clienttypes.Successful:
+ case client.Successful:
lggr.Debugw("Successfully broadcast transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String())
timeout := ec.dbConfig.DefaultQueryTimeout()
return ec.txStore.SaveSentAttempt(ctx, timeout, &attempt, now)
- case clienttypes.Unknown:
+ case client.Unknown:
// Every error that doesn't fall under one of the above categories will be treated as Unknown.
fallthrough
default:
@@ -1058,7 +1058,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) For
}
attempt.Tx = *etx // for logging
ec.lggr.Debugw("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", etx.FeeLimit, "attempt", attempt)
- if errCode, err := ec.client.SendTransactionReturnCode(context.TODO(), *etx, attempt, ec.lggr); errCode != clienttypes.Successful && err != nil {
+ if errCode, err := ec.client.SendTransactionReturnCode(context.TODO(), *etx, attempt, ec.lggr); errCode != client.Successful && err != nil {
ec.lggr.Errorw(fmt.Sprintf("ForceRebroadcast: failed to rebroadcast tx %v with sequence %v and gas limit %v: %s", etx.ID, *etx.Sequence, etx.FeeLimit, err.Error()), "err", err, "fee", attempt.TxFee)
continue
}
diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go
index 655de0f113..d788b82773 100644
--- a/common/txmgr/resender.go
+++ b/common/txmgr/resender.go
@@ -6,7 +6,7 @@ import (
"fmt"
"time"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
@@ -175,13 +175,13 @@ func (er *Resender[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) resendUnconfi
return nil
}
-func logResendResult(lggr logger.Logger, codes []clienttypes.SendTxReturnCode) {
+func logResendResult(lggr logger.Logger, codes []client.SendTxReturnCode) {
var nNew int
var nFatal int
for _, c := range codes {
- if c == clienttypes.Successful {
+ if c == client.Successful {
nNew++
- } else if c == clienttypes.Fatal {
+ } else if c == client.Fatal {
nFatal++
}
}
diff --git a/common/txmgr/types/client.go b/common/txmgr/types/client.go
index 6d7f1c5555..58c1b6f6ad 100644
--- a/common/txmgr/types/client.go
+++ b/common/txmgr/types/client.go
@@ -6,7 +6,7 @@ import (
"math/big"
"time"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -49,7 +49,7 @@ type TransactionClient[
bathSize int,
lggr logger.Logger,
) (
- txCodes []clienttypes.SendTxReturnCode,
+ txCodes []client.SendTxReturnCode,
txErrs []error,
broadcastTime time.Time,
successfulTxIDs []int64,
@@ -59,7 +59,7 @@ type TransactionClient[
tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE],
attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE],
lggr logger.Logger,
- ) (clienttypes.SendTxReturnCode, error)
+ ) (client.SendTxReturnCode, error)
SendEmptyTransaction(
ctx context.Context,
newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error),
diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go
index bda028cbf3..4c5108745c 100644
--- a/core/chains/evm/client/chain_client.go
+++ b/core/chains/evm/client/chain_client.go
@@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
- commontypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -213,7 +212,7 @@ func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction
return c.multiNode.SendTransaction(ctx, tx)
}
-func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commontypes.SendTxReturnCode, error) {
+func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) {
err := c.SendTransaction(ctx, tx)
return ClassifySendError(err, c.logger, tx, fromAddress, c.IsL2())
}
diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go
index af03720ced..fb8a39f379 100644
--- a/core/chains/evm/client/client.go
+++ b/core/chains/evm/client/client.go
@@ -6,7 +6,7 @@ import (
"strings"
"time"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -61,7 +61,7 @@ type Client interface {
HeadByHash(ctx context.Context, n common.Hash) (*evmtypes.Head, error)
SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error)
- SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (clienttypes.SendTxReturnCode, error)
+ SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error)
// Wrapped Geth client methods
// blockNumber can be specified as `nil` to imply latest block
@@ -211,7 +211,7 @@ func (client *client) HeaderByHash(ctx context.Context, h common.Hash) (*types.H
return client.pool.HeaderByHash(ctx, h)
}
-func (client *client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (clienttypes.SendTxReturnCode, error) {
+func (client *client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) {
err := client.SendTransaction(ctx, tx)
return ClassifySendError(err, client.logger, tx, fromAddress, client.pool.ChainType().IsL2())
}
diff --git a/core/chains/evm/client/client_test.go b/core/chains/evm/client/client_test.go
index 81a82d20fa..673fe044af 100644
--- a/core/chains/evm/client/client_test.go
+++ b/core/chains/evm/client/client_test.go
@@ -24,49 +24,48 @@ import (
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
- commontypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
-func mustNewClient(t *testing.T, wsURL string, sendonlys ...url.URL) evmclient.Client {
+func mustNewClient(t *testing.T, wsURL string, sendonlys ...url.URL) client.Client {
return mustNewClientWithChainID(t, wsURL, testutils.FixtureChainID, sendonlys...)
}
-func mustNewClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) evmclient.Client {
- cfg := evmclient.TestNodePoolConfig{
- NodeSelectionMode: evmclient.NodeSelectionMode_RoundRobin,
+func mustNewClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) client.Client {
+ cfg := client.TestNodePoolConfig{
+ NodeSelectionMode: client.NodeSelectionMode_RoundRobin,
}
- c, err := evmclient.NewClientWithTestNode(t, cfg, time.Second*0, wsURL, nil, sendonlys, 42, chainID)
+ c, err := client.NewClientWithTestNode(t, cfg, time.Second*0, wsURL, nil, sendonlys, 42, chainID)
require.NoError(t, err)
return c
}
-func mustNewChainClient(t *testing.T, wsURL string, sendonlys ...url.URL) evmclient.Client {
+func mustNewChainClient(t *testing.T, wsURL string, sendonlys ...url.URL) client.Client {
return mustNewChainClientWithChainID(t, wsURL, testutils.FixtureChainID, sendonlys...)
}
-func mustNewChainClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) evmclient.Client {
- cfg := evmclient.TestNodePoolConfig{
- NodeSelectionMode: evmclient.NodeSelectionMode_RoundRobin,
+func mustNewChainClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) client.Client {
+ cfg := client.TestNodePoolConfig{
+ NodeSelectionMode: client.NodeSelectionMode_RoundRobin,
}
- c, err := evmclient.NewChainClientWithTestNode(t, cfg, time.Second*0, cfg.NodeLeaseDuration, wsURL, nil, sendonlys, 42, chainID)
+ c, err := client.NewChainClientWithTestNode(t, cfg, time.Second*0, cfg.NodeLeaseDuration, wsURL, nil, sendonlys, 42, chainID)
require.NoError(t, err)
return c
}
-func mustNewClients(t *testing.T, wsURL string, sendonlys ...url.URL) []evmclient.Client {
- var clients []evmclient.Client
+func mustNewClients(t *testing.T, wsURL string, sendonlys ...url.URL) []client.Client {
+ var clients []client.Client
clients = append(clients, mustNewClient(t, wsURL, sendonlys...))
clients = append(clients, mustNewChainClient(t, wsURL, sendonlys...))
return clients
}
-func mustNewClientsWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) []evmclient.Client {
- var clients []evmclient.Client
+func mustNewClientsWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) []client.Client {
+ var clients []client.Client
clients = append(clients, mustNewClientWithChainID(t, wsURL, chainID, sendonlys...))
clients = append(clients, mustNewChainClientWithChainID(t, wsURL, chainID, sendonlys...))
return clients
@@ -287,7 +286,7 @@ func TestEthClient_GetERC20Balance(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
contractAddress := testutils.NewAddress()
userAddress := testutils.NewAddress()
- functionSelector := evmtypes.HexToFunctionSelector(evmclient.BALANCE_OF_ADDRESS_FUNCTION_SELECTOR) // balanceOf(address)
+ functionSelector := evmtypes.HexToFunctionSelector(client.BALANCE_OF_ADDRESS_FUNCTION_SELECTOR) // balanceOf(address)
txData := utils.ConcatBytes(functionSelector.Bytes(), common.LeftPadBytes(userAddress.Bytes(), utils.EVMWordByteLen))
wsURL := cltest.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) {
@@ -522,7 +521,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.Fatal)
+ assert.Equal(t, errType, commonclient.Fatal)
}
})
@@ -550,7 +549,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.TransactionAlreadyKnown)
+ assert.Equal(t, errType, commonclient.TransactionAlreadyKnown)
}
})
@@ -577,7 +576,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.NoError(t, err)
- assert.Equal(t, errType, commontypes.Successful)
+ assert.Equal(t, errType, commonclient.Successful)
}
})
@@ -605,7 +604,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.Underpriced)
+ assert.Equal(t, errType, commonclient.Underpriced)
}
})
@@ -633,7 +632,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.Unsupported)
+ assert.Equal(t, errType, commonclient.Unsupported)
}
})
@@ -661,7 +660,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.Retryable)
+ assert.Equal(t, errType, commonclient.Retryable)
}
})
@@ -689,7 +688,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.InsufficientFunds)
+ assert.Equal(t, errType, commonclient.InsufficientFunds)
}
})
@@ -717,7 +716,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.ExceedsMaxFee)
+ assert.Equal(t, errType, commonclient.ExceedsMaxFee)
}
})
@@ -745,7 +744,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) {
errType, err := ethClient.SendTransactionReturnCode(testutils.Context(t), tx, fromAddress)
assert.Error(t, err)
- assert.Equal(t, errType, commontypes.Unknown)
+ assert.Equal(t, errType, commonclient.Unknown)
}
})
}
@@ -811,7 +810,7 @@ func TestEthClient_ErroringClient(t *testing.T) {
ctx := testutils.Context(t)
// Empty node means there are no active nodes to select from, causing client to always return error.
- erroringClient := evmclient.NewChainClientWithEmptyNode(t, commonclient.NodeSelectionModeRoundRobin, time.Second*0, time.Second*0, testutils.FixtureChainID)
+ erroringClient := client.NewChainClientWithEmptyNode(t, commonclient.NodeSelectionModeRoundRobin, time.Second*0, time.Second*0, testutils.FixtureChainID)
_, err := erroringClient.BalanceAt(ctx, common.Address{}, nil)
require.Equal(t, err, commonclient.ErroringNodeError)
@@ -883,7 +882,7 @@ func TestEthClient_ErroringClient(t *testing.T) {
require.Equal(t, err, commonclient.ErroringNodeError)
code, err := erroringClient.SendTransactionReturnCode(ctx, nil, common.Address{})
- require.Equal(t, code, commontypes.Unknown)
+ require.Equal(t, code, commonclient.Unknown)
require.Equal(t, err, commonclient.ErroringNodeError)
_, err = erroringClient.SequenceAt(ctx, common.Address{}, nil)
@@ -912,4 +911,4 @@ func TestEthClient_ErroringClient(t *testing.T) {
}
-const headResult = evmclient.HeadResult
+const headResult = client.HeadResult
diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go
index 7197d77b3d..0d177455e3 100644
--- a/core/chains/evm/client/errors.go
+++ b/core/chains/evm/client/errors.go
@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
@@ -397,20 +397,20 @@ func ExtractRPCError(baseErr error) (*JsonError, error) {
return &jErr, nil
}
-func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (clienttypes.SendTxReturnCode, error) {
+func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (commonclient.SendTxReturnCode, error) {
sendError := NewSendError(err)
if sendError == nil {
- return clienttypes.Successful, err
+ return commonclient.Successful, err
}
if sendError.Fatal() {
lggr.Criticalw("Fatal error sending transaction", "err", sendError, "etx", tx)
// Attempt is thrown away in this case; we don't need it since it never got accepted by a node
- return clienttypes.Fatal, err
+ return commonclient.Fatal, err
}
if sendError.IsNonceTooLowError() || sendError.IsTransactionAlreadyMined() {
// Nonce too low indicated that a transaction at this nonce was confirmed already.
// Mark it as TransactionAlreadyKnown.
- return clienttypes.TransactionAlreadyKnown, err
+ return commonclient.TransactionAlreadyKnown, err
}
if sendError.IsReplacementUnderpriced() {
lggr.Errorw(fmt.Sprintf("Replacement transaction underpriced for eth_tx %x. "+
@@ -419,41 +419,41 @@ func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fro
tx.Hash(), err), "gasPrice", tx.GasPrice, "gasTipCap", tx.GasTipCap, "gasFeeCap", tx.GasFeeCap)
// Assume success and hand off to the next cycle.
- return clienttypes.Successful, err
+ return commonclient.Successful, err
}
if sendError.IsTransactionAlreadyInMempool() {
lggr.Debugw("Transaction already in mempool", "txHash", tx.Hash, "nodeErr", sendError.Error())
- return clienttypes.Successful, err
+ return commonclient.Successful, err
}
if sendError.IsTemporarilyUnderpriced() {
lggr.Infow("Transaction temporarily underpriced", "err", sendError.Error())
- return clienttypes.Successful, err
+ return commonclient.Successful, err
}
if sendError.IsTerminallyUnderpriced() {
- return clienttypes.Underpriced, err
+ return commonclient.Underpriced, err
}
if sendError.L2FeeTooLow() || sendError.IsL2FeeTooHigh() || sendError.IsL2Full() {
if isL2 {
- return clienttypes.FeeOutOfValidRange, err
+ return commonclient.FeeOutOfValidRange, err
}
- return clienttypes.Unsupported, errors.Wrap(sendError, "this error type only handled for L2s")
+ return commonclient.Unsupported, errors.Wrap(sendError, "this error type only handled for L2s")
}
if sendError.IsNonceTooHighError() {
// This error occurs when the tx nonce is greater than current_nonce + tx_count_in_mempool,
// instead of keeping the tx in mempool. This can happen if previous transactions haven't
// reached the client yet. The correct thing to do is to mark it as retryable.
lggr.Warnw("Transaction has a nonce gap.", "err", err)
- return clienttypes.Retryable, err
+ return commonclient.Retryable, err
}
if sendError.IsInsufficientEth() {
lggr.Criticalw(fmt.Sprintf("Tx %x with type 0x%d was rejected due to insufficient eth: %s\n"+
"ACTION REQUIRED: Chainlink wallet with address 0x%x is OUT OF FUNDS",
tx.Hash(), tx.Type(), sendError.Error(), fromAddress,
), "err", sendError)
- return clienttypes.InsufficientFunds, err
+ return commonclient.InsufficientFunds, err
}
if sendError.IsTimeout() {
- return clienttypes.Retryable, errors.Wrapf(sendError, "timeout while sending transaction %s", tx.Hash().Hex())
+ return commonclient.Retryable, errors.Wrapf(sendError, "timeout while sending transaction %s", tx.Hash().Hex())
}
if sendError.IsTxFeeExceedsCap() {
lggr.Criticalw(fmt.Sprintf("Sending transaction failed: %s", label.RPCTxFeeCapConfiguredIncorrectlyWarning),
@@ -461,19 +461,19 @@ func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fro
"err", sendError,
"id", "RPCTxFeeCapExceeded",
)
- return clienttypes.ExceedsMaxFee, err
+ return commonclient.ExceedsMaxFee, err
}
- return clienttypes.Unknown, err
+ return commonclient.Unknown, err
}
// ClassifySendOnlyError handles SendOnly nodes error codes. In that case, we don't assume there is another transaction that will be correctly
// priced.
-func ClassifySendOnlyError(err error) clienttypes.SendTxReturnCode {
+func ClassifySendOnlyError(err error) commonclient.SendTxReturnCode {
sendError := NewSendError(err)
if sendError == nil || sendError.IsNonceTooLowError() || sendError.IsTransactionAlreadyMined() || sendError.IsTransactionAlreadyInMempool() {
// Nonce too low or transaction known errors are expected since
// the primary SendTransaction may well have succeeded already
- return clienttypes.Successful
+ return commonclient.Successful
}
- return clienttypes.Fatal
+ return commonclient.Fatal
}
diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go
index 8552b2c0a0..2820ba992c 100644
--- a/core/chains/evm/client/helpers_test.go
+++ b/core/chains/evm/client/helpers_test.go
@@ -9,7 +9,6 @@ import (
"github.com/pkg/errors"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -89,7 +88,7 @@ func NewChainClientWithTestNode(
}
lggr := logger.TestLogger(t)
- rpc := NewRPCClient(lggr, *parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, clienttypes.Primary)
+ rpc := NewRPCClient(lggr, *parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, commonclient.Primary)
n := commonclient.NewNode[*big.Int, *evmtypes.Head, RPCCLient](
nodeCfg, noNewHeadsThreshold, lggr, *parsed, rpcHTTPURL, "eth-primary-node-0", id, chainID, 1, rpc, "EVM")
@@ -101,7 +100,7 @@ func NewChainClientWithTestNode(
return nil, errors.Errorf("sendonly ethereum rpc url scheme must be http(s): %s", u.String())
}
var empty url.URL
- rpc := NewRPCClient(lggr, empty, &sendonlyRPCURLs[i], fmt.Sprintf("eth-sendonly-rpc-%d", i), id, chainID, clienttypes.Secondary)
+ rpc := NewRPCClient(lggr, empty, &sendonlyRPCURLs[i], fmt.Sprintf("eth-sendonly-rpc-%d", i), id, chainID, commonclient.Secondary)
s := commonclient.NewSendOnlyNode[*big.Int, RPCCLient](
lggr, u, fmt.Sprintf("eth-sendonly-%d", i), chainID, rpc)
sendonlys = append(sendonlys, s)
diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go
index fdcb15d6a6..7617a7c05f 100644
--- a/core/chains/evm/client/mocks/client.go
+++ b/core/chains/evm/client/mocks/client.go
@@ -7,10 +7,10 @@ import (
assets "github.com/smartcontractkit/chainlink/v2/core/assets"
- chainsclient "github.com/smartcontractkit/chainlink/v2/common/chains/client"
-
common "github.com/ethereum/go-ethereum/common"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+
context "context"
ethereum "github.com/ethereum/go-ethereum"
@@ -566,18 +566,18 @@ func (_m *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er
}
// SendTransactionReturnCode provides a mock function with given fields: ctx, tx, fromAddress
-func (_m *Client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (chainsclient.SendTxReturnCode, error) {
+func (_m *Client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) {
ret := _m.Called(ctx, tx, fromAddress)
- var r0 chainsclient.SendTxReturnCode
+ var r0 commonclient.SendTxReturnCode
var r1 error
- if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) (chainsclient.SendTxReturnCode, error)); ok {
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) (commonclient.SendTxReturnCode, error)); ok {
return rf(ctx, tx, fromAddress)
}
- if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) chainsclient.SendTxReturnCode); ok {
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) commonclient.SendTxReturnCode); ok {
r0 = rf(ctx, tx, fromAddress)
} else {
- r0 = ret.Get(0).(chainsclient.SendTxReturnCode)
+ r0 = ret.Get(0).(commonclient.SendTxReturnCode)
}
if rf, ok := ret.Get(1).(func(context.Context, *types.Transaction, common.Address) error); ok {
diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go
index 8e271aea1e..286f62b3b8 100644
--- a/core/chains/evm/client/null_client.go
+++ b/core/chains/evm/client/null_client.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -121,9 +121,9 @@ func (nc *NullClient) HeaderByHash(ctx context.Context, h common.Hash) (*types.H
return nil, nil
}
-func (nc *NullClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, sender common.Address) (clienttypes.SendTxReturnCode, error) {
+func (nc *NullClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, sender common.Address) (commonclient.SendTxReturnCode, error) {
nc.lggr.Debug("SendTransactionReturnCode")
- return clienttypes.Successful, nil
+ return commonclient.Successful, nil
}
func (nc *NullClient) SendTransaction(ctx context.Context, tx *types.Transaction) error {
diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go
index b6ed84eee4..04b9fad1fc 100644
--- a/core/chains/evm/client/rpc_client.go
+++ b/core/chains/evm/client/rpc_client.go
@@ -17,7 +17,6 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
@@ -57,7 +56,7 @@ type rpcClient struct {
name string
id int32
chainID *big.Int
- tier clienttypes.NodeTier
+ tier commonclient.NodeTier
ws rawclient
http *rawclient
@@ -85,7 +84,7 @@ func NewRPCClient(
name string,
id int32,
chainID *big.Int,
- tier clienttypes.NodeTier,
+ tier commonclient.NodeTier,
) RPCCLient {
r := new(rpcClient)
r.name = name
diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go
index cde536bc7b..7823908967 100644
--- a/core/chains/evm/client/simulated_backend_client.go
+++ b/core/chains/evm/client/simulated_backend_client.go
@@ -18,7 +18,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -417,16 +417,16 @@ func (c *SimulatedBackendClient) HeaderByHash(ctx context.Context, h common.Hash
return c.b.HeaderByHash(ctx, h)
}
-func (c *SimulatedBackendClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (clienttypes.SendTxReturnCode, error) {
+func (c *SimulatedBackendClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) {
err := c.SendTransaction(ctx, tx)
if err == nil {
- return clienttypes.Successful, nil
+ return commonclient.Successful, nil
}
if strings.Contains(err.Error(), "could not fetch parent") || strings.Contains(err.Error(), "invalid transaction") {
- return clienttypes.Fatal, err
+ return commonclient.Fatal, err
}
// All remaining error messages returned from SendTransaction are considered Unknown.
- return clienttypes.Unknown, err
+ return commonclient.Unknown, err
}
// SendTransaction sends a transaction.
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 61a230c21b..ca2697ca99 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -22,11 +22,11 @@ import (
"go.uber.org/zap/zapcore"
"gopkg.in/guregu/null.v4"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
@@ -51,7 +51,7 @@ import (
func NewTestEthBroadcaster(
t testing.TB,
txStore txmgr.TestEvmTxStore,
- ethClient evmclient.Client,
+ ethClient client.Client,
keyStore keystore.Eth,
config evmconfig.ChainScopedConfig,
checkerFactory txmgr.TransmitCheckerFactory,
@@ -217,7 +217,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
}
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(2) && tx.Value().Cmp(big.NewInt(242)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Earlier
tr := int32(99)
@@ -245,7 +245,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
require.Equal(t, value.String(), tx.Value().String())
require.Equal(t, earlierEthTx.EncodedPayload, tx.Data())
return true
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Later
laterEthTx := txmgr.Tx{
@@ -268,7 +268,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
require.Equal(t, value.String(), tx.Value().String())
require.Equal(t, laterEthTx.EncodedPayload, tx.Data())
return true
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Insertion order deliberately reversed to test ordering
require.NoError(t, txStore.InsertTx(&expensiveEthTx))
@@ -349,7 +349,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
t.Run("sends transactions with type 0x2 in EIP-1559 mode", func(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(343) && tx.Value().Cmp(big.NewInt(242)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, []byte{42, 42, 0}, gasLimit, big.Int(assets.NewEthValue(242)), &cltest.FixtureChainID)
// Do the thing
@@ -400,7 +400,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
}
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(344) && tx.Value().Cmp(big.NewInt(442)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
ethClient.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", mock.MatchedBy(func(callarg map[string]interface{}) bool {
if fmt.Sprintf("%s", callarg["value"]) == "0x1ba" { // 442
assert.Equal(t, txRequest.FromAddress, callarg["from"])
@@ -433,7 +433,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
t.Run("with unknown error, sends tx as normal", func(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(345) && tx.Value().Cmp(big.NewInt(542)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
ethClient.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", mock.MatchedBy(func(callarg map[string]interface{}) bool {
return fmt.Sprintf("%s", callarg["value"]) == "0x21e" // 542
}), "latest").Return(errors.New("this is not a revert, something unexpected went wrong")).Once()
@@ -454,7 +454,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
})
t.Run("on revert, marks tx as fatally errored and does not send", func(t *testing.T) {
- jerr := evmclient.JsonError{
+ jerr := client.JsonError{
Code: 42,
Message: "oh no, it reverted",
Data: []byte{42, 166, 34},
@@ -503,7 +503,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == 0 && tx.Value().Cmp(big.NewInt(442)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
ethTx := cltest.MustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID,
cltest.EvmTxRequestWithValue(big.Int(assets.NewEthValue(442))),
@@ -526,7 +526,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == 1 && tx.Value().Cmp(big.NewInt(442)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
ethTx := cltest.MustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID,
cltest.EvmTxRequestWithValue(big.Int(assets.NewEthValue(442))),
@@ -646,7 +646,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
assert.Equal(t, int(1600), int(tx.Gas()))
return true
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
txRequest := txmgr.TxRequest{
FromAddress: fromAddress,
@@ -730,7 +730,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(firstNonce)
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
{
@@ -766,7 +766,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(firstNonce)
- }), fromAddress).Return(clienttypes.Fatal, errors.New("exceeds block gas limit")).Once()
+ }), fromAddress).Return(commonclient.Fatal, errors.New("exceeds block gas limit")).Once()
// Do the thing
{
@@ -802,7 +802,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(firstNonce)
- }), fromAddress).Return(clienttypes.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once()
// Do the thing
{
@@ -837,7 +837,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(firstNonce)
- }), fromAddress).Return(clienttypes.TransactionAlreadyKnown, errors.New("nonce too low")).Once()
+ }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once()
// Do the thing
{
@@ -874,7 +874,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(firstNonce)
- }), fromAddress).Return(clienttypes.Retryable, failedToReachNodeError).Once()
+ }), fromAddress).Return(commonclient.Retryable, failedToReachNodeError).Once()
// Do the thing
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -920,7 +920,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
s, e := txmgr.GetGethSignedTx(attempt.SignedRawTx)
require.NoError(t, e)
return tx.Nonce() == uint64(firstNonce) && tx.GasPrice().Int64() == s.GasPrice().Int64()
- }), fromAddress).Return(clienttypes.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once()
// Do the thing
{
@@ -980,7 +980,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// First send, replacement underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(0)
- }), fromAddress).Return(clienttypes.Successful, errors.New("replacement transaction underpriced")).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once()
// Do the thing
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1017,7 +1017,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Fatal, errors.New(fatalErrorExample)).Once()
+ }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once()
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
assert.NoError(t, err)
@@ -1067,7 +1067,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Fatal, errors.New(fatalErrorExample)).Once()
+ }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once()
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
require.Error(t, err)
@@ -1088,7 +1088,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Fatal, errors.New(fatalErrorExample)).Once()
+ }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once()
{
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1120,7 +1120,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.ExceedsMaxFee, errors.New(TxFeeExceedsCapError)).Twice()
+ }), fromAddress).Return(commonclient.ExceedsMaxFee, errors.New(TxFeeExceedsCapError)).Twice()
// In the first case, the tx was NOT accepted into the mempool. In the case
// of multiple RPC nodes, it is possible that it can be accepted by
// another node even if the primary one returns "exceeds the configured
@@ -1178,7 +1178,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(localNextNonce)
- }), fromAddress).Return(clienttypes.Unknown, errors.New(retryableErrorExample)).Once()
+ }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once()
// Nonce is the same as localNextNonce, implying that this sent transaction has not been accepted
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce), nil).Once()
@@ -1204,7 +1204,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// Now on the second run, it is successful
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
retryable, err = eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
assert.NoError(t, err)
@@ -1230,7 +1230,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == uint64(localNextNonce)
- }), fromAddress).Return(clienttypes.Unknown, errors.New(retryableErrorExample)).Once()
+ }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), errors.New("pending nonce fetch failed")).Once()
// Do the thing
@@ -1256,7 +1256,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// Now on the second run, it is successful
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
retryable, err = eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
assert.NoError(t, err)
@@ -1282,7 +1282,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Unknown, errors.New(retryableErrorExample)).Once()
+ }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once()
// Nonce is one higher than localNextNonce, implying that despite the error, this sent transaction has been accepted into the mempool
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce+1), nil).Once()
@@ -1316,17 +1316,17 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// First was underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg.EVM().GasEstimator().PriceDefault().ToInt()) == 0
- }), fromAddress).Return(clienttypes.Underpriced, errors.New(underpricedError)).Once()
+ }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Second with gas bump was still underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(big.NewInt(25000000000)) == 0
- }), fromAddress).Return(clienttypes.Underpriced, errors.New(underpricedError)).Once()
+ }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Third succeeded
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(big.NewInt(30000000000)) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1362,7 +1362,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Retryable, failedToReachNodeError).Once()
+ }), fromAddress).Return(commonclient.Retryable, failedToReachNodeError).Once()
// Do the thing
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1393,7 +1393,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Successful, errors.New(temporarilyUnderpricedError)).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New(temporarilyUnderpricedError)).Once()
// Do the thing
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1433,7 +1433,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// First was underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg2.EVM().GasEstimator().PriceDefault().ToInt()) == 0
- }), fromAddress).Return(clienttypes.Underpriced, errors.New(underpricedError)).Once()
+ }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Do the thing
retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1451,7 +1451,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.InsufficientFunds, errors.New(insufficientEthError)).Once()
+ }), fromAddress).Return(commonclient.InsufficientFunds, errors.New(insufficientEthError)).Once()
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
require.Error(t, err)
@@ -1481,7 +1481,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
etx := cltest.MustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce
- }), fromAddress).Return(clienttypes.Retryable, errors.New(nonceGapError)).Once()
+ }), fromAddress).Return(commonclient.Retryable, errors.New(nonceGapError)).Once()
retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
require.Error(t, err)
@@ -1525,7 +1525,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
localNextNonce = getLocalNextNonce(t, eb, fromAddress)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(1)) == 0
- }), fromAddress).Return(clienttypes.Underpriced, errors.New(underpricedError)).Once()
+ }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Check gas tip cap verification
retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
@@ -1569,15 +1569,15 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// Second was underpriced but above minimum
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(gasTipCapDefault.ToInt()) == 0
- }), fromAddress).Return(clienttypes.Underpriced, errors.New(underpricedError)).Once()
+ }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Resend at the bumped price
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), evmcfg2.EVM().GasEstimator().BumpMin().ToInt())) == 0
- }), fromAddress).Return(clienttypes.Underpriced, errors.New(underpricedError)).Once()
+ }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Final bump succeeds
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), big.NewInt(0).Mul(evmcfg2.EVM().GasEstimator().BumpMin().ToInt(), big.NewInt(2)))) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
retryable, err = eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
require.NoError(t, err)
diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go
index e1b1257774..8789f5f173 100644
--- a/core/chains/evm/txmgr/client.go
+++ b/core/chains/evm/txmgr/client.go
@@ -13,8 +13,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -24,10 +24,10 @@ import (
var _ TxmClient = (*evmTxmClient)(nil)
type evmTxmClient struct {
- client evmclient.Client
+ client client.Client
}
-func NewEvmTxmClient(c evmclient.Client) *evmTxmClient {
+func NewEvmTxmClient(c client.Client) *evmTxmClient {
return &evmTxmClient{client: c}
}
@@ -45,14 +45,14 @@ func (c *evmTxmClient) BatchSendTransactions(
batchSize int,
lggr logger.Logger,
) (
- codes []clienttypes.SendTxReturnCode,
+ codes []commonclient.SendTxReturnCode,
txErrs []error,
broadcastTime time.Time,
successfulTxIDs []int64,
err error,
) {
// preallocate
- codes = make([]clienttypes.SendTxReturnCode, len(attempts))
+ codes = make([]commonclient.SendTxReturnCode, len(attempts))
txErrs = make([]error, len(attempts))
reqs, broadcastTime, successfulTxIDs, batchErr := batchSendTransactions(ctx, attempts, batchSize, lggr, c.client)
@@ -80,7 +80,7 @@ func (c *evmTxmClient) BatchSendTransactions(
processingErr[i] = fmt.Errorf("failed to process tx (index %d): %w", i, signedErr)
return
}
- codes[i], txErrs[i] = evmclient.ClassifySendError(reqs[i].Error, lggr, tx, attempts[i].Tx.FromAddress, c.client.IsL2())
+ codes[i], txErrs[i] = client.ClassifySendError(reqs[i].Error, lggr, tx, attempts[i].Tx.FromAddress, c.client.IsL2())
}(index)
}
wg.Wait()
@@ -88,11 +88,11 @@ func (c *evmTxmClient) BatchSendTransactions(
return
}
-func (c *evmTxmClient) SendTransactionReturnCode(ctx context.Context, etx Tx, attempt TxAttempt, lggr logger.Logger) (clienttypes.SendTxReturnCode, error) {
+func (c *evmTxmClient) SendTransactionReturnCode(ctx context.Context, etx Tx, attempt TxAttempt, lggr logger.Logger) (commonclient.SendTxReturnCode, error) {
signedTx, err := GetGethSignedTx(attempt.SignedRawTx)
if err != nil {
lggr.Criticalw("Fatal error signing transaction", "err", err, "etx", etx)
- return clienttypes.Fatal, err
+ return commonclient.Fatal, err
}
return c.client.SendTransactionReturnCode(ctx, signedTx, etx.FromAddress)
}
@@ -174,5 +174,5 @@ func (c *evmTxmClient) CallContract(ctx context.Context, a TxAttempt, blockNumbe
Data: a.Tx.EncodedPayload,
AccessList: nil,
}, blockNumber)
- return evmclient.ExtractRPCError(errCall)
+ return client.ExtractRPCError(errCall)
}
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index 8fbdb7696d..1385250a20 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -20,12 +20,12 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
@@ -564,7 +564,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) {
data, err := utils.ABIEncode(`[{"type":"uint256"}]`, big.NewInt(10))
require.NoError(t, err)
sig := utils.Keccak256Fixed([]byte(`MyError(uint256)`))
- ethClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(nil, &evmclient.JsonError{
+ ethClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(nil, &client.JsonError{
Code: 1,
Message: "reverted",
Data: utils.ConcatBytes(sig[:4], data),
@@ -1658,7 +1658,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1.ID))
// Send transaction and assume success.
- ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(clienttypes.Successful, nil).Once()
+ ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once()
err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)
require.NoError(t, err)
@@ -1703,7 +1703,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1.ID))
// Send transaction and assume success.
- ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(clienttypes.Successful, nil).Once()
+ ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once()
err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)
require.NoError(t, err)
@@ -1787,7 +1787,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence)
- }), fromAddress).Return(clienttypes.Fatal, errors.New("exceeds block gas limit")).Once()
+ }), fromAddress).Return(commonclient.Fatal, errors.New("exceeds block gas limit")).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -1819,7 +1819,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
// Once for the bumped attempt which exceeds limit
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) && tx.GasPrice().Int64() == int64(20000000000)
- }), fromAddress).Return(clienttypes.ExceedsMaxFee, errors.New("tx fee (1.10 ether) exceeds the configured cap (1.00 ether)")).Once()
+ }), fromAddress).Return(commonclient.ExceedsMaxFee, errors.New("tx fee (1.10 ether) exceeds the configured cap (1.00 ether)")).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -1858,7 +1858,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -1904,7 +1904,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, fmt.Errorf("known transaction: %s", ethTx.Hash().Hex())).Once()
+ }), fromAddress).Return(commonclient.Successful, fmt.Errorf("known transaction: %s", ethTx.Hash().Hex())).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -1944,7 +1944,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.TransactionAlreadyKnown, errors.New("nonce too low")).Once()
+ }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -1996,7 +1996,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Unknown, errors.New("some network error")).Once()
+ }), fromAddress).Return(commonclient.Unknown, errors.New("some network error")).Once()
// Do the thing
err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)
@@ -2024,7 +2024,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
n = *etx2.Sequence
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2063,7 +2063,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.TransactionAlreadyKnown, errors.New("nonce too low")).Once()
+ }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once()
// Creates new attempt as normal if currentHead is not high enough
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2104,7 +2104,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, errors.New("replacement transaction underpriced")).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2141,7 +2141,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, fmt.Errorf("known transaction: %s", ethTx.Hash().Hex())).Once()
+ }), fromAddress).Return(commonclient.Successful, fmt.Errorf("known transaction: %s", ethTx.Hash().Hex())).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2180,7 +2180,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, errors.New(temporarilyUnderpricedError)).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New(temporarilyUnderpricedError)).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2209,7 +2209,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && gasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, errors.New("already known")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx
+ }), fromAddress).Return(commonclient.Successful, errors.New("already known")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx
// Do the thing
require.NoError(t, ec2.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2239,7 +2239,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && gasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, errors.New("already known")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx
+ }), fromAddress).Return(commonclient.Successful, errors.New("already known")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx
// Do the thing
require.NoError(t, ec2.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2278,7 +2278,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
gasTipCap := assets.GWei(42)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && gasTipCap.ToInt().Cmp(tx.GasTipCap()) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
var err error
etx4, err = txStore.FindTxWithAttempts(etx4.ID)
@@ -2308,7 +2308,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
// Third attempt failed to bump, resubmits old one instead
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && attempt4_2.Hash.String() == tx.Hash().String()
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec2.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
var err error
@@ -2344,7 +2344,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
mock.Anything).Return(ðTx, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && expectedBumpedTipCap.ToInt().Cmp(tx.GasTipCap()) == 0
- }), fromAddress).Return(clienttypes.Successful, errors.New("replacement transaction underpriced")).Once()
+ }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once()
// Do it
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2401,10 +2401,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
// Fail the first time with terminally underpriced.
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Once()
+ commonclient.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Once()
// Succeed the second time after bumping gas.
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Successful, nil).Once()
+ commonclient.Successful, nil).Once()
kst.On("SignTx", mock.Anything, mock.Anything, mock.Anything).Return(
signedTx, nil,
).Once()
@@ -2424,10 +2424,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
// Fail a few times with terminally underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Times(3)
+ commonclient.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Times(3)
// Succeed the second time after bumping gas.
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Successful, nil).Once()
+ commonclient.Successful, nil).Once()
signedLegacyTx := new(types.Transaction)
kst.On("SignTx", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Type() == 0x0 && tx.Nonce() == uint64(*etx.Sequence)
@@ -2456,10 +2456,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
// Fail a few times with terminally underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Underpriced, errors.New("transaction underpriced")).Times(3)
+ commonclient.Underpriced, errors.New("transaction underpriced")).Times(3)
// Succeed the second time after bumping gas.
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Successful, nil).Once()
+ commonclient.Successful, nil).Once()
signedDxFeeTx := new(types.Transaction)
kst.On("SignTx", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Type() == 0x2 && tx.Nonce() == uint64(*etx.Sequence)
@@ -2517,7 +2517,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.InsufficientFunds, insufficientEthError).Once()
+ }), fromAddress).Return(commonclient.InsufficientFunds, insufficientEthError).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2543,7 +2543,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.InsufficientFunds, insufficientEthError).Once()
+ }), fromAddress).Return(commonclient.InsufficientFunds, insufficientEthError).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2568,7 +2568,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead))
@@ -2600,7 +2600,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
cltest.MustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, nonce, fromAddress)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(n)
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
nonce++
}
@@ -2695,7 +2695,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) {
require.NoError(t, err)
// Keeps gas price and nonce the same
return atx.GasPrice().Cmp(tx.GasPrice()) == 0 && atx.Nonce() == tx.Nonce()
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head))
@@ -2718,7 +2718,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) {
cltest.MustInsertEthReceipt(t, txStore, head.Parent.Number, utils.NewHash(), attemptHash)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(
- clienttypes.Successful, nil).Once()
+ commonclient.Successful, nil).Once()
// Do the thing
require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head))
@@ -2753,7 +2753,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) {
s, err := txmgr.GetGethSignedTx(attempt3.SignedRawTx)
require.NoError(t, err)
return tx.Hash() == s.Hash()
- }), fromAddress).Return(clienttypes.Successful, nil).Once()
+ }), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head))
@@ -2817,7 +2817,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
tx.Gas() == uint64(overrideGasLimit) &&
reflect.DeepEqual(tx.Data(), etx1.EncodedPayload) &&
tx.To().String() == etx1.ToAddress.String()
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{1}, gasPriceWei, fromAddress, overrideGasLimit))
})
@@ -2832,7 +2832,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
tx.Gas() == uint64(etx1.FeeLimit) &&
reflect.DeepEqual(tx.Data(), etx1.EncodedPayload) &&
tx.To().String() == etx1.ToAddress.String()
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{(1)}, gasPriceWei, fromAddress, 0))
})
@@ -2843,10 +2843,10 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx1.Sequence) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == uint64(overrideGasLimit)
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx2.Sequence) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == uint64(overrideGasLimit)
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{(1), (2)}, gasPriceWei, fromAddress, overrideGasLimit))
})
@@ -2857,10 +2857,10 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(1)
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(2)
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
for i := 3; i <= 5; i++ {
nonce := i
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
@@ -2870,7 +2870,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
*tx.To() == fromAddress &&
tx.Value().Cmp(big.NewInt(0)) == 0 &&
len(tx.Data()) == 0
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
}
nonces := []evmtypes.Nonce{(1), (2), (3), (4), (5)}
@@ -2883,7 +2883,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && uint32(tx.Gas()) == config.EVM().GasEstimator().LimitDefault()
- }), mock.Anything).Return(clienttypes.Successful, nil).Once()
+ }), mock.Anything).Return(commonclient.Successful, nil).Once()
require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0))
})
diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go
index df60e16423..a73e98a935 100644
--- a/core/cmd/shell_local_test.go
+++ b/core/cmd/shell_local_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"time"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
cmdMocks "github.com/smartcontractkit/chainlink/v2/core/cmd/mocks"
@@ -307,7 +307,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) {
app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe()
ethClient.On("Dial", mock.Anything).Return(nil)
- client := cmd.Shell{
+ c := cmd.Shell{
Config: config,
AppFactory: cltest.InstanceAppFactory{App: app},
FallbackAPIInitializer: cltest.NewMockAPIInitializer(t),
@@ -318,7 +318,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) {
beginningNonce := uint64(7)
endingNonce := uint64(10)
set := flag.NewFlagSet("test", 0)
- cltest.FlagSetApplyFromAction(client.RebroadcastTransactions, set, "")
+ cltest.FlagSetApplyFromAction(c.RebroadcastTransactions, set, "")
require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String()))
require.NoError(t, set.Set("beginningNonce", strconv.FormatUint(beginningNonce, 10)))
@@ -328,16 +328,16 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) {
require.NoError(t, set.Set("address", fromAddress.Hex()))
require.NoError(t, set.Set("password", "../internal/fixtures/correct_password.txt"))
- c := cli.NewContext(nil, set, nil)
+ ctx := cli.NewContext(nil, set, nil)
for i := beginningNonce; i <= endingNonce; i++ {
n := i
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == n
- }), mock.Anything).Once().Return(clienttypes.Successful, nil)
+ }), mock.Anything).Once().Return(client.Successful, nil)
}
- assert.NoError(t, client.RebroadcastTransactions(c))
+ assert.NoError(t, c.RebroadcastTransactions(ctx))
}
func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
@@ -388,7 +388,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy}
app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe()
- client := cmd.Shell{
+ c := cmd.Shell{
Config: config,
AppFactory: cltest.InstanceAppFactory{App: app},
FallbackAPIInitializer: cltest.NewMockAPIInitializer(t),
@@ -397,7 +397,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
}
set := flag.NewFlagSet("test", 0)
- cltest.FlagSetApplyFromAction(client.RebroadcastTransactions, set, "")
+ cltest.FlagSetApplyFromAction(c.RebroadcastTransactions, set, "")
require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String()))
require.NoError(t, set.Set("beginningNonce", strconv.FormatUint(uint64(beginningNonce), 10)))
@@ -407,16 +407,16 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
require.NoError(t, set.Set("address", fromAddress.Hex()))
require.NoError(t, set.Set("password", "../internal/fixtures/correct_password.txt"))
- c := cli.NewContext(nil, set, nil)
+ ctx := cli.NewContext(nil, set, nil)
for i := beginningNonce; i <= endingNonce; i++ {
n := i
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return uint(tx.Nonce()) == n
- }), mock.Anything).Once().Return(clienttypes.Successful, nil)
+ }), mock.Anything).Once().Return(client.Successful, nil)
}
- assert.NoError(t, client.RebroadcastTransactions(c))
+ assert.NoError(t, c.RebroadcastTransactions(ctx))
cltest.AssertEthTxAttemptCountStays(t, app.GetSqlxDB(), 1)
})
@@ -466,7 +466,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) {
mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy}
app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe()
- ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(clienttypes.Successful, nil)
+ ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(client.Successful, nil)
client := cmd.Shell{
Config: config,
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 66162aef10..e5c2ca031a 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -44,7 +44,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
- clienttypes "github.com/smartcontractkit/chainlink/v2/common/chains/client"
+ "github.com/smartcontractkit/chainlink/v2/common/client"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
"github.com/smartcontractkit/chainlink/v2/core/assets"
@@ -518,7 +518,7 @@ func NewEthMocksWithTransactionsOnBlocksAssertions(t testing.TB) *evmclimocks.Cl
c.On("Dial", mock.Anything).Maybe().Return(nil)
c.On("SubscribeNewHead", mock.Anything, mock.Anything).Maybe().Return(EmptyMockSubscription(t), nil)
c.On("SendTransaction", mock.Anything, mock.Anything).Maybe().Return(nil)
- c.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(clienttypes.Successful, nil)
+ c.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(client.Successful, nil)
// Construct chain
h2 := Head(2)
h1 := HeadWithHash(1, h2.ParentHash)
From 84bbe2af6ac8889e40f0210414375c956df65275 Mon Sep 17 00:00:00 2001
From: FelixFan1992
Date: Mon, 6 Nov 2023 14:42:47 -0500
Subject: [PATCH 080/327] populate retry interval for mercury requests [DO NOT
MERGE] (#11150)
* populate retry interval for mercury requests
* fix go mod
* populate retry interval based on the work ID counter
* add tests
* use const value
* include check block number in plugin retry key
* address comments
* refactor
* test for plugin retry counter
* Bump ocr2keepers to 0.7.28 (#11181)
* handles 206 response code
* reduce mercury permission cache period
* address comments
* remove special logging for 206
---------
Co-authored-by: Akshay Aggarwal
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
.../ocr2/plugins/ocr2keeper/evm21/registry.go | 19 +-
.../ocr2keeper/evm21/streams_lookup.go | 88 ++++++--
.../ocr2keeper/evm21/streams_lookup_test.go | 205 ++++++++++++++----
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
9 files changed, 248 insertions(+), 82 deletions(-)
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 6b0a33451e..8d731f3f41 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -22,7 +22,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
- github.com/smartcontractkit/ocr2keepers v0.7.27
+ github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/spf13/cobra v1.6.1
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 2cb0eb2582..ebab8c990d 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1478,8 +1478,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545 h1:qOsw2ETQD/Sb/W2xuYn2KPWjvvsWA0C+l19rWFq8iNg=
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
-github.com/smartcontractkit/ocr2keepers v0.7.27 h1:kwqMrzmEdq6gH4yqNuLQCbdlED0KaIjwZzu3FF+Gves=
-github.com/smartcontractkit/ocr2keepers v0.7.27/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
+github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
+github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A=
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
index 0ca20477f2..73e2bc0a9c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
@@ -20,6 +20,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -35,11 +36,14 @@ import (
)
const (
+ defaultPluginRetryExpiration = 30 * time.Minute
// defaultAllowListExpiration decides how long an upkeep's allow list info will be valid for.
- defaultAllowListExpiration = 20 * time.Minute
- // allowListCleanupInterval decides when the expired items in allowList cache will be deleted.
- allowListCleanupInterval = 5 * time.Minute
+ defaultAllowListExpiration = 10 * time.Minute
+ // cleanupInterval decides when the expired items in cache will be deleted.
+ cleanupInterval = 5 * time.Minute
logTriggerRefreshBatchSize = 32
+ totalFastPluginRetries = 5
+ totalMediumPluginRetries = 10
)
var (
@@ -100,9 +104,10 @@ func NewEvmRegistry(
headFunc: func(ocr2keepers.BlockKey) {},
chLog: make(chan logpoller.Log, 1000),
mercury: &MercuryConfig{
- cred: mc,
- abi: core.StreamsCompatibleABI,
- allowListCache: cache.New(defaultAllowListExpiration, allowListCleanupInterval),
+ cred: mc,
+ abi: core.StreamsCompatibleABI,
+ allowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
+ pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
},
hc: http.DefaultClient,
logEventProvider: logEventProvider,
@@ -126,6 +131,8 @@ type MercuryConfig struct {
abi abi.ABI
// allowListCache stores the upkeeps privileges. In 2.1, this only includes a JSON bytes for allowed to use mercury
allowListCache *cache.Cache
+
+ pluginRetryCache *cache.Cache
}
type EvmRegistry struct {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
index 6f2594b6c3..f183e1f6bb 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
@@ -162,10 +162,11 @@ func (r *EvmRegistry) streamsLookup(ctx context.Context, checkResults []ocr2keep
func (r *EvmRegistry) doLookup(ctx context.Context, wg *sync.WaitGroup, lookup *StreamsLookup, i int, checkResults []ocr2keepers.CheckResult, lggr logger.Logger) {
defer wg.Done()
- state, reason, values, retryable, err := r.doMercuryRequest(ctx, lookup, lggr)
+ state, reason, values, retryable, ri, err := r.doMercuryRequest(ctx, lookup, generatePluginRetryKey(checkResults[i].WorkID, lookup.block), lggr)
if err != nil {
- lggr.Errorf("upkeep %s retryable %v doMercuryRequest: %s", lookup.upkeepId, retryable, err.Error())
+ lggr.Errorf("upkeep %s retryable %v retryInterval %s doMercuryRequest: %s", lookup.upkeepId, retryable, ri, err.Error())
checkResults[i].Retryable = retryable
+ checkResults[i].RetryInterval = ri
checkResults[i].PipelineExecutionState = uint8(state)
checkResults[i].IneligibilityReason = uint8(reason)
return
@@ -278,12 +279,12 @@ func (r *EvmRegistry) checkCallback(ctx context.Context, values [][]byte, lookup
}
// doMercuryRequest sends requests to Mercury API to retrieve mercury data.
-func (r *EvmRegistry) doMercuryRequest(ctx context.Context, sl *StreamsLookup, lggr logger.Logger) (encoding.PipelineExecutionState, encoding.UpkeepFailureReason, [][]byte, bool, error) {
+func (r *EvmRegistry) doMercuryRequest(ctx context.Context, sl *StreamsLookup, prk string, lggr logger.Logger) (encoding.PipelineExecutionState, encoding.UpkeepFailureReason, [][]byte, bool, time.Duration, error) {
var isMercuryV03 bool
resultLen := len(sl.Feeds)
ch := make(chan MercuryData, resultLen)
if len(sl.Feeds) == 0 {
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
+ return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
}
if sl.FeedParamKey == feedIdHex && sl.TimeParamKey == blockNumber {
// only mercury v0.2
@@ -297,10 +298,11 @@ func (r *EvmRegistry) doMercuryRequest(ctx context.Context, sl *StreamsLookup, l
ch = make(chan MercuryData, resultLen)
go r.multiFeedsRequest(ctx, ch, sl, lggr)
} else {
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
+ return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
}
var reqErr error
+ var ri time.Duration
results := make([][]byte, len(sl.Feeds))
retryable := true
allSuccess := true
@@ -323,8 +325,11 @@ func (r *EvmRegistry) doMercuryRequest(ctx context.Context, sl *StreamsLookup, l
results[m.Index] = m.Bytes[0]
}
}
+ if retryable && !allSuccess {
+ ri = r.calculateRetryConfig(prk)
+ }
// only retry when not all successful AND none are not retryable
- return state, encoding.UpkeepFailureReasonNone, results, retryable && !allSuccess, reqErr
+ return state, encoding.UpkeepFailureReasonNone, results, retryable && !allSuccess, ri, reqErr
}
// singleFeedRequest sends a v0.2 Mercury request for a single feed report.
@@ -378,7 +383,7 @@ func (r *EvmRegistry) singleFeedRequest(ctx context.Context, ch chan<- MercuryDa
return err1
}
- if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusInternalServerError {
+ if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusInternalServerError || resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusServiceUnavailable || resp.StatusCode == http.StatusGatewayTimeout {
lggr.Warnf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, sl.Feeds[index])
retryable = true
state = encoding.MercuryFlakyFailure
@@ -415,9 +420,9 @@ func (r *EvmRegistry) singleFeedRequest(ctx context.Context, ch chan<- MercuryDa
sent = true
return nil
},
- // only retry when the error is 404 Not Found or 500 Internal Server Error
+ // only retry when the error is 404 Not Found, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
retry.RetryIf(func(err error) bool {
- return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError)
+ return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) || err.Error() == fmt.Sprintf("%d", http.StatusBadGateway) || err.Error() == fmt.Sprintf("%d", http.StatusServiceUnavailable) || err.Error() == fmt.Sprintf("%d", http.StatusGatewayTimeout)
}),
retry.Context(ctx),
retry.Delay(retryDelay),
@@ -504,15 +509,29 @@ func (r *EvmRegistry) multiFeedsRequest(ctx context.Context, ch chan<- MercuryDa
retryable = false
state = encoding.InvalidMercuryRequest
return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3 with message: %s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, string(body))
- } else if resp.StatusCode == http.StatusInternalServerError {
+ } else if resp.StatusCode == http.StatusInternalServerError || resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusServiceUnavailable || resp.StatusCode == http.StatusGatewayTimeout {
retryable = true
state = encoding.MercuryFlakyFailure
- return fmt.Errorf("%d", http.StatusInternalServerError)
- } else if resp.StatusCode == 420 {
- // in 0.3, this will happen when missing/malformed query args, missing or bad required headers, non-existent feeds, or no permissions for feeds
- retryable = false
- state = encoding.InvalidMercuryRequest
- return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by missing/malformed query args, missing or bad required headers, non-existent feeds, or no permissions for feeds", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode)
+ return fmt.Errorf("%d", resp.StatusCode)
+ } else if resp.StatusCode == http.StatusPartialContent {
+ //var response MercuryV03Response
+ //err1 = json.Unmarshal(body, &response)
+ //if err1 != nil {
+ // lggr.Warnf("at timestamp %s upkeep %s failed to unmarshal body to MercuryV03Response from mercury v0.3: %v", sl.Time.String(), sl.upkeepId.String(), err1)
+ // retryable = false
+ // state = encoding.MercuryUnmarshalError
+ // return err1
+ //}
+ // in v0.3, if some feeds are not available, the server will only return available feeds, but we need to make sure ALL feeds are retrieved before calling user contract
+ // hence, retry in this case. retry will help when we send a very new timestamp and reports are not yet generated
+ //var receivedFeeds []string
+ //for _, f := range response.Reports {
+ // receivedFeeds = append(receivedFeeds, f.FeedID)
+ //}
+ lggr.Warnf("at timestamp %s upkeep %s requested [%s] feeds but mercury v0.3 server returned 206 status, treating it as 404 and retrying", sl.Time.String(), sl.upkeepId.String(), sl.Feeds)
+ retryable = true
+ state = encoding.MercuryFlakyFailure
+ return fmt.Errorf("%d", http.StatusPartialContent)
} else if resp.StatusCode != http.StatusOK {
retryable = false
state = encoding.InvalidMercuryRequest
@@ -532,8 +551,11 @@ func (r *EvmRegistry) multiFeedsRequest(ctx context.Context, ch chan<- MercuryDa
// in v0.3, if some feeds are not available, the server will only return available feeds, but we need to make sure ALL feeds are retrieved before calling user contract
// hence, retry in this case. retry will help when we send a very new timestamp and reports are not yet generated
if len(response.Reports) != len(sl.Feeds) {
- // TODO: AUTO-5044: calculate what reports are missing and log a warning
- lggr.Warnf("at timestamp %s upkeep %s mercury v0.3 server retruned 200 status with %d reports while we requested %d feeds, treating as 404 (not found) and retrying", sl.Time.String(), sl.upkeepId.String(), len(response.Reports), len(sl.Feeds))
+ var receivedFeeds []string
+ for _, f := range response.Reports {
+ receivedFeeds = append(receivedFeeds, f.FeedID)
+ }
+ lggr.Warnf("at timestamp %s upkeep %s mercury v0.3 server returned 206 status with [%s] reports while we requested [%s] feeds, retrying", sl.Time.String(), sl.upkeepId.String(), receivedFeeds, sl.Feeds)
retryable = true
state = encoding.MercuryFlakyFailure
return fmt.Errorf("%d", http.StatusNotFound)
@@ -558,9 +580,9 @@ func (r *EvmRegistry) multiFeedsRequest(ctx context.Context, ch chan<- MercuryDa
sent = true
return nil
},
- // only retry when the error is 404 Not Found or 500 Internal Server Error
+ // only retry when the error is 206 Partial Content, 404 Not Found, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
retry.RetryIf(func(err error) bool {
- return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError)
+ return err.Error() == fmt.Sprintf("%d", http.StatusPartialContent) || err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) || err.Error() == fmt.Sprintf("%d", http.StatusBadGateway) || err.Error() == fmt.Sprintf("%d", http.StatusServiceUnavailable) || err.Error() == fmt.Sprintf("%d", http.StatusGatewayTimeout)
}),
retry.Context(ctx),
retry.Delay(retryDelay),
@@ -593,3 +615,29 @@ func (r *EvmRegistry) generateHMAC(method string, path string, body []byte, clie
userHmac := hex.EncodeToString(signedMessage.Sum(nil))
return userHmac
}
+
+// calculateRetryConfig returns plugin retry interval based on how many times plugin has retried this work
+func (r *EvmRegistry) calculateRetryConfig(prk string) time.Duration {
+ var ri time.Duration
+ var retries int
+ totalAttempts, ok := r.mercury.pluginRetryCache.Get(prk)
+ if ok {
+ retries = totalAttempts.(int)
+ if retries < totalFastPluginRetries {
+ ri = 1 * time.Second
+ } else if retries < totalMediumPluginRetries {
+ ri = 5 * time.Second
+ }
+ // if the core node has retried totalMediumPluginRetries times, do not set retry interval and plugin will use
+ // the default interval
+ } else {
+ ri = 1 * time.Second
+ }
+ r.mercury.pluginRetryCache.Set(prk, retries+1, cache.DefaultExpiration)
+ return ri
+}
+
+// generatePluginRetryKey returns a plugin retry cache key
+func generatePluginRetryKey(workID string, block uint64) string {
+ return workID + "|" + fmt.Sprintf("%d", block)
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
index 6f7065ef87..8d7c67d80c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
@@ -10,6 +10,7 @@ import (
"net/http"
"strings"
"testing"
+ "time"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -65,8 +66,9 @@ func setupEVMRegistry(t *testing.T) *EvmRegistry {
Username: "FakeClientID",
Password: "FakeClientKey",
},
- abi: streamsLookupCompatibleABI,
- allowListCache: cache.New(defaultAllowListExpiration, allowListCleanupInterval),
+ abi: streamsLookupCompatibleABI,
+ allowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
+ pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
},
hc: mockHttpClient,
}
@@ -427,15 +429,18 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10)
tests := []struct {
- name string
- lookup *StreamsLookup
- mockHttpStatusCode int
- mockChainlinkBlobs []string
- expectedValues [][]byte
- expectedRetryable bool
- expectedError error
- state encoding.PipelineExecutionState
- reason encoding.UpkeepFailureReason
+ name string
+ lookup *StreamsLookup
+ mockHttpStatusCode int
+ mockChainlinkBlobs []string
+ pluginRetries int
+ pluginRetryKey string
+ expectedValues [][]byte
+ expectedRetryable bool
+ expectedRetryInterval time.Duration
+ expectedError error
+ state encoding.PipelineExecutionState
+ reason encoding.UpkeepFailureReason
}{
{
name: "success",
@@ -456,7 +461,7 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
expectedError: nil,
},
{
- name: "failure - retryable",
+ name: "failure - retryable and interval is 1s",
lookup: &StreamsLookup{
StreamsLookupError: &encoding.StreamsLookupError{
FeedParamKey: feedIdHex,
@@ -467,6 +472,49 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
},
upkeepId: upkeepId,
},
+ mockHttpStatusCode: http.StatusInternalServerError,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{nil},
+ expectedRetryable: true,
+ pluginRetries: 0,
+ expectedRetryInterval: 1 * time.Second,
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
+ state: encoding.MercuryFlakyFailure,
+ },
+ {
+ name: "failure - retryable and interval is 5s",
+ lookup: &StreamsLookup{
+ StreamsLookupError: &encoding.StreamsLookupError{
+ FeedParamKey: feedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: blockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ upkeepId: upkeepId,
+ },
+ pluginRetries: 5,
+ mockHttpStatusCode: http.StatusInternalServerError,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{nil},
+ expectedRetryable: true,
+ expectedRetryInterval: 5 * time.Second,
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
+ state: encoding.MercuryFlakyFailure,
+ },
+ {
+ name: "failure - not retryable because there are many plugin retries already",
+ lookup: &StreamsLookup{
+ StreamsLookupError: &encoding.StreamsLookupError{
+ FeedParamKey: feedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: blockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ upkeepId: upkeepId,
+ },
+ pluginRetries: 10,
mockHttpStatusCode: http.StatusInternalServerError,
mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
expectedValues: [][]byte{nil},
@@ -486,11 +534,11 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
},
upkeepId: upkeepId,
},
- mockHttpStatusCode: http.StatusBadGateway,
+ mockHttpStatusCode: http.StatusTooManyRequests,
mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
expectedValues: [][]byte{nil},
expectedRetryable: false,
- expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 25880526 upkeep 88786950015966611018675766524283132478093844178961698330929478019253453382042 received status code 502 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"),
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 25880526 upkeep 88786950015966611018675766524283132478093844178961698330929478019253453382042 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"),
state: encoding.InvalidMercuryRequest,
},
{
@@ -528,6 +576,9 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ if tt.pluginRetries != 0 {
+ r.mercury.pluginRetryCache.Set(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
+ }
hc := mocks.NewHttpClient(t)
for _, blob := range tt.mockChainlinkBlobs {
@@ -539,7 +590,7 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
StatusCode: tt.mockHttpStatusCode,
Body: io.NopCloser(bytes.NewReader(b)),
}
- if tt.expectedError != nil && tt.expectedRetryable {
+ if tt.expectedError != nil && tt.expectedRetryable || tt.pluginRetries > 0 {
hc.On("Do", mock.Anything).Return(resp, nil).Times(totalAttempt)
} else {
hc.On("Do", mock.Anything).Return(resp, nil).Once()
@@ -547,13 +598,18 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
}
r.hc = hc
- state, reason, values, retryable, reqErr := r.doMercuryRequest(context.Background(), tt.lookup, r.lggr)
+ state, reason, values, retryable, ri, reqErr := r.doMercuryRequest(context.Background(), tt.lookup, tt.pluginRetryKey, r.lggr)
assert.Equal(t, tt.expectedValues, values)
assert.Equal(t, tt.expectedRetryable, retryable)
+ if retryable {
+ newRetries, _ := r.mercury.pluginRetryCache.Get(tt.pluginRetryKey)
+ assert.Equal(t, tt.pluginRetries+1, newRetries.(int))
+ }
+ assert.Equal(t, tt.expectedRetryInterval, ri)
assert.Equal(t, tt.state, state)
assert.Equal(t, tt.reason, reason)
if tt.expectedError != nil {
- assert.Equal(t, tt.expectedError.Error(), reqErr.Error())
+ assert.True(t, strings.HasPrefix(reqErr.Error(), "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"))
}
})
}
@@ -563,15 +619,17 @@ func TestEvmRegistry_DoMercuryRequestV03(t *testing.T) {
upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10)
tests := []struct {
- name string
- lookup *StreamsLookup
- mockHttpStatusCode int
- mockChainlinkBlobs []string
- expectedValues [][]byte
- expectedRetryable bool
- expectedError error
- state encoding.PipelineExecutionState
- reason encoding.UpkeepFailureReason
+ name string
+ lookup *StreamsLookup
+ mockHttpStatusCode int
+ mockChainlinkBlobs []string
+ pluginRetryKey string
+ expectedValues [][]byte
+ expectedRetryable bool
+ expectedRetryInterval time.Duration
+ expectedError error
+ state encoding.PipelineExecutionState
+ reason encoding.UpkeepFailureReason
}{
{
name: "success v0.3",
@@ -622,9 +680,10 @@ func TestEvmRegistry_DoMercuryRequestV03(t *testing.T) {
}
r.hc = hc
- state, reason, values, retryable, reqErr := r.doMercuryRequest(context.Background(), tt.lookup, r.lggr)
+ state, reason, values, retryable, ri, reqErr := r.doMercuryRequest(context.Background(), tt.lookup, tt.pluginRetryKey, r.lggr)
assert.Equal(t, tt.expectedValues, values)
assert.Equal(t, tt.expectedRetryable, retryable)
+ assert.Equal(t, tt.expectedRetryInterval, ri)
assert.Equal(t, tt.state, state)
assert.Equal(t, tt.reason, reason)
if tt.expectedError != nil {
@@ -640,6 +699,7 @@ func TestEvmRegistry_SingleFeedRequest(t *testing.T) {
name string
index int
lookup *StreamsLookup
+ pluginRetryKey string
blob string
statusCode int
lastStatusCode int
@@ -728,8 +788,8 @@ func TestEvmRegistry_SingleFeedRequest(t *testing.T) {
blob: "0xab2123dc",
retryNumber: 1,
statusCode: http.StatusNotFound,
- lastStatusCode: http.StatusBadGateway,
- errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 404\n#2: at block 123456 upkeep 123456789 received status code 502 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ lastStatusCode: http.StatusTooManyRequests,
+ errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 404\n#2: at block 123456 upkeep 123456789 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
},
{
name: "failure - returns not retryable",
@@ -744,8 +804,8 @@ func TestEvmRegistry_SingleFeedRequest(t *testing.T) {
upkeepId: upkeepId,
},
blob: "0xab2123dc",
- statusCode: http.StatusBadGateway,
- errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 123456 upkeep 123456789 received status code 502 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ statusCode: http.StatusConflict,
+ errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 123456 upkeep 123456789 received status code 409 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
},
}
@@ -819,6 +879,8 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
lookup *StreamsLookup
statusCode int
lastStatusCode int
+ pluginRetries int
+ pluginRetryKey string
retryNumber int
retryable bool
errorMessage string
@@ -883,6 +945,47 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
},
statusCode: http.StatusOK,
},
+ {
+ name: "success - retry 206",
+ lookup: &StreamsLookup{
+ StreamsLookupError: &encoding.StreamsLookupError{
+ FeedParamKey: feedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: timestamp,
+ Time: big.NewInt(123456),
+ },
+ upkeepId: upkeepId,
+ },
+ firstResponse: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ },
+ },
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000019",
+ },
+ },
+ },
+ retryNumber: 1,
+ statusCode: http.StatusPartialContent,
+ lastStatusCode: http.StatusOK,
+ },
{
name: "success - retry for 500",
lookup: &StreamsLookup{
@@ -946,7 +1049,7 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
errorMessage: "All attempts fail:\n#1: hex string without 0x prefix",
},
{
- name: "failure - returns retryable",
+ name: "failure - returns retryable with 1s plugin retry interval",
lookup: &StreamsLookup{
StreamsLookupError: &encoding.StreamsLookupError{
FeedParamKey: feedIDs,
@@ -962,7 +1065,7 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
errorMessage: "All attempts fail:\n#1: 500\n#2: 500\n#3: 500",
},
{
- name: "failure - returns retryable and then non-retryable",
+ name: "failure - returns retryable with 5s plugin retry interval",
lookup: &StreamsLookup{
StreamsLookupError: &encoding.StreamsLookupError{
FeedParamKey: feedIDs,
@@ -972,27 +1075,30 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
},
upkeepId: upkeepId,
},
- retryNumber: 1,
- statusCode: http.StatusInternalServerError,
- lastStatusCode: http.StatusUnauthorized,
- errorMessage: "All attempts fail:\n#1: 500\n#2: at timestamp 123456 upkeep 123456789 received status code 401 from mercury v0.3, most likely this is caused by unauthorized upkeep",
+ pluginRetries: 6,
+ retryNumber: totalAttempt,
+ statusCode: http.StatusInternalServerError,
+ retryable: true,
+ errorMessage: "All attempts fail:\n#1: 500\n#2: 500\n#3: 500",
},
{
- name: "failure - returns status code 420 not retryable",
+ name: "failure - returns retryable and then non-retryable",
lookup: &StreamsLookup{
StreamsLookupError: &encoding.StreamsLookupError{
FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
TimeParamKey: timestamp,
Time: big.NewInt(123456),
},
upkeepId: upkeepId,
},
- statusCode: 420,
- errorMessage: "All attempts fail:\n#1: at timestamp 123456 upkeep 123456789 received status code 420 from mercury v0.3, most likely this is caused by missing/malformed query args, missing or bad required headers, non-existent feeds, or no permissions for feeds",
+ retryNumber: 1,
+ statusCode: http.StatusInternalServerError,
+ lastStatusCode: http.StatusUnauthorized,
+ errorMessage: "All attempts fail:\n#1: 500\n#2: at timestamp 123456 upkeep 123456789 received status code 401 from mercury v0.3, most likely this is caused by unauthorized upkeep",
},
{
- name: "failure - returns status code 502 not retryable",
+ name: "failure - returns status code 422 not retryable",
lookup: &StreamsLookup{
StreamsLookupError: &encoding.StreamsLookupError{
FeedParamKey: feedIDs,
@@ -1002,8 +1108,8 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
},
upkeepId: upkeepId,
},
- statusCode: http.StatusBadGateway,
- errorMessage: "All attempts fail:\n#1: at timestamp 123456 upkeep 123456789 received status code 502 from mercury v0.3",
+ statusCode: http.StatusUnprocessableEntity,
+ errorMessage: "All attempts fail:\n#1: at timestamp 123456 upkeep 123456789 received status code 422 from mercury v0.3",
},
{
name: "success - retry when reports length does not match feeds length",
@@ -1042,14 +1148,19 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
},
},
},
- retryNumber: 1,
- statusCode: http.StatusOK,
+ retryNumber: 1,
+ statusCode: http.StatusOK,
+ lastStatusCode: http.StatusOK,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ if tt.pluginRetries != 0 {
+ r.mercury.pluginRetryCache.Set(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
+ }
+
hc := mocks.NewHttpClient(t)
b, err := json.Marshal(tt.response)
assert.Nil(t, err)
@@ -1071,7 +1182,7 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
b1, err := json.Marshal(tt.response)
assert.Nil(t, err)
resp1 := &http.Response{
- StatusCode: tt.statusCode,
+ StatusCode: tt.lastStatusCode,
Body: io.NopCloser(bytes.NewReader(b1)),
}
hc.On("Do", mock.Anything).Return(resp0, nil).Once().On("Do", mock.Anything).Return(resp1, nil).Once()
diff --git a/go.mod b/go.mod
index f271bf421f..4d8a929402 100644
--- a/go.mod
+++ b/go.mod
@@ -70,7 +70,7 @@ require (
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
- github.com/smartcontractkit/ocr2keepers v0.7.27
+ github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1
diff --git a/go.sum b/go.sum
index 8426876e23..acd966e8aa 100644
--- a/go.sum
+++ b/go.sum
@@ -1479,8 +1479,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545 h1:qOsw2ETQD/Sb/W2xuYn2KPWjvvsWA0C+l19rWFq8iNg=
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
-github.com/smartcontractkit/ocr2keepers v0.7.27 h1:kwqMrzmEdq6gH4yqNuLQCbdlED0KaIjwZzu3FF+Gves=
-github.com/smartcontractkit/ocr2keepers v0.7.27/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
+github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
+github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index f73838f1ab..936729944f 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -25,7 +25,7 @@ require (
github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
- github.com/smartcontractkit/ocr2keepers v0.7.27
+ github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 843cef2690..7bd733023c 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2384,8 +2384,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545 h1:qOsw2ETQD/Sb/W2xuYn2KPWjvvsWA0C+l19rWFq8iNg=
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
-github.com/smartcontractkit/ocr2keepers v0.7.27 h1:kwqMrzmEdq6gH4yqNuLQCbdlED0KaIjwZzu3FF+Gves=
-github.com/smartcontractkit/ocr2keepers v0.7.27/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
+github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
+github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A=
From 7b5e6a5ea6c4a450af73acd67a322553d033a16a Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Mon, 6 Nov 2023 14:56:22 -0500
Subject: [PATCH 081/327] Fixes old pointer aliases (#11187)
---
.../chaos/automation_chaos_test.go | 17 ++++++++---------
integration-tests/chaos/ocr2vrf_chaos_test.go | 17 ++++++++---------
integration-tests/chaos/ocr_chaos_test.go | 17 ++++++++---------
integration-tests/reorg/reorg_confirmer.go | 7 ++++---
4 files changed, 28 insertions(+), 30 deletions(-)
diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go
index a3d4e37406..22c9e742f3 100644
--- a/integration-tests/chaos/automation_chaos_test.go
+++ b/integration-tests/chaos/automation_chaos_test.go
@@ -14,7 +14,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
- a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
@@ -132,7 +131,7 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMinority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -141,7 +140,7 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -150,9 +149,9 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
DurationStr: "1m",
- ContainerNames: &[]*string{a.Str("chainlink-db")},
+ ContainerNames: &[]*string{utils.Ptr("chainlink-db")},
},
},
NetworkChaosFailMajorityNetwork: {
@@ -160,8 +159,8 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{ChaosGroupMajority: a.Str("1")},
- ToLabels: &map[string]*string{ChaosGroupMinority: a.Str("1")},
+ FromLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ ToLabels: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -170,8 +169,8 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{"app": a.Str("geth")},
- ToLabels: &map[string]*string{ChaosGroupMajorityPlus: a.Str("1")},
+ FromLabels: &map[string]*string{"app": utils.Ptr("geth")},
+ ToLabels: &map[string]*string{ChaosGroupMajorityPlus: utils.Ptr("1")},
DurationStr: "1m",
},
},
diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go
index 0beccadddd..ba75974f01 100644
--- a/integration-tests/chaos/ocr2vrf_chaos_test.go
+++ b/integration-tests/chaos/ocr2vrf_chaos_test.go
@@ -13,7 +13,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
- a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
@@ -68,7 +67,7 @@ func TestOCR2VRFChaos(t *testing.T) {
chainlink.New(0, defaultOCR2VRFSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMinority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -78,7 +77,7 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewFailPods,
// &chaos.Props{
- // LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ // LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
// DurationStr: "1m",
// },
//},
@@ -88,9 +87,9 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewFailPods,
// &chaos.Props{
- // LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ // LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
// DurationStr: "1m",
- // ContainerNames: &[]*string{a.Str("chainlink-db")},
+ // ContainerNames: &[]*string{utils.Ptr("chainlink-db")},
// },
//},
//NetworkChaosFailMajorityNetwork: {
@@ -98,8 +97,8 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewNetworkPartition,
// &chaos.Props{
- // FromLabels: &map[string]*string{ChaosGroupMajority: a.Str("1")},
- // ToLabels: &map[string]*string{ChaosGroupMinority: a.Str("1")},
+ // FromLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ // ToLabels: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
// DurationStr: "1m",
// },
//},
@@ -108,8 +107,8 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewNetworkPartition,
// &chaos.Props{
- // FromLabels: &map[string]*string{"app": a.Str("geth")},
- // ToLabels: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ // FromLabels: &map[string]*string{"app": utils.Ptr("geth")},
+ // ToLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
// DurationStr: "1m",
// },
//},
diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go
index b65f8bb74f..599fad8ddc 100644
--- a/integration-tests/chaos/ocr_chaos_test.go
+++ b/integration-tests/chaos/ocr_chaos_test.go
@@ -15,7 +15,6 @@ import (
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
- a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
@@ -81,8 +80,8 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{ChaosGroupMajority: a.Str("1")},
- ToLabels: &map[string]*string{ChaosGroupMinority: a.Str("1")},
+ FromLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ ToLabels: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -91,8 +90,8 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{"app": a.Str("geth")},
- ToLabels: &map[string]*string{ChaosGroupMajorityPlus: a.Str("1")},
+ FromLabels: &map[string]*string{"app": utils.Ptr("geth")},
+ ToLabels: &map[string]*string{ChaosGroupMajorityPlus: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -101,7 +100,7 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMinority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -110,7 +109,7 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
DurationStr: "1m",
},
},
@@ -119,9 +118,9 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
DurationStr: "1m",
- ContainerNames: &[]*string{a.Str("chainlink-db")},
+ ContainerNames: &[]*string{utils.Ptr("chainlink-db")},
},
},
}
diff --git a/integration-tests/reorg/reorg_confirmer.go b/integration-tests/reorg/reorg_confirmer.go
index be535d2a6d..885bed2ad4 100644
--- a/integration-tests/reorg/reorg_confirmer.go
+++ b/integration-tests/reorg/reorg_confirmer.go
@@ -14,8 +14,9 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
- a "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/alias"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// The steps are:
@@ -231,8 +232,8 @@ func (rc *ReorgController) forkNetwork(header blockchain.NodeHeader) error {
rc.cfg.Env.Cfg.Namespace,
&chaos.Props{
DurationStr: "999h",
- FromLabels: &map[string]*string{"app": a.Str(reorg.TXNodesAppLabel)},
- ToLabels: &map[string]*string{"app": a.Str(reorg.MinerNodesAppLabel)},
+ FromLabels: &map[string]*string{"app": utils.Ptr(reorg.TXNodesAppLabel)},
+ ToLabels: &map[string]*string{"app": utils.Ptr(reorg.MinerNodesAppLabel)},
},
))
rc.chaosExperimentName = expName
From 2b3806209238ebe3b2d8199639bf5c864fe4ba3c Mon Sep 17 00:00:00 2001
From: Bolek <1416262+bolekk@users.noreply.github.com>
Date: Mon, 6 Nov 2023 12:01:26 -0800
Subject: [PATCH 082/327] [Functions] Respond with an error on insufficient
balance (#11183)
Co-authored-by: Morgan Kuphal <87319522+KuphJr@users.noreply.github.com>
---
core/services/functions/connector_handler.go | 7 ++++++
.../functions/connector_handler_test.go | 24 ++++++++++++++++---
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go
index a018157a37..8a8710e6ea 100644
--- a/core/services/functions/connector_handler.go
+++ b/core/services/functions/connector_handler.go
@@ -78,6 +78,13 @@ func (h *functionsConnectorHandler) HandleGatewayMessage(ctx context.Context, ga
}
if balance, err := h.subscriptions.GetMaxUserBalance(fromAddr); err != nil || balance.Cmp(h.minimumBalance.ToInt()) < 0 {
h.lggr.Errorw("user subscription has insufficient balance", "id", gatewayId, "address", fromAddr, "balance", balance, "minBalance", h.minimumBalance)
+ response := functions.SecretsResponseBase{
+ Success: false,
+ ErrorMessage: "user subscription has insufficient balance",
+ }
+ if err := h.sendResponse(ctx, gatewayId, body, response); err != nil {
+ h.lggr.Errorw("failed to send response to gateway", "id", gatewayId, "error", err)
+ }
return
}
diff --git a/core/services/functions/connector_handler_test.go b/core/services/functions/connector_handler_test.go
index bb3e2acbab..7bf98d7501 100644
--- a/core/services/functions/connector_handler_test.go
+++ b/core/services/functions/connector_handler_test.go
@@ -39,7 +39,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
allowlist.On("Close", mock.Anything).Return(nil)
subscriptions.On("Start", mock.Anything).Return(nil)
subscriptions.On("Close", mock.Anything).Return(nil)
- handler, err := functions.NewFunctionsConnectorHandler(addr.Hex(), privateKey, storage, allowlist, rateLimiter, subscriptions, *assets.NewLinkFromJuels(0), logger)
+ handler, err := functions.NewFunctionsConnectorHandler(addr.Hex(), privateKey, storage, allowlist, rateLimiter, subscriptions, *assets.NewLinkFromJuels(100), logger)
require.NoError(t, err)
handler.SetConnector(connector)
@@ -78,7 +78,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
}
storage.On("List", ctx, addr).Return(snapshot, nil).Once()
allowlist.On("Allow", addr).Return(true).Once()
- subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil)
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -91,6 +91,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
t.Run("orm error", func(t *testing.T) {
storage.On("List", ctx, addr).Return(nil, errors.New("boom")).Once()
allowlist.On("Allow", addr).Return(true).Once()
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -135,7 +136,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
storage.On("Put", ctx, &key, &record, signature).Return(nil).Once()
allowlist.On("Allow", addr).Return(true).Once()
- subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil)
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -148,6 +149,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
t.Run("orm error", func(t *testing.T) {
storage.On("Put", ctx, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("boom")).Once()
allowlist.On("Allow", addr).Return(true).Once()
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -163,6 +165,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
require.NoError(t, msg.Sign(privateKey))
storage.On("Put", ctx, mock.Anything, mock.Anything, mock.Anything).Return(s4.ErrWrongSignature).Once()
allowlist.On("Allow", addr).Return(true).Once()
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -177,6 +180,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
msg.Body.Payload = json.RawMessage(`{sdfgdfgoscsicosd:sdf:::sdf ::; xx}`)
require.NoError(t, msg.Sign(privateKey))
allowlist.On("Allow", addr).Return(true).Once()
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -186,6 +190,19 @@ func TestFunctionsConnectorHandler(t *testing.T) {
handler.HandleGatewayMessage(ctx, "gw1", &msg)
})
+
+ t.Run("insufficient balance", func(t *testing.T) {
+ allowlist.On("Allow", addr).Return(true).Once()
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(0), nil).Once()
+ connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
+ msg, ok := args[2].(*api.Message)
+ require.True(t, ok)
+ require.Equal(t, `{"success":false,"error_message":"user subscription has insufficient balance"}`, string(msg.Body.Payload))
+
+ }).Return(nil).Once()
+
+ handler.HandleGatewayMessage(ctx, "gw1", &msg)
+ })
})
t.Run("unsupported method", func(t *testing.T) {
@@ -201,6 +218,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
require.NoError(t, msg.Sign(privateKey))
allowlist.On("Allow", addr).Return(true).Once()
+ subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
handler.HandleGatewayMessage(testutils.Context(t), "gw1", &msg)
})
})
From 0ae0b691466687ac7be2b49d9d4a1bd3136d6424 Mon Sep 17 00:00:00 2001
From: Erik Burton
Date: Mon, 6 Nov 2023 13:24:15 -0800
Subject: [PATCH 083/327] chore: bump sigstore/cosign-installer from 2.1.0 to
3.1.2 (#11192)
---
.github/actions/build-sign-publish-chainlink/action.yml | 2 +-
.github/actions/goreleaser-build-sign-publish/action.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml
index fe4ef858f5..62add53092 100644
--- a/.github/actions/build-sign-publish-chainlink/action.yml
+++ b/.github/actions/build-sign-publish-chainlink/action.yml
@@ -223,7 +223,7 @@ runs:
- if: inputs.sign-images == 'true'
name: Install cosign
- uses: sigstore/cosign-installer@581838fbedd492d2350a9ecd427a95d6de1e5d01 # v2.1.0
+ uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
with:
cosign-release: "v1.6.0"
diff --git a/.github/actions/goreleaser-build-sign-publish/action.yml b/.github/actions/goreleaser-build-sign-publish/action.yml
index 845d2443fc..b2d42c1234 100644
--- a/.github/actions/goreleaser-build-sign-publish/action.yml
+++ b/.github/actions/goreleaser-build-sign-publish/action.yml
@@ -84,7 +84,7 @@ runs:
version: ${{ inputs.zig-version }}
- name: Setup cosign
if: inputs.enable-cosign == 'true'
- uses: sigstore/cosign-installer@581838fbedd492d2350a9ecd427a95d6de1e5d01 # v2.1.0
+ uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
with:
cosign-release: ${{ inputs.cosign-version }}
- name: Login to docker registry
From c71ead762d71e8952698b1be303c158cbd6f74e0 Mon Sep 17 00:00:00 2001
From: Tate
Date: Mon, 6 Nov 2023 17:00:15 -0700
Subject: [PATCH 084/327] [TT-668] Use Internal Mirror for docker images used
in e2e tests (#11189)
Part of the effor to remove the e2e flakes caused by dockerhub rate limit issues
---
.github/workflows/integration-tests.yml | 4 ----
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
3 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 928c716dd1..125ddb3f4f 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -228,8 +228,6 @@ jobs:
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
- dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
artifacts_location: ./integration-tests/smoke/logs/
publish_check_name: ${{ matrix.product.name }}
token: ${{ secrets.GITHUB_TOKEN }}
@@ -429,8 +427,6 @@ jobs:
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}${{ matrix.product.tag_suffix }}
aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
- dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
artifacts_name: ${{ matrix.product.name }}-test-logs
artifacts_location: ./integration-tests/smoke/logs/
publish_check_name: ${{ matrix.product.name }}
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 936729944f..8daa5a29e5 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,7 +22,7 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.4
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.28
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 7bd733023c..696e06b6c9 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2376,8 +2376,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66 h1:AOqcHiAppMoIvM2WSJNIZzJDnOQNXyElbLFK3ZqoJeM=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.4-0.20231106173929-20fe04d6ad66/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.4 h1:IAalKSqRDSGj10zE/JvFrngKGp7mEIVTPh5jTnsaCec=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.4/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
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 0e5b5232e378263964f202ff4bb1712c4ad77813 Mon Sep 17 00:00:00 2001
From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com>
Date: Tue, 7 Nov 2023 11:00:37 +0400
Subject: [PATCH 085/327] Fix Automation benchmark test (#11191)
* fix benchmark test
* bump runner
---
.github/workflows/automation-benchmark-tests.yml | 2 +-
integration-tests/benchmark/keeper_test.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index 7bdb66c919..a4338d642b 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -57,7 +57,7 @@ jobs:
id-token: write
contents: read
name: ${{ inputs.network }} Automation Benchmark Test
- runs-on: ubuntu-latest
+ runs-on: ubuntu20.04-16cores-64GB
env:
SELECTED_NETWORKS: ${{ inputs.network }}
SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }}
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index 25a147fbf0..9342f3629b 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -227,7 +227,7 @@ func addRegistry(registryToTest string) []eth_contracts.KeeperRegistryVersion {
case "2_0-Multiple":
return repeatRegistries(eth_contracts.RegistryVersion_2_0, NumberOfRegistries)
case "2_1-Multiple":
- return repeatRegistries(eth_contracts.RegistryVersion_1_0, NumberOfRegistries)
+ return repeatRegistries(eth_contracts.RegistryVersion_2_1, NumberOfRegistries)
default:
return []eth_contracts.KeeperRegistryVersion{eth_contracts.RegistryVersion_2_0}
}
From fcaf226947ceece466df04e0524428f132ecc267 Mon Sep 17 00:00:00 2001
From: ilija42 <57732589+ilija42@users.noreply.github.com>
Date: Tue, 7 Nov 2023 10:12:36 +0100
Subject: [PATCH 086/327] Add to delegate job spec CaptureEATelemetry override
from evm ocr cfg (#11197)
* Add to delegate job spec CaptureEATelemetry override from evm ocr cfg
* Add logs for when Ea telemetry is disabled
* Update core/services/ocr/delegate.go
Co-authored-by: Jordan Krage
* Update core/services/ocr2/delegate.go
* Update core/services/ocrcommon/data_source.go
---------
Co-authored-by: Patrick
Co-authored-by: Jordan Krage
Co-authored-by: Gheorghe Strimtu
---
core/services/ocr/delegate.go | 3 +++
core/services/ocr2/delegate.go | 2 ++
core/services/ocrcommon/data_source.go | 2 ++
3 files changed, 7 insertions(+)
diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go
index bbed43c151..6eb6714a47 100644
--- a/core/services/ocr/delegate.go
+++ b/core/services/ocr/delegate.go
@@ -295,10 +295,13 @@ func (d *Delegate) ServicesForSpec(jb job.Job) (services []job.ServiceCtx, err e
configOverrider = configOverriderService
}
+ jb.OCROracleSpec.CaptureEATelemetry = chain.Config().OCR().CaptureEATelemetry()
enhancedTelemChan := make(chan ocrcommon.EnhancedTelemetryData, 100)
if ocrcommon.ShouldCollectEnhancedTelemetry(&jb) {
enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, enhancedTelemChan, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint("EVM", chain.ID().String(), concreteSpec.ContractAddress.String(), synchronization.EnhancedEA), lggr.Named("EnhancedTelemetry"))
services = append(services, enhancedTelemService)
+ } else {
+ lggr.Infow("Enhanced telemetry is disabled for job", "job", jb.Name)
}
oracle, err := ocr.NewOracle(ocr.OracleArgs{
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 39a8c84d6b..99aa492bc7 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -746,6 +746,8 @@ func (d *Delegate) newServicesMedian(
if ocrcommon.ShouldCollectEnhancedTelemetry(&jb) {
enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, enhancedTelemChan, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.EnhancedEA), lggr.Named("EnhancedTelemetry"))
medianServices = append(medianServices, enhancedTelemService)
+ } else {
+ lggr.Infow("Enhanced telemetry is disabled for job", "job", jb.Name)
}
return medianServices, err2
diff --git a/core/services/ocrcommon/data_source.go b/core/services/ocrcommon/data_source.go
index ed832e45fc..0363a7124b 100644
--- a/core/services/ocrcommon/data_source.go
+++ b/core/services/ocrcommon/data_source.go
@@ -144,6 +144,8 @@ func (ds *inMemoryDataSource) executeRun(ctx context.Context, timestamp Observat
FinalResults: finalResult,
RepTimestamp: timestamp,
})
+ } else {
+ ds.lggr.Infow("Enhanced telemetry is disabled for job", "job", ds.jb.Name)
}
return run, finalResult, err
From 48b9902f5dc931c6a2d06699ea26f660b65630f1 Mon Sep 17 00:00:00 2001
From: Mohamed Mehany <7327188+mohamed-mehany@users.noreply.github.com>
Date: Tue, 7 Nov 2023 12:11:36 +0100
Subject: [PATCH 087/327] Adds WeMix chain config (#10793)
* Adds WeMix testnet config
* Extending NoNewHeads threshold to 3s
* Adds WeMix contract loader
* Downgrading to go 1.20.5 bullseye
* Revert "Downgrading to go 1.20.5 bullseye"
This reverts commit 7eab839819456513dcf7f83ca8f08c97bdeb3835.
* Update testing branch
* Excludes fee delegation transactions for Wemix
* Update testing branch
* Linting
* Fix typo
* Update CTF
---------
Co-authored-by: davidcauchi
---
.github/workflows/on-demand-ocr-soak-test.yml | 2 +
.../config/toml/defaults/WeMix_Mainnet.toml | 14 ++
.../config/toml/defaults/WeMix_Testnet.toml | 14 ++
.../evm/gas/block_history_estimator_test.go | 6 +
core/chains/evm/gas/chain_specific.go | 7 +
core/config/chaintype.go | 6 +-
core/config/docs/chains-evm.toml | 2 +-
core/services/chainlink/config_test.go | 4 +-
core/services/ocr/contract_tracker.go | 2 +-
docs/CONFIG.md | 160 +++++++++++++++++-
.../contracts/contract_deployer.go | 6 +
.../contracts/contract_loader.go | 7 +
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
14 files changed, 225 insertions(+), 11 deletions(-)
create mode 100644 core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml
create mode 100644 core/chains/evm/config/toml/defaults/WeMix_Testnet.toml
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index 1e510c23be..b6ccad2246 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -28,6 +28,8 @@ on:
- "FANTOM_MAINNET"
- "KROMA_MAINNET"
- "KROMA_SEPOLIA"
+ - "WEMIX_TESTNET"
+ - "WEMIX_MAINNET"
fundingPrivateKey:
description: Private funding key (Skip for Simulated)
required: false
diff --git a/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml b/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml
new file mode 100644
index 0000000000..ee50a9844a
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml
@@ -0,0 +1,14 @@
+ChainID = '1111'
+ChainType = 'wemix'
+FinalityDepth = 1
+MinIncomingConfirmations = 1
+# WeMix emits a block every 1 second, regardless of transactions
+LogPollInterval = '3s'
+NoNewHeadsThreshold = '30s'
+
+[OCR]
+ContractConfirmations = 1
+
+[GasEstimator]
+EIP1559DynamicFees = true
+TipCapDefault = '100 gwei'
diff --git a/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml b/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml
new file mode 100644
index 0000000000..6cdb451eb1
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml
@@ -0,0 +1,14 @@
+ChainID = '1112'
+ChainType = 'wemix'
+FinalityDepth = 1
+MinIncomingConfirmations = 1
+# WeMix emits a block every 1 second, regardless of transactions
+LogPollInterval = '3s'
+NoNewHeadsThreshold = '30s'
+
+[OCR]
+ContractConfirmations = 1
+
+[GasEstimator]
+EIP1559DynamicFees = true
+TipCapDefault = '100 gwei'
diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go
index 7f4d157e37..decb68dbe9 100644
--- a/core/chains/evm/gas/block_history_estimator_test.go
+++ b/core/chains/evm/gas/block_history_estimator_test.go
@@ -1329,6 +1329,12 @@ func TestBlockHistoryEstimator_IsUsable(t *testing.T) {
assert.Equal(t, true, bhe.IsUsable(tx2, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
})
+ t.Run("returns false if transaction is of type 0x16 only on WeMix", func(t *testing.T) {
+ cfg.ChainTypeF = "wemix"
+ tx := evmtypes.Transaction{Type: 0x16, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()}
+ assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
+ })
+
t.Run("returns false if transaction has base fee higher than the gas price only on Celo", func(t *testing.T) {
cfg.ChainTypeF = "celo"
tx := evmtypes.Transaction{Type: 0x0, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()}
diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go
index 4d87b8b454..5c0b256bd3 100644
--- a/core/chains/evm/gas/chain_specific.go
+++ b/core/chains/evm/gas/chain_specific.go
@@ -42,5 +42,12 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy
return false
}
}
+ if chainType == config.ChainWeMix {
+ // WeMix specific transaction types that enables fee delegation.
+ // https://docs.wemix.com/v/en/design/fee-delegation
+ if tx.Type == 0x16 {
+ return false
+ }
+ }
return true
}
diff --git a/core/config/chaintype.go b/core/config/chaintype.go
index c99099ee61..0110f247b7 100644
--- a/core/config/chaintype.go
+++ b/core/config/chaintype.go
@@ -15,18 +15,18 @@ const (
ChainOptimismBedrock ChainType = "optimismBedrock"
ChainXDai ChainType = "xdai"
ChainCelo ChainType = "celo"
+ ChainWeMix ChainType = "wemix"
ChainKroma ChainType = "kroma"
)
var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Join([]string{
string(ChainArbitrum), string(ChainMetis), string(ChainXDai), string(ChainOptimismBedrock), string(ChainCelo),
- string(ChainKroma),
-}, ", "))
+ string(ChainKroma), string(ChainWeMix)}, ", "))
// IsValid returns true if the ChainType value is known or empty.
func (c ChainType) IsValid() bool {
switch c {
- case "", ChainArbitrum, ChainMetis, ChainOptimismBedrock, ChainXDai, ChainCelo, ChainKroma:
+ case "", ChainArbitrum, ChainMetis, ChainOptimismBedrock, ChainXDai, ChainCelo, ChainKroma, ChainWeMix:
return true
}
return false
diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml
index 082bbd6cd1..c0cdfc7a31 100644
--- a/core/config/docs/chains-evm.toml
+++ b/core/config/docs/chains-evm.toml
@@ -14,7 +14,7 @@ BlockBackfillDepth = 10 # Default
# BlockBackfillSkip enables skipping of very long backfills.
BlockBackfillSkip = false # Default
# ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
-# Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma
+# Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma, wemix
ChainType = 'arbitrum' # Example
# FinalityDepth is the number of blocks after which an ethereum transaction is considered "final". Note that the default is automatically set based on chain ID so it should not be necessary to change this under normal operation.
# BlocksConsideredFinal determines how deeply we look back to ensure that transactions are confirmed onto the longest chain
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 59a02f1dcf..cc3fda167d 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -1190,7 +1190,7 @@ func TestConfig_Validate(t *testing.T) {
- 1: 6 errors:
- ChainType: invalid value (Foo): must not be set with this chain id
- Nodes: missing: must have at least one node
- - ChainType: invalid value (Foo): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma or omitted
+ - ChainType: invalid value (Foo): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma, wemix or omitted
- HeadTracker.HistoryDepth: invalid value (30): must be equal to or greater than FinalityDepth
- GasEstimator: 2 errors:
- FeeCapDefault: invalid value (101 wei): must be equal to PriceMax (99 wei) since you are using FixedPrice estimation with gas bumping disabled in EIP1559 mode - PriceMax will be used as the FeeCap for transactions instead of FeeCapDefault
@@ -1199,7 +1199,7 @@ func TestConfig_Validate(t *testing.T) {
- 2: 5 errors:
- ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id
- Nodes: missing: must have at least one node
- - ChainType: invalid value (Arbitrum): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma or omitted
+ - ChainType: invalid value (Arbitrum): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma, wemix or omitted
- FinalityDepth: invalid value (0): must be greater than or equal to 1
- MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1
- 3.Nodes: 5 errors:
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index 3a216e025f..2308fa3035 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -401,7 +401,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight
// care about the block height; we have no way of getting the L1 block
// height anyway
return 0, nil
- case "", config.ChainArbitrum, config.ChainCelo, config.ChainOptimismBedrock, config.ChainXDai, config.ChainKroma:
+ case "", config.ChainArbitrum, config.ChainCelo, config.ChainOptimismBedrock, config.ChainXDai, config.ChainKroma, config.ChainWeMix:
// continue
}
latestBlockHeight := t.getLatestBlockHeight()
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 4b55c804a3..fd8822c162 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -3302,6 +3302,164 @@ GasLimit = 5300000
+WeMix Mainnet (1111)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'wemix'
+FinalityDepth = 1
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '3s'
+LogKeepBlocksDepth = 100000
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '30s'
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '1m0s'
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'BlockHistory'
+PriceDefault = '20 gwei'
+PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+PriceMin = '1 gwei'
+LimitDefault = 500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+BumpMin = '5 gwei'
+BumpPercent = 20
+BumpThreshold = 3
+EIP1559DynamicFees = true
+FeeCapDefault = '100 gwei'
+TipCapDefault = '100 gwei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 8
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[HeadTracker]
+HistoryDepth = 100
+MaxBufferSize = 3
+SamplingInterval = '1s'
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 5
+LeaseDuration = '0s'
+
+[OCR]
+ContractConfirmations = 1
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5300000
+```
+
+
+
+WeMix Testnet (1112)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'wemix'
+FinalityDepth = 1
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '3s'
+LogKeepBlocksDepth = 100000
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '30s'
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '1m0s'
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'BlockHistory'
+PriceDefault = '20 gwei'
+PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+PriceMin = '1 gwei'
+LimitDefault = 500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+BumpMin = '5 gwei'
+BumpPercent = 20
+BumpThreshold = 3
+EIP1559DynamicFees = true
+FeeCapDefault = '100 gwei'
+TipCapDefault = '100 gwei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 8
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[HeadTracker]
+HistoryDepth = 100
+MaxBufferSize = 3
+SamplingInterval = '1s'
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 5
+LeaseDuration = '0s'
+
+[OCR]
+ContractConfirmations = 1
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5300000
+```
+
+
+
Simulated (1337)
```toml
@@ -5074,7 +5232,7 @@ BlockBackfillSkip enables skipping of very long backfills.
ChainType = 'arbitrum' # Example
```
ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
-Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma
+Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma, wemix
### FinalityDepth
```toml
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index 0c36a26081..916971f82d 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -175,6 +175,8 @@ func NewContractDeployer(bcClient blockchain.EVMClient, logger zerolog.Logger) (
return &FantomContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
case *blockchain.KromaClient:
return &KromaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
+ case *blockchain.WeMixClient:
+ return &WeMixContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil
}
return nil, errors.New("unknown blockchain client implementation for contract deployer, register blockchain client in NewContractDeployer")
}
@@ -246,6 +248,10 @@ type KromaContractDeployer struct {
*EthereumContractDeployer
}
+type WeMixContractDeployer struct {
+ *EthereumContractDeployer
+}
+
// NewEthereumContractDeployer returns an instantiated instance of the ETH contract deployer
func NewEthereumContractDeployer(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractDeployer {
return &EthereumContractDeployer{
diff --git a/integration-tests/contracts/contract_loader.go b/integration-tests/contracts/contract_loader.go
index 4dda2d3f0c..cfe7a35467 100644
--- a/integration-tests/contracts/contract_loader.go
+++ b/integration-tests/contracts/contract_loader.go
@@ -64,6 +64,8 @@ func NewContractLoader(bcClient blockchain.EVMClient, logger zerolog.Logger) (Co
return &OptimismContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil
case *blockchain.PolygonZkEvmClient:
return &PolygonZkEvmContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil
+ case *blockchain.WeMixClient:
+ return &WeMixContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil
}
return nil, errors.New("unknown blockchain client implementation for contract Loader, register blockchain client in NewContractLoader")
}
@@ -107,6 +109,11 @@ type PolygonZKEVMContractLoader struct {
*EthereumContractLoader
}
+// WeMixContractLoader wraps for WeMix
+type WeMixContractLoader struct {
+ *EthereumContractLoader
+}
+
// NewEthereumContractLoader returns an instantiated instance of the ETH contract Loader
func NewEthereumContractLoader(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractLoader {
return &EthereumContractLoader{
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 8daa5a29e5..dab3cfa64b 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,7 +22,7 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.4
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
github.com/smartcontractkit/ocr2keepers v0.7.28
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 696e06b6c9..e8ee06ff49 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2376,8 +2376,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.4 h1:IAalKSqRDSGj10zE/JvFrngKGp7mEIVTPh5jTnsaCec=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.4/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65 h1:/iRhwYy5KFsaS9Zo1T64QxAd11HGZB5p/LHI5oVc4BU=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
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 cc308a14d879478933de95c3a153e3cb7cf1a3b2 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Tue, 7 Nov 2023 13:22:56 +0100
Subject: [PATCH 088/327] fix mockery version (#11199)
---
contracts/GNUmakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile
index b477164a49..e41d6422c2 100644
--- a/contracts/GNUmakefile
+++ b/contracts/GNUmakefile
@@ -34,7 +34,7 @@ abigen: ## Build & install abigen.
.PHONY: mockery
mockery: $(mockery) ## Install mockery.
- go install github.com/vektra/mockery/v2@v2.28.1
+ go install github.com/vektra/mockery/v2@v2.35.4
.PHONY: foundry
foundry: ## Install foundry.
From 302eb05d592132309b264e316f443f1ceb81b6c3 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Tue, 7 Nov 2023 13:57:26 +0000
Subject: [PATCH 089/327] [BCF-2632] Adapt median to POC (#11178)
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
core/services/ocr2/delegate.go | 9 +-
.../generic/pipeline_runner_adapter.go | 12 +-
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
plugins/cmd/chainlink-medianpoc/main.go | 42 ++++++
plugins/medianpoc/data_source.go | 79 +++++++++++
plugins/medianpoc/data_source_test.go | 115 ++++++++++++++++
plugins/medianpoc/plugin.go | 126 ++++++++++++++++++
plugins/medianpoc/plugin_test.go | 105 +++++++++++++++
13 files changed, 489 insertions(+), 17 deletions(-)
create mode 100644 plugins/cmd/chainlink-medianpoc/main.go
create mode 100644 plugins/medianpoc/data_source.go
create mode 100644 plugins/medianpoc/data_source_test.go
create mode 100644 plugins/medianpoc/plugin.go
create mode 100644 plugins/medianpoc/plugin_test.go
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 8d731f3f41..7766697c60 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -305,7 +305,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index ebab8c990d..5149148d03 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1466,8 +1466,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de h1:CeVpn5xEdmuEsYE8ss2b7bSq9h3BY4OPvpqXeYIPnHw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 h1:nhhEtc7+u/92CGVE36/mpQCVB8MhrC3ZE3pAFbOvhd4=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 99aa492bc7..75147ca233 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -596,10 +596,11 @@ func (d *Delegate) newServicesGenericPlugin(
}
pluginConfig := types.ReportingPluginServiceConfig{
- PluginName: cconf.PluginName,
- Command: command,
- ProviderType: cconf.ProviderType,
- PluginConfig: string(p.PluginConfig),
+ PluginName: cconf.PluginName,
+ Command: command,
+ ProviderType: cconf.ProviderType,
+ TelemetryType: cconf.TelemetryType,
+ PluginConfig: string(p.PluginConfig),
}
pr := generic.NewPipelineRunnerAdapter(pluginLggr, jb, d.pipelineRunner)
diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
index 6afb35ca75..def33114e8 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
@@ -23,7 +23,7 @@ type PipelineRunnerAdapter struct {
logger logger.Logger
}
-func (p *PipelineRunnerAdapter) ExecuteRun(ctx context.Context, spec string, vars types.Vars, options types.Options) ([]types.TaskResult, error) {
+func (p *PipelineRunnerAdapter) ExecuteRun(ctx context.Context, spec string, vars types.Vars, options types.Options) (types.TaskResults, error) {
s := pipeline.Spec{
DotDagSource: spec,
CreatedAt: time.Now(),
@@ -54,9 +54,13 @@ func (p *PipelineRunnerAdapter) ExecuteRun(ctx context.Context, spec string, var
taskResults[i] = types.TaskResult{
ID: trr.ID.String(),
Type: string(trr.Task.Type()),
- Value: trr.Result.Value,
- Error: trr.Result.Error,
- Index: int(trr.TaskRun.Index),
+ Index: int(trr.Task.OutputIndex()),
+
+ TaskValue: types.TaskValue{
+ Value: trr.Result.Value,
+ Error: trr.Result.Error,
+ IsTerminal: len(trr.Task.Outputs()) == 0,
+ },
}
}
return taskResults, nil
diff --git a/go.mod b/go.mod
index 4d8a929402..a5628eb4b8 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index acd966e8aa..a35e0f32bd 100644
--- a/go.sum
+++ b/go.sum
@@ -1467,8 +1467,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de h1:CeVpn5xEdmuEsYE8ss2b7bSq9h3BY4OPvpqXeYIPnHw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 h1:nhhEtc7+u/92CGVE36/mpQCVB8MhrC3ZE3pAFbOvhd4=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index dab3cfa64b..3c5a5e1f2e 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -388,7 +388,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index e8ee06ff49..cd5cb84a68 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2370,8 +2370,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de h1:CeVpn5xEdmuEsYE8ss2b7bSq9h3BY4OPvpqXeYIPnHw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231102162027-5fdce33763de/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 h1:nhhEtc7+u/92CGVE36/mpQCVB8MhrC3ZE3pAFbOvhd4=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/plugins/cmd/chainlink-medianpoc/main.go b/plugins/cmd/chainlink-medianpoc/main.go
new file mode 100644
index 0000000000..325de6538f
--- /dev/null
+++ b/plugins/cmd/chainlink-medianpoc/main.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "github.com/hashicorp/go-plugin"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop/reportingplugins"
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/plugins/medianpoc"
+)
+
+const (
+ loggerName = "PluginMedianPoc"
+)
+
+func main() {
+ s := loop.MustNewStartedServer(loggerName)
+ defer s.Stop()
+
+ p := medianpoc.NewPlugin(s.Logger)
+ defer s.Logger.ErrorIfFn(p.Close, "Failed to close")
+
+ s.MustRegister(p)
+
+ stop := make(chan struct{})
+ defer close(stop)
+
+ plugin.Serve(&plugin.ServeConfig{
+ HandshakeConfig: reportingplugins.ReportingPluginHandshakeConfig(),
+ Plugins: map[string]plugin.Plugin{
+ reportingplugins.PluginServiceName: &reportingplugins.GRPCService[types.MedianProvider]{
+ PluginServer: p,
+ BrokerConfig: loop.BrokerConfig{
+ Logger: s.Logger,
+ StopCh: stop,
+ GRPCOpts: s.GRPCOpts,
+ },
+ },
+ },
+ GRPCServer: s.GRPCOpts.NewServer,
+ })
+}
diff --git a/plugins/medianpoc/data_source.go b/plugins/medianpoc/data_source.go
new file mode 100644
index 0000000000..7b20f1e5eb
--- /dev/null
+++ b/plugins/medianpoc/data_source.go
@@ -0,0 +1,79 @@
+package medianpoc
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math/big"
+ "sync"
+ "time"
+
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type DataSource struct {
+ pipelineRunner types.PipelineRunnerService
+ spec string
+ lggr logger.Logger
+
+ current bridges.BridgeMetaData
+ mu sync.RWMutex
+}
+
+func (d *DataSource) Observe(ctx context.Context, reportTimestamp ocrtypes.ReportTimestamp) (*big.Int, error) {
+ md, err := bridges.MarshalBridgeMetaData(d.currentAnswer())
+ if err != nil {
+ d.lggr.Warnw("unable to attach metadata for run", "err", err)
+ }
+
+ // NOTE: job metadata is automatically attached by the pipeline runner service
+ vars := types.Vars{
+ Vars: map[string]interface{}{
+ "jobRun": md,
+ },
+ }
+
+ results, err := d.pipelineRunner.ExecuteRun(ctx, d.spec, vars, types.Options{})
+ if err != nil {
+ return nil, err
+ }
+
+ finalResults := results.FinalResults()
+ if len(finalResults) == 0 {
+ return nil, errors.New("pipeline execution failed: not enough results")
+ }
+
+ finalResult := finalResults[0]
+ if finalResult.Error != nil {
+ return nil, fmt.Errorf("pipeline execution failed: %w", finalResult.Error)
+ }
+
+ asDecimal, err := utils.ToDecimal(finalResult.Value)
+ if err != nil {
+ return nil, errors.New("cannot convert observation to decimal")
+ }
+
+ resultAsBigInt := asDecimal.BigInt()
+ d.updateAnswer(resultAsBigInt)
+ return resultAsBigInt, nil
+}
+
+func (d *DataSource) currentAnswer() (*big.Int, *big.Int) {
+ d.mu.RLock()
+ defer d.mu.RUnlock()
+ return d.current.LatestAnswer, d.current.UpdatedAt
+}
+
+func (d *DataSource) updateAnswer(latestAnswer *big.Int) {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ d.current = bridges.BridgeMetaData{
+ LatestAnswer: latestAnswer,
+ UpdatedAt: big.NewInt(time.Now().Unix()),
+ }
+}
diff --git a/plugins/medianpoc/data_source_test.go b/plugins/medianpoc/data_source_test.go
new file mode 100644
index 0000000000..e9a7945cee
--- /dev/null
+++ b/plugins/medianpoc/data_source_test.go
@@ -0,0 +1,115 @@
+package medianpoc
+
+import (
+ "context"
+ "errors"
+ "math/big"
+ "testing"
+
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+)
+
+type mockPipelineRunner struct {
+ results types.TaskResults
+ err error
+ spec string
+ vars types.Vars
+ options types.Options
+}
+
+func (m *mockPipelineRunner) ExecuteRun(ctx context.Context, spec string, vars types.Vars, options types.Options) (types.TaskResults, error) {
+ m.spec = spec
+ m.vars = vars
+ m.options = options
+ return m.results, m.err
+}
+
+func TestDataSource(t *testing.T) {
+ lggr := logger.TestLogger(t)
+ expect := int64(3)
+ pr := &mockPipelineRunner{
+ results: types.TaskResults{
+ {
+ TaskValue: types.TaskValue{
+ Value: expect,
+ Error: nil,
+ IsTerminal: true,
+ },
+ Index: 2,
+ },
+ {
+ TaskValue: types.TaskValue{
+ Value: int(4),
+ Error: nil,
+ IsTerminal: false,
+ },
+ Index: 1,
+ },
+ },
+ }
+ spec := "SPEC"
+ ds := &DataSource{
+ pipelineRunner: pr,
+ spec: spec,
+ lggr: lggr,
+ }
+ res, err := ds.Observe(context.Background(), ocrtypes.ReportTimestamp{})
+ require.NoError(t, err)
+ assert.Equal(t, big.NewInt(expect), res)
+ assert.Equal(t, spec, pr.spec)
+ assert.Equal(t, big.NewInt(expect), ds.current.LatestAnswer)
+}
+
+func TestDataSource_ResultErrors(t *testing.T) {
+ lggr := logger.TestLogger(t)
+ pr := &mockPipelineRunner{
+ results: types.TaskResults{
+ {
+ TaskValue: types.TaskValue{
+ Error: errors.New("something went wrong"),
+ IsTerminal: true,
+ },
+ Index: 0,
+ },
+ },
+ }
+ spec := "SPEC"
+ ds := &DataSource{
+ pipelineRunner: pr,
+ spec: spec,
+ lggr: lggr,
+ }
+ _, err := ds.Observe(context.Background(), ocrtypes.ReportTimestamp{})
+ assert.ErrorContains(t, err, "something went wrong")
+}
+
+func TestDataSource_ResultNotAnInt(t *testing.T) {
+ lggr := logger.TestLogger(t)
+
+ expect := "string-result"
+ pr := &mockPipelineRunner{
+ results: types.TaskResults{
+ {
+ TaskValue: types.TaskValue{
+ Value: expect,
+ IsTerminal: true,
+ },
+ Index: 0,
+ },
+ },
+ }
+ spec := "SPEC"
+ ds := &DataSource{
+ pipelineRunner: pr,
+ spec: spec,
+ lggr: lggr,
+ }
+ _, err := ds.Observe(context.Background(), ocrtypes.ReportTimestamp{})
+ assert.ErrorContains(t, err, "cannot convert observation to decimal")
+}
diff --git a/plugins/medianpoc/plugin.go b/plugins/medianpoc/plugin.go
new file mode 100644
index 0000000000..ceea1eb84f
--- /dev/null
+++ b/plugins/medianpoc/plugin.go
@@ -0,0 +1,126 @@
+package medianpoc
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
+
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop/reportingplugins"
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+func NewPlugin(lggr logger.Logger) *Plugin {
+ return &Plugin{
+ Plugin: loop.Plugin{Logger: lggr},
+ MedianProviderServer: reportingplugins.MedianProviderServer{},
+ stop: make(utils.StopChan),
+ }
+}
+
+type Plugin struct {
+ loop.Plugin
+ stop utils.StopChan
+ reportingplugins.MedianProviderServer
+}
+
+type jsonConfig struct {
+ Pipelines map[string]string `json:"pipelines"`
+}
+
+func (j jsonConfig) defaultPipeline() (string, error) {
+ return j.getPipeline("__DEFAULT_PIPELINE__")
+}
+
+func (j jsonConfig) getPipeline(key string) (string, error) {
+ v, ok := j.Pipelines[key]
+ if ok {
+ return v, nil
+ }
+ return "", fmt.Errorf("no pipeline found for %s", key)
+}
+
+func (p *Plugin) NewReportingPluginFactory(
+ ctx context.Context,
+ config types.ReportingPluginServiceConfig,
+ provider types.MedianProvider,
+ pipelineRunner types.PipelineRunnerService,
+ telemetry types.TelemetryClient,
+ errorLog types.ErrorLog,
+) (types.ReportingPluginFactory, error) {
+ f, err := p.newFactory(ctx, config, provider, pipelineRunner, telemetry, errorLog)
+ if err != nil {
+ return nil, err
+ }
+ s := &reportingPluginFactoryService{lggr: p.Logger, ReportingPluginFactory: f}
+ p.SubService(s)
+ return s, nil
+}
+
+func (p *Plugin) newFactory(ctx context.Context, config types.ReportingPluginServiceConfig, provider types.MedianProvider, pipelineRunner types.PipelineRunnerService, telemetry types.TelemetryClient, errorLog types.ErrorLog) (*median.NumericalMedianFactory, error) {
+ jc := &jsonConfig{}
+ err := json.Unmarshal([]byte(config.PluginConfig), jc)
+ if err != nil {
+ return nil, err
+ }
+
+ dp, err := jc.defaultPipeline()
+ if err != nil {
+ return nil, err
+ }
+ ds := &DataSource{
+ pipelineRunner: pipelineRunner,
+ spec: dp,
+ lggr: p.Logger,
+ }
+
+ jfp, err := jc.getPipeline("juelsPerFeeCoinPipeline")
+ if err != nil {
+ return nil, err
+ }
+ jds := &DataSource{
+ pipelineRunner: pipelineRunner,
+ spec: jfp,
+ lggr: p.Logger,
+ }
+ factory := &median.NumericalMedianFactory{
+ ContractTransmitter: provider.MedianContract(),
+ DataSource: ds,
+ JuelsPerFeeCoinDataSource: jds,
+ Logger: logger.NewOCRWrapper(
+ p.Logger,
+ true,
+ func(msg string) {},
+ ),
+ OnchainConfigCodec: provider.OnchainConfigCodec(),
+ ReportCodec: provider.ReportCodec(),
+ }
+ return factory, nil
+}
+
+type reportingPluginFactoryService struct {
+ services.StateMachine
+ lggr logger.Logger
+ ocrtypes.ReportingPluginFactory
+}
+
+func (r *reportingPluginFactoryService) Name() string { return r.lggr.Name() }
+
+func (r *reportingPluginFactoryService) Start(ctx context.Context) error {
+ return r.StartOnce("ReportingPluginFactory", func() error { return nil })
+}
+
+func (r *reportingPluginFactoryService) Close() error {
+ return r.StopOnce("ReportingPluginFactory", func() error { return nil })
+}
+
+func (r *reportingPluginFactoryService) HealthReport() map[string]error {
+ return map[string]error{r.Name(): r.Healthy()}
+}
diff --git a/plugins/medianpoc/plugin_test.go b/plugins/medianpoc/plugin_test.go
new file mode 100644
index 0000000000..74a0695c6c
--- /dev/null
+++ b/plugins/medianpoc/plugin_test.go
@@ -0,0 +1,105 @@
+package medianpoc
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+type mockErrorLog struct {
+ types.ErrorLog
+}
+
+type mockOffchainConfigDigester struct {
+ ocrtypes.OffchainConfigDigester
+}
+
+type mockContractTransmitter struct {
+ ocrtypes.ContractTransmitter
+}
+
+type mockContractConfigTracker struct {
+ ocrtypes.ContractConfigTracker
+}
+
+type mockReportCodec struct {
+ median.ReportCodec
+}
+
+type mockMedianContract struct {
+ median.MedianContract
+}
+
+type mockOnchainConfigCodec struct {
+ median.OnchainConfigCodec
+}
+
+type provider struct {
+ types.Service
+}
+
+func (p provider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester {
+ return mockOffchainConfigDigester{}
+}
+
+func (p provider) ContractTransmitter() ocrtypes.ContractTransmitter {
+ return mockContractTransmitter{}
+}
+
+func (p provider) ContractConfigTracker() ocrtypes.ContractConfigTracker {
+ return mockContractConfigTracker{}
+}
+
+func (p provider) ReportCodec() median.ReportCodec {
+ return mockReportCodec{}
+}
+
+func (p provider) MedianContract() median.MedianContract {
+ return mockMedianContract{}
+}
+
+func (p provider) OnchainConfigCodec() median.OnchainConfigCodec {
+ return mockOnchainConfigCodec{}
+}
+
+func TestNewPlugin(t *testing.T) {
+ lggr := logger.TestLogger(t)
+ p := NewPlugin(lggr)
+
+ defaultSpec := "default-spec"
+ juelsPerFeeCoinSpec := "jpfc-spec"
+ config := types.ReportingPluginServiceConfig{
+ PluginConfig: fmt.Sprintf(
+ `{"pipelines": {"__DEFAULT_PIPELINE__": "%s", "juelsPerFeeCoinPipeline": "%s"}}`,
+ defaultSpec,
+ juelsPerFeeCoinSpec,
+ ),
+ }
+ pr := &mockPipelineRunner{}
+ prov := provider{}
+
+ f, err := p.newFactory(
+ context.Background(),
+ config,
+ prov,
+ pr,
+ nil,
+ mockErrorLog{},
+ )
+ require.NoError(t, err)
+
+ ds := f.DataSource.(*DataSource)
+ assert.Equal(t, defaultSpec, ds.spec)
+ jpfcDs := f.JuelsPerFeeCoinDataSource.(*DataSource)
+ assert.Equal(t, juelsPerFeeCoinSpec, jpfcDs.spec)
+}
From b1c5a856d71f560883d2cb61d633c47660d41365 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Tue, 7 Nov 2023 14:59:44 +0000
Subject: [PATCH 090/327] [fix] Pull in correct commit sha for pull request
events (#11202)
---
tools/flakeytests/utils.go | 44 +++++++++++++++++++++------------
tools/flakeytests/utils_test.go | 29 ++++++++++++++++++++++
2 files changed, 57 insertions(+), 16 deletions(-)
diff --git a/tools/flakeytests/utils.go b/tools/flakeytests/utils.go
index 18ab43980b..7ead45c858 100644
--- a/tools/flakeytests/utils.go
+++ b/tools/flakeytests/utils.go
@@ -29,23 +29,16 @@ func DigString(mp map[string]interface{}, path []string) (string, error) {
return vs, nil
}
-func GetGithubMetadata(repo string, eventName string, sha string, path string) Context {
- event := map[string]interface{}{}
- if path != "" {
- r, err := os.Open(path)
- if err != nil {
- log.Fatalf("Error reading gh event at path: %s", path)
- }
-
- d, err := io.ReadAll(r)
- if err != nil {
- log.Fatal("Error reading gh event into string")
- }
+func getGithubMetadata(repo string, eventName string, sha string, e io.Reader) Context {
+ d, err := io.ReadAll(e)
+ if err != nil {
+ log.Fatal("Error reading gh event into string")
+ }
- err = json.Unmarshal(d, &event)
- if err != nil {
- log.Fatalf("Error unmarshaling gh event at path: %s", path)
- }
+ event := map[string]interface{}{}
+ err = json.Unmarshal(d, &event)
+ if err != nil {
+ log.Fatalf("Error unmarshaling gh event at path")
}
basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName}
@@ -58,8 +51,27 @@ func GetGithubMetadata(repo string, eventName string, sha string, path string) C
}
basicCtx.PullRequestURL = prURL
+
+ // For pull request events, the $GITHUB_SHA variable doesn't actually
+ // contain the sha for the latest commit, as documented here:
+ // https://stackoverflow.com/a/68068674
+ var newSha string
+ s, err := DigString(event, []string{"pull_request", "head", "sha"})
+ if err == nil {
+ newSha = s
+ }
+
+ basicCtx.CommitSHA = newSha
return *basicCtx
default:
return *basicCtx
}
}
+
+func GetGithubMetadata(repo string, eventName string, sha string, path string) Context {
+ event, err := os.Open(path)
+ if err != nil {
+ log.Fatalf("Error reading gh event at path: %s", path)
+ }
+ return getGithubMetadata(repo, eventName, sha, event)
+}
diff --git a/tools/flakeytests/utils_test.go b/tools/flakeytests/utils_test.go
index d3ef8eb602..17d597c3c0 100644
--- a/tools/flakeytests/utils_test.go
+++ b/tools/flakeytests/utils_test.go
@@ -1,6 +1,8 @@
package flakeytests
import (
+ "fmt"
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -17,3 +19,30 @@ func TestDigString(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "some-url", out)
}
+
+var prEventTemplate = `
+{
+ "pull_request": {
+ "head": {
+ "sha": "%s"
+ },
+ "_links": {
+ "html": {
+ "href": "%s"
+ }
+ }
+ }
+}
+`
+
+func TestGetGithubMetadata(t *testing.T) {
+ repo, eventName, sha, event := "chainlink", "merge_group", "a-sha", `{}`
+ ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event))
+ assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName}, ctx)
+
+ anotherSha, eventName, url := "another-sha", "pull_request", "a-url"
+ event = fmt.Sprintf(prEventTemplate, anotherSha, url)
+ sha = "302eb05d592132309b264e316f443f1ceb81b6c3"
+ ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event))
+ assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url}, ctx)
+}
From 031d9d26c32171152dd29bcad10ccc2e93478a6d Mon Sep 17 00:00:00 2001
From: Cedric
Date: Tue, 7 Nov 2023 15:23:43 +0000
Subject: [PATCH 091/327] [chore] Pin to chainlink-relay@main (#11203)
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 ++--
go.mod | 2 +-
go.sum | 4 ++--
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 7766697c60..9dbe132346 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -305,7 +305,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 5149148d03..7025d38c20 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1466,8 +1466,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 h1:nhhEtc7+u/92CGVE36/mpQCVB8MhrC3ZE3pAFbOvhd4=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/go.mod b/go.mod
index a5628eb4b8..d61b7b6f61 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
diff --git a/go.sum b/go.sum
index a35e0f32bd..f2737ab3ae 100644
--- a/go.sum
+++ b/go.sum
@@ -1467,8 +1467,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 h1:nhhEtc7+u/92CGVE36/mpQCVB8MhrC3ZE3pAFbOvhd4=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 3c5a5e1f2e..6f2809df8c 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -388,7 +388,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index cd5cb84a68..9e1be8b814 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2370,8 +2370,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41 h1:nhhEtc7+u/92CGVE36/mpQCVB8MhrC3ZE3pAFbOvhd4=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231106145532-206ff03d1d41/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From f6f3cfefec2d2a44e23a000c1a6dbd64f40edd2f Mon Sep 17 00:00:00 2001
From: Sam
Date: Tue, 7 Nov 2023 10:25:51 -0500
Subject: [PATCH 092/327] Simple delete queue for mercury transmitter (#11182)
---
.../services/relay/evm/mercury/transmitter.go | 85 +++++++++++++++++--
docs/CHANGELOG.md | 5 ++
2 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go
index 88c3113abc..557210e58a 100644
--- a/core/services/relay/evm/mercury/transmitter.go
+++ b/core/services/relay/evm/mercury/transmitter.go
@@ -33,6 +33,7 @@ import (
var (
maxTransmitQueueSize = 10_000
+ maxDeleteQueueSize = 10_000
transmitTimeout = 5 * time.Second
)
@@ -60,6 +61,24 @@ var (
},
[]string{"feedID"},
)
+ transmitQueueDeleteErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "mercury_transmit_queue_delete_error_count",
+ Help: "Running count of DB errors when trying to delete an item from the queue DB",
+ },
+ []string{"feedID"},
+ )
+ transmitQueueInsertErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "mercury_transmit_queue_insert_error_count",
+ Help: "Running count of DB errors when trying to insert an item into the queue DB",
+ },
+ []string{"feedID"},
+ )
+ transmitQueuePushErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "mercury_transmit_queue_push_error_count",
+ Help: "Running count of DB errors when trying to push an item onto the queue",
+ },
+ []string{"feedID"},
+ )
transmitServerErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "mercury_transmit_server_error_count",
Help: "Number of errored transmissions that failed due to an error returned by the mercury server",
@@ -99,9 +118,14 @@ type mercuryTransmitter struct {
queue *TransmitQueue
wg sync.WaitGroup
- transmitSuccessCount prometheus.Counter
- transmitDuplicateCount prometheus.Counter
- transmitConnectionErrorCount prometheus.Counter
+ deleteQueue chan *pb.TransmitRequest
+
+ transmitSuccessCount prometheus.Counter
+ transmitDuplicateCount prometheus.Counter
+ transmitConnectionErrorCount prometheus.Counter
+ transmitQueueDeleteErrorCount prometheus.Counter
+ transmitQueueInsertErrorCount prometheus.Counter
+ transmitQueuePushErrorCount prometheus.Counter
}
var PayloadTypes = getPayloadTypes()
@@ -139,9 +163,13 @@ func NewTransmitter(lggr logger.Logger, cfgTracker ConfigTracker, rpcClient wsrp
make(chan (struct{})),
nil,
sync.WaitGroup{},
+ make(chan *pb.TransmitRequest, maxDeleteQueueSize),
transmitSuccessCount.WithLabelValues(feedIDHex),
transmitDuplicateCount.WithLabelValues(feedIDHex),
transmitConnectionErrorCount.WithLabelValues(feedIDHex),
+ transmitQueueDeleteErrorCount.WithLabelValues(feedIDHex),
+ transmitQueueInsertErrorCount.WithLabelValues(feedIDHex),
+ transmitQueuePushErrorCount.WithLabelValues(feedIDHex),
}
}
@@ -164,6 +192,8 @@ func (mt *mercuryTransmitter) Start(ctx context.Context) (err error) {
return err
}
mt.wg.Add(1)
+ go mt.runDeleteQueueLoop()
+ mt.wg.Add(1)
go mt.runQueueLoop()
return nil
})
@@ -192,6 +222,46 @@ func (mt *mercuryTransmitter) HealthReport() map[string]error {
return report
}
+func (mt *mercuryTransmitter) runDeleteQueueLoop() {
+ defer mt.wg.Done()
+ runloopCtx, cancel := mt.stopCh.Ctx(context.Background())
+ defer cancel()
+
+ // Exponential backoff for very rarely occurring errors (DB disconnect etc)
+ b := backoff.Backoff{
+ Min: 1 * time.Second,
+ Max: 120 * time.Second,
+ Factor: 2,
+ Jitter: true,
+ }
+
+ for {
+ select {
+ case req := <-mt.deleteQueue:
+ for {
+ if err := mt.persistenceManager.Delete(runloopCtx, req); err != nil {
+ mt.lggr.Errorw("Failed to delete transmit request record", "error", err, "req", req)
+ mt.transmitQueueDeleteErrorCount.Inc()
+ select {
+ case <-time.After(b.Duration()):
+ // Wait a backoff duration before trying to delete again
+ continue
+ case <-mt.stopCh:
+ // abort and return immediately on stop even if items remain in queue
+ return
+ }
+ }
+ break
+ }
+ // success
+ b.Reset()
+ case <-mt.stopCh:
+ // abort and return immediately on stop even if items remain in queue
+ return
+ }
+ }
+}
+
func (mt *mercuryTransmitter) runQueueLoop() {
defer mt.wg.Done()
// Exponential backoff with very short retry interval (since latency is a priority)
@@ -253,9 +323,10 @@ func (mt *mercuryTransmitter) runQueueLoop() {
}
}
- if err := mt.persistenceManager.Delete(runloopCtx, t.Req); err != nil {
- mt.lggr.Errorw("Failed to delete transmit request record", "error", err, "reportCtx", t.ReportCtx)
- return
+ select {
+ case mt.deleteQueue <- t.Req:
+ default:
+ mt.lggr.Criticalw("Delete queue is full", "reportCtx", t.ReportCtx)
}
}
}
@@ -288,9 +359,11 @@ func (mt *mercuryTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.R
mt.lggr.Tracew("Transmit enqueue", "req", req, "report", report, "reportCtx", reportCtx, "signatures", signatures)
if err := mt.persistenceManager.Insert(ctx, req, reportCtx); err != nil {
+ mt.transmitQueueInsertErrorCount.Inc()
return err
}
if ok := mt.queue.Push(req, reportCtx); !ok {
+ mt.transmitQueuePushErrorCount.Inc()
return errors.New("transmit queue is closed")
}
return nil
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index a9f9d080f4..a10f9dd1c6 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added a new, optional WebServer authentication option that supports LDAP as a user identity provider. This enables user login access and user roles to be managed and provisioned via a centralized remote server that supports the LDAP protocol, which can be helpful when running multiple nodes. See the documentation for more information and config setup instructions. There is a new `[WebServer].AuthenticationMethod` config option, when set to `ldap` requires the new `[WebServer.LDAP]` config section to be defined, see the reference `docs/core.toml`.
+- New prom metrics for mercury:
+ `mercury_transmit_queue_delete_error_count`
+ `mercury_transmit_queue_insert_error_count`
+ `mercury_transmit_queue_push_error_count`
+ Nops should consider alerting on these.
### Changed
From 8b4e0f8db32502f928860b928e6102a96db78b07 Mon Sep 17 00:00:00 2001
From: Awbrey Hughlett
Date: Tue, 7 Nov 2023 12:00:25 -0500
Subject: [PATCH 093/327] Update SimulatedBackendClient CallContext (#11164)
* Update SimulatedBackendClient CallContext
The function `CallContext` has different supported contract function calls than
`BatchCallContext` even though the latter is simply a batch version of the
former.
This commit makes the two functions match both in the supported calls, but also
in the validation and execution of those calls.
* Update core/chains/evm/client/simulated_backend_client.go
Use suggestion on default address returned on error.
Co-authored-by: Jordan Krage
* replace errors with panics
* align parameters to documentation, real-world RPCs, and the simulated backend client
* allow different receipt types
* comment on strong typing on result
* remove logic for handling incomplete transaction receipt handling on simulated backend client
* reduce panics in favor of errors
* remove commented code
---------
Co-authored-by: Jordan Krage
---
.../evm/client/simulated_backend_client.go | 503 ++++++++----------
core/chains/evm/txmgr/transmitchecker.go | 2 +-
.../plugins/ocr2keeper/evm21/core/utils.go | 17 +-
3 files changed, 235 insertions(+), 287 deletions(-)
diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go
index 7823908967..d542e98e6e 100644
--- a/core/chains/evm/client/simulated_backend_client.go
+++ b/core/chains/evm/client/simulated_backend_client.go
@@ -25,6 +25,41 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
+func init() {
+ var err error
+
+ balanceOfABI, err = abi.JSON(strings.NewReader(balanceOfABIString))
+ if err != nil {
+ panic(fmt.Errorf("%w: while parsing erc20ABI", err))
+ }
+}
+
+var (
+ balanceOfABIString = `[
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "name": "balance",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ }
+]`
+
+ balanceOfABI abi.ABI
+)
+
// SimulatedBackendClient is an Client implementation using a simulated
// blockchain backend. Note that not all RPC methods are implemented here.
type SimulatedBackendClient struct {
@@ -51,69 +86,6 @@ func (c *SimulatedBackendClient) Dial(context.Context) error {
// other simulated clients might still be using it
func (c *SimulatedBackendClient) Close() {}
-// checkEthCallArgs extracts and verifies the arguments for an eth_call RPC
-func (c *SimulatedBackendClient) checkEthCallArgs(
- args []interface{}) (*CallArgs, *big.Int, error) {
- if len(args) != 2 {
- return nil, nil, fmt.Errorf(
- "should have two arguments after \"eth_call\", got %d", len(args))
- }
- callArgs, ok := args[0].(map[string]interface{})
- if !ok {
- return nil, nil, fmt.Errorf("third arg to SimulatedBackendClient.Call "+
- "must be an eth.CallArgs, got %+#v", args[0])
- }
- blockNumber, err := c.blockNumber(args[1])
- if err != nil {
- return nil, nil, fmt.Errorf("fourth arg to SimulatedBackendClient.Call "+
- "must be the string \"latest\", or a *big.Int, got %#+v", args[1])
- }
-
- // to and from need to map to a common.Address but could come in as a string
- var (
- toAddr common.Address
- frmAddr common.Address
- )
-
- toAddr, err = interfaceToAddress(callArgs["to"])
- if err != nil {
- return nil, nil, err
- }
-
- // from is optional in the standard client; default to 0x when missing
- if value, ok := callArgs["from"]; ok {
- addr, err := interfaceToAddress(value)
- if err != nil {
- return nil, nil, err
- }
-
- frmAddr = addr
- } else {
- frmAddr = common.HexToAddress("0x")
- }
-
- ca := CallArgs{
- To: toAddr,
- From: frmAddr,
- Data: callArgs["data"].(hexutil.Bytes),
- }
-
- return &ca, blockNumber, nil
-}
-
-func interfaceToAddress(value interface{}) (common.Address, error) {
- switch v := value.(type) {
- case common.Address:
- return v, nil
- case string:
- return common.HexToAddress(v), nil
- case *big.Int:
- return common.BigToAddress(v), nil
- default:
- return common.HexToAddress("0x"), fmt.Errorf("unrecognized value type for converting value to common.Address; try string, *big.Int, or common.Address")
- }
-}
-
// CallContext mocks the ethereum client RPC calls used by chainlink, copying the
// return value into result.
// The simulated client avoids the old block error from the simulated backend by
@@ -121,41 +93,16 @@ func interfaceToAddress(value interface{}) (common.Address, error) {
// and will not return an error when an old block is used.
func (c *SimulatedBackendClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
switch method {
+ case "eth_getTransactionReceipt":
+ return c.ethGetTransactionReceipt(ctx, result, args...)
+ case "eth_getBlockByNumber":
+ return c.ethGetBlockByNumber(ctx, result, args...)
case "eth_call":
- var (
- callArgs *CallArgs
- b []byte
- err error
- )
-
- if callArgs, _, err = c.checkEthCallArgs(args); err != nil {
- return err
- }
-
- callMsg := ethereum.CallMsg{From: callArgs.From, To: &callArgs.To, Data: callArgs.Data}
-
- if b, err = c.b.CallContract(ctx, callMsg, nil /* always latest block */); err != nil {
- return fmt.Errorf("%w: while calling contract at address %x with "+
- "data %x", err, callArgs.To, callArgs.Data)
- }
-
- switch r := result.(type) {
- case *hexutil.Bytes:
- *r = append(*r, b...)
-
- if !bytes.Equal(*r, b) {
- return fmt.Errorf("was passed a non-empty array, or failed to copy "+
- "answer. Expected %x = %x", *r, b)
- }
- return nil
- default:
- return fmt.Errorf("first arg to SimulatedBackendClient.Call is an "+
- "unrecognized type: %T; add processing logic for it here", result)
- }
+ return c.ethCall(ctx, result, args...)
+ case "eth_getHeaderByNumber":
+ return c.ethGetHeaderByNumber(ctx, result, args...)
default:
- return fmt.Errorf("second arg to SimulatedBackendClient.Call is an RPC "+
- "API method which has not yet been implemented: %s. Add processing for "+
- "it here", method)
+ return fmt.Errorf("second arg to SimulatedBackendClient.Call is an RPC API method which has not yet been implemented: %s. Add processing for it here", method)
}
}
@@ -175,38 +122,6 @@ func (c *SimulatedBackendClient) currentBlockNumber() *big.Int {
return c.b.Blockchain().CurrentBlock().Number
}
-var balanceOfABIString = `[
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "balance",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- }
-]`
-
-var balanceOfABI abi.ABI
-
-func init() {
- var err error
- balanceOfABI, err = abi.JSON(strings.NewReader(balanceOfABIString))
- if err != nil {
- panic(fmt.Errorf("%w: while parsing erc20ABI", err))
- }
-}
-
func (c *SimulatedBackendClient) TokenBalance(ctx context.Context, address common.Address, contractAddress common.Address) (balance *big.Int, err error) {
callData, err := balanceOfABI.Pack("balanceOf", address)
if err != nil {
@@ -251,13 +166,12 @@ func (c *SimulatedBackendClient) blockNumber(number interface{}) (blockNumber *b
case "earliest":
return big.NewInt(0), nil
case "pending":
- panic("not implemented") // I don't understand the semantics of this.
+ panic("pending block not supported by simulated backend client") // I don't understand the semantics of this.
// return big.NewInt(0).Add(c.currentBlockNumber(), big.NewInt(1)), nil
default:
- blockNumber, err = utils.HexToUint256(n)
+ blockNumber, err := hexutil.DecodeBig(n)
if err != nil {
- return nil, fmt.Errorf("%w: while parsing '%s' as hex-encoded"+
- "block number", err, n)
+ return nil, fmt.Errorf("%w: while parsing '%s' as hex-encoded block number", err, n)
}
return blockNumber, nil
}
@@ -521,114 +435,18 @@ func (c *SimulatedBackendClient) BatchCallContext(ctx context.Context, b []rpc.B
for i, elem := range b {
switch elem.Method {
case "eth_getTransactionReceipt":
- if _, ok := elem.Result.(*evmtypes.Receipt); !ok {
- return fmt.Errorf("SimulatedBackendClient expected return type of *evmtypes.Receipt for eth_getTransactionReceipt, got type %T", elem.Result)
- }
- if len(elem.Args) != 1 {
- return fmt.Errorf("SimulatedBackendClient expected 1 arg, got %d for eth_getTransactionReceipt", len(elem.Args))
- }
- hash, is := elem.Args[0].(common.Hash)
- if !is {
- return fmt.Errorf("SimulatedBackendClient expected arg to be a hash, got: %T", elem.Args[0])
- }
- receipt, err := c.b.TransactionReceipt(ctx, hash)
- if receipt != nil {
- *(b[i].Result.(*evmtypes.Receipt)) = *evmtypes.FromGethReceipt(receipt)
- }
- b[i].Error = err
+ b[i].Error = c.ethGetTransactionReceipt(ctx, b[i].Result, b[i].Args...)
case "eth_getBlockByNumber":
- switch v := elem.Result.(type) {
- case *evmtypes.Head:
- case *evmtypes.Block:
- default:
- return fmt.Errorf("SimulatedBackendClient expected return type of [*evmtypes.Head] or [*evmtypes.Block] for eth_getBlockByNumber, got type %T", v)
- }
- if len(elem.Args) != 2 {
- return fmt.Errorf("SimulatedBackendClient expected 2 args, got %d for eth_getBlockByNumber", len(elem.Args))
- }
- blockNumOrTag, is := elem.Args[0].(string)
- if !is {
- return fmt.Errorf("SimulatedBackendClient expected first arg to be a string for eth_getBlockByNumber, got: %T", elem.Args[0])
- }
- _, is = elem.Args[1].(bool)
- if !is {
- return fmt.Errorf("SimulatedBackendClient expected second arg to be a boolean for eth_getBlockByNumber, got: %T", elem.Args[1])
- }
- header, err := c.fetchHeader(ctx, blockNumOrTag)
- if err != nil {
- return err
- }
- switch res := elem.Result.(type) {
- case *evmtypes.Head:
- res.Number = header.Number.Int64()
- res.Hash = header.Hash()
- res.ParentHash = header.ParentHash
- res.Timestamp = time.Unix(int64(header.Time), 0).UTC()
- case *evmtypes.Block:
- res.Number = header.Number.Int64()
- res.Hash = header.Hash()
- res.ParentHash = header.ParentHash
- res.Timestamp = time.Unix(int64(header.Time), 0).UTC()
- default:
- return fmt.Errorf("SimulatedBackendClient Unexpected Type %T", elem.Result)
- }
- b[i].Error = err
+ b[i].Error = c.ethGetBlockByNumber(ctx, b[i].Result, b[i].Args...)
case "eth_call":
- if len(elem.Args) != 2 {
- return fmt.Errorf("SimulatedBackendClient expected 2 args, got %d for eth_call", len(elem.Args))
- }
-
- _, ok := elem.Result.(*string)
- if !ok {
- return fmt.Errorf("SimulatedBackendClient expected result to be *string for eth_call, got: %T", elem.Result)
- }
-
- params, ok := elem.Args[0].(map[string]interface{})
- if !ok {
- return fmt.Errorf("SimulatedBackendClient expected first arg to be map[string]interface{} for eth_call, got: %T", elem.Args[0])
- }
-
- blockNum, ok := elem.Args[1].(string)
- if !ok {
- return fmt.Errorf("SimulatedBackendClient expected second arg to be a string for eth_call, got: %T", elem.Args[1])
- }
-
- if blockNum != "" {
- if _, ok = new(big.Int).SetString(blockNum, 0); !ok {
- return fmt.Errorf("error while converting block number string: %s to big.Int ", blockNum)
- }
- }
-
- callMsg := toCallMsg(params)
- resp, err := c.b.CallContract(ctx, callMsg, nil)
- *(b[i].Result.(*string)) = hexutil.Encode(resp)
- b[i].Error = err
+ b[i].Error = c.ethCall(ctx, b[i].Result, b[i].Args...)
case "eth_getHeaderByNumber":
- if len(elem.Args) != 1 {
- return fmt.Errorf("SimulatedBackendClient expected 2 args, got %d for eth_getHeaderByNumber", len(elem.Args))
- }
- blockNum, is := elem.Args[0].(string)
- if !is {
- return fmt.Errorf("SimulatedBackendClient expected first arg to be a string for eth_getHeaderByNumber, got: %T", elem.Args[0])
- }
- n, err := hexutil.DecodeBig(blockNum)
- if err != nil {
- return fmt.Errorf("error while converting hex block number %s to big.Int ", blockNum)
- }
- header, err := c.b.HeaderByNumber(ctx, n)
- if err != nil {
- return err
- }
- switch v := elem.Result.(type) {
- case *types.Header:
- b[i].Result = header
- default:
- return fmt.Errorf("SimulatedBackendClient Unexpected Type %T", v)
- }
+ b[i].Error = c.ethGetHeaderByNumber(ctx, b[i].Result, b[i].Args...)
default:
return fmt.Errorf("SimulatedBackendClient got unsupported method %s", elem.Method)
}
}
+
return nil
}
@@ -655,32 +473,175 @@ func (c *SimulatedBackendClient) Commit() common.Hash {
return c.b.Commit()
}
-func toCallMsg(params map[string]interface{}) ethereum.CallMsg {
- var callMsg ethereum.CallMsg
+func (c *SimulatedBackendClient) IsL2() bool {
+ return false
+}
- switch to := params["to"].(type) {
- case string:
- toAddr := common.HexToAddress(to)
- callMsg.To = &toAddr
- case common.Address:
- callMsg.To = &to
- case *common.Address:
- callMsg.To = to
+func (c *SimulatedBackendClient) fetchHeader(ctx context.Context, blockNumOrTag string) (*types.Header, error) {
+ switch blockNumOrTag {
+ case rpc.SafeBlockNumber.String():
+ return c.b.Blockchain().CurrentSafeBlock(), nil
+ case rpc.LatestBlockNumber.String():
+ return c.b.Blockchain().CurrentHeader(), nil
+ case rpc.FinalizedBlockNumber.String():
+ return c.b.Blockchain().CurrentFinalBlock(), nil
default:
- panic("unexpected type of 'to' parameter")
+ blockNum, ok := new(big.Int).SetString(blockNumOrTag, 0)
+ if !ok {
+ return nil, fmt.Errorf("error while converting block number string: %s to big.Int ", blockNumOrTag)
+ }
+ return c.b.HeaderByNumber(ctx, blockNum)
}
+}
- switch from := params["from"].(type) {
- case nil:
- // This parameter is not required so nil is acceptable
- case string:
- callMsg.From = common.HexToAddress(from)
- case common.Address:
- callMsg.From = from
- case *common.Address:
- callMsg.From = *from
+func (c *SimulatedBackendClient) ethGetTransactionReceipt(ctx context.Context, result interface{}, args ...interface{}) error {
+ if len(args) != 1 {
+ return fmt.Errorf("SimulatedBackendClient expected 1 arg, got %d for eth_getTransactionReceipt", len(args))
+ }
+
+ hash, is := args[0].(common.Hash)
+ if !is {
+ return fmt.Errorf("SimulatedBackendClient expected arg to be a hash, got: %T", args[0])
+ }
+
+ receipt, err := c.b.TransactionReceipt(ctx, hash)
+ if err != nil {
+ return err
+ }
+
+ // strongly typing the result here has the consequence of not being flexible in
+ // custom types where a real-world RPC client would allow for custom types with
+ // custom marshalling.
+ switch typed := result.(type) {
+ case *types.Receipt:
+ *typed = *receipt
+ case *evmtypes.Receipt:
+ *typed = *evmtypes.FromGethReceipt(receipt)
+ default:
+ return fmt.Errorf("SimulatedBackendClient expected return type of *evmtypes.Receipt for eth_getTransactionReceipt, got type %T", result)
+ }
+
+ return nil
+}
+
+func (c *SimulatedBackendClient) ethGetBlockByNumber(ctx context.Context, result interface{}, args ...interface{}) error {
+ if len(args) != 2 {
+ return fmt.Errorf("SimulatedBackendClient expected 2 args, got %d for eth_getBlockByNumber", len(args))
+ }
+
+ blockNumOrTag, is := args[0].(string)
+ if !is {
+ return fmt.Errorf("SimulatedBackendClient expected first arg to be a string for eth_getBlockByNumber, got: %T", args[0])
+ }
+
+ _, is = args[1].(bool)
+ if !is {
+ return fmt.Errorf("SimulatedBackendClient expected second arg to be a boolean for eth_getBlockByNumber, got: %T", args[1])
+ }
+
+ header, err := c.fetchHeader(ctx, blockNumOrTag)
+ if err != nil {
+ return err
+ }
+
+ switch res := result.(type) {
+ case *evmtypes.Head:
+ res.Number = header.Number.Int64()
+ res.Hash = header.Hash()
+ res.ParentHash = header.ParentHash
+ res.Timestamp = time.Unix(int64(header.Time), 0).UTC()
+ case *evmtypes.Block:
+ res.Number = header.Number.Int64()
+ res.Hash = header.Hash()
+ res.ParentHash = header.ParentHash
+ res.Timestamp = time.Unix(int64(header.Time), 0).UTC()
+ default:
+ return fmt.Errorf("SimulatedBackendClient Unexpected Type %T", res)
+ }
+
+ return nil
+}
+
+func (c *SimulatedBackendClient) ethCall(ctx context.Context, result interface{}, args ...interface{}) error {
+ if len(args) != 2 {
+ return fmt.Errorf("SimulatedBackendClient expected 2 args, got %d for eth_call", len(args))
+ }
+
+ params, ok := args[0].(map[string]interface{})
+ if !ok {
+ return fmt.Errorf("SimulatedBackendClient expected first arg to be map[string]interface{} for eth_call, got: %T", args[0])
+ }
+
+ if _, err := c.blockNumber(args[1]); err != nil {
+ return fmt.Errorf("SimulatedBackendClient expected second arg to be the string 'latest' or a *big.Int for eth_call, got: %T", args[1])
+ }
+
+ resp, err := c.b.CallContract(ctx, toCallMsg(params), nil /* always latest block on simulated backend */)
+ if err != nil {
+ return err
+ }
+
+ switch typedResult := result.(type) {
+ case *hexutil.Bytes:
+ *typedResult = append(*typedResult, resp...)
+
+ if !bytes.Equal(*typedResult, resp) {
+ return fmt.Errorf("SimulatedBackendClient was passed a non-empty array, or failed to copy answer. Expected %x = %x", *typedResult, resp)
+ }
+ case *string:
+ *typedResult = hexutil.Encode(resp)
default:
- panic("unexpected type of 'from' parameter")
+ return fmt.Errorf("SimulatedBackendClient unexpected type %T", result)
+ }
+
+ return nil
+}
+
+func (c *SimulatedBackendClient) ethGetHeaderByNumber(ctx context.Context, result interface{}, args ...interface{}) error {
+ if len(args) != 1 {
+ return fmt.Errorf("SimulatedBackendClient expected 1 arg, got %d for eth_getHeaderByNumber", len(args))
+ }
+
+ blockNumber, err := c.blockNumber(args[0])
+ if err != nil {
+ return fmt.Errorf("SimulatedBackendClient expected first arg to be a string for eth_getHeaderByNumber: %w", err)
+ }
+
+ header, err := c.b.HeaderByNumber(ctx, blockNumber)
+ if err != nil {
+ return err
+ }
+
+ switch typedResult := result.(type) {
+ case *types.Header:
+ *typedResult = *header
+ default:
+ return fmt.Errorf("SimulatedBackendClient unexpected Type %T", typedResult)
+ }
+
+ return nil
+}
+
+func toCallMsg(params map[string]interface{}) ethereum.CallMsg {
+ var callMsg ethereum.CallMsg
+
+ toAddr, err := interfaceToAddress(params["to"])
+ if err != nil {
+ panic(fmt.Errorf("unexpected 'to' parameter: %s", err))
+ }
+
+ callMsg.To = &toAddr
+
+ // from is optional in the standard client; default to 0x when missing
+ if value, ok := params["from"]; ok {
+ addr, err := interfaceToAddress(value)
+ if err != nil {
+ panic(fmt.Errorf("unexpected 'from' parameter: %s", err))
+ }
+
+ callMsg.From = addr
+ } else {
+ callMsg.From = common.HexToAddress("0x")
}
switch data := params["data"].(type) {
@@ -691,7 +652,7 @@ func toCallMsg(params map[string]interface{}) ethereum.CallMsg {
case []byte:
callMsg.Data = data
default:
- panic("unexpected type of 'data' parameter")
+ panic("unexpected type of 'data' parameter; try hexutil.Bytes, []byte, or nil")
}
if value, ok := params["value"].(*big.Int); ok {
@@ -709,23 +670,23 @@ func toCallMsg(params map[string]interface{}) ethereum.CallMsg {
return callMsg
}
-func (c *SimulatedBackendClient) IsL2() bool {
- return false
-}
+func interfaceToAddress(value interface{}) (common.Address, error) {
+ switch v := value.(type) {
+ case common.Address:
+ return v, nil
+ case string:
+ if ok := common.IsHexAddress(v); !ok {
+ return common.Address{}, fmt.Errorf("string not formatted as a hex encoded evm address")
+ }
-func (c *SimulatedBackendClient) fetchHeader(ctx context.Context, blockNumOrTag string) (*types.Header, error) {
- switch blockNumOrTag {
- case rpc.SafeBlockNumber.String():
- return c.b.Blockchain().CurrentSafeBlock(), nil
- case rpc.LatestBlockNumber.String():
- return c.b.Blockchain().CurrentHeader(), nil
- case rpc.FinalizedBlockNumber.String():
- return c.b.Blockchain().CurrentFinalBlock(), nil
- default:
- blockNum, ok := new(big.Int).SetString(blockNumOrTag, 0)
- if !ok {
- return nil, fmt.Errorf("error while converting block number string: %s to big.Int ", blockNumOrTag)
+ return common.HexToAddress(v), nil
+ case *big.Int:
+ if v.Uint64() > 0 || len(v.Bytes()) > 20 {
+ return common.Address{}, fmt.Errorf("invalid *big.Int; value must be larger than 0 with a byte length <= 20")
}
- return c.b.HeaderByNumber(ctx, blockNum)
+
+ return common.BigToAddress(v), nil
+ default:
+ return common.Address{}, fmt.Errorf("unrecognized value type for converting value to common.Address; use hex encoded string, *big.Int, or common.Address")
}
}
diff --git a/core/chains/evm/txmgr/transmitchecker.go b/core/chains/evm/txmgr/transmitchecker.go
index 4636b70848..eb6edd3f58 100644
--- a/core/chains/evm/txmgr/transmitchecker.go
+++ b/core/chains/evm/txmgr/transmitchecker.go
@@ -217,7 +217,7 @@ func (v *VRFV1Checker) Check(
requestTransactionReceipt := &gethtypes.Receipt{}
batch := []rpc.BatchElem{{
Method: "eth_getBlockByNumber",
- Args: []interface{}{nil},
+ Args: []interface{}{"latest", false},
Result: mostRecentHead,
}, {
Method: "eth_getTransactionReceipt",
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/utils.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/utils.go
index 6a31b938fc..1da28c1ad0 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/utils.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/utils.go
@@ -3,7 +3,6 @@ package core
import (
"context"
"math/big"
- "strings"
"github.com/ethereum/go-ethereum/common"
@@ -14,20 +13,8 @@ import (
// GetTxBlock calls eth_getTransactionReceipt on the eth client to obtain a tx receipt
func GetTxBlock(ctx context.Context, client client.Client, txHash common.Hash) (*big.Int, common.Hash, error) {
receipt := types.Receipt{}
- err := client.CallContext(ctx, &receipt, "eth_getTransactionReceipt", txHash)
- if err != nil {
- if strings.Contains(err.Error(), "not yet been implemented") {
- // workaround for simulated chains
- // Exploratory: fix this properly (e.g. in the simulated backend)
- r, err1 := client.TransactionReceipt(ctx, txHash)
- if err1 != nil {
- return nil, common.Hash{}, err1
- }
- if r.Status != 1 {
- return nil, common.Hash{}, nil
- }
- return r.BlockNumber, r.BlockHash, nil
- }
+
+ if err := client.CallContext(ctx, &receipt, "eth_getTransactionReceipt", txHash); err != nil {
return nil, common.Hash{}, err
}
From 38de9a61c0233b412e9cf8a32011909022da6320 Mon Sep 17 00:00:00 2001
From: FelixFan1992
Date: Tue, 7 Nov 2023 12:08:01 -0500
Subject: [PATCH 094/327] add a TODO for 206 response parsing (#11188)
---
.../plugins/ocr2keeper/evm21/streams_lookup.go | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
index f183e1f6bb..660550afe9 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
@@ -514,20 +514,7 @@ func (r *EvmRegistry) multiFeedsRequest(ctx context.Context, ch chan<- MercuryDa
state = encoding.MercuryFlakyFailure
return fmt.Errorf("%d", resp.StatusCode)
} else if resp.StatusCode == http.StatusPartialContent {
- //var response MercuryV03Response
- //err1 = json.Unmarshal(body, &response)
- //if err1 != nil {
- // lggr.Warnf("at timestamp %s upkeep %s failed to unmarshal body to MercuryV03Response from mercury v0.3: %v", sl.Time.String(), sl.upkeepId.String(), err1)
- // retryable = false
- // state = encoding.MercuryUnmarshalError
- // return err1
- //}
- // in v0.3, if some feeds are not available, the server will only return available feeds, but we need to make sure ALL feeds are retrieved before calling user contract
- // hence, retry in this case. retry will help when we send a very new timestamp and reports are not yet generated
- //var receivedFeeds []string
- //for _, f := range response.Reports {
- // receivedFeeds = append(receivedFeeds, f.FeedID)
- //}
+ // TODO (AUTO-5044): handle response code 206 entirely with errors field parsing
lggr.Warnf("at timestamp %s upkeep %s requested [%s] feeds but mercury v0.3 server returned 206 status, treating it as 404 and retrying", sl.Time.String(), sl.upkeepId.String(), sl.Feeds)
retryable = true
state = encoding.MercuryFlakyFailure
From 4e45a2ac05849703f34a4f5ce4ae539e9cfdcbcf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Friedemann=20F=C3=BCrst?=
<59653747+friedemannf@users.noreply.github.com>
Date: Tue, 7 Nov 2023 18:43:02 +0100
Subject: [PATCH 095/327] Add zkSync support (#11162)
* feat(zksync): add custom error messages
* feat(zksync): add custom chain type to ignore 0x71 transaction type and commit default node config
* fix: add exhaustive case stmt for zkSync ChainType
* docs: regenerate CONFIG.md
* test: add zksync ChainType to expected output
* test: add test for custom zkSync tx type
* fix: reduce HistoryDepth setting to 5
* ci: trigger pipelines
* fix(zksync): also ignore tx type 0xff
* docs(zksync): regenerate CONFIG.md
---
core/chains/evm/client/errors.go | 18 +-
core/chains/evm/client/errors_test.go | 16 ++
.../config/toml/defaults/zkSync_Goerli.toml | 14 ++
.../config/toml/defaults/zkSync_Mainnet.toml | 14 ++
.../evm/gas/block_history_estimator_test.go | 16 ++
core/chains/evm/gas/chain_specific.go | 7 +
core/config/chaintype.go | 5 +-
core/config/docs/chains-evm.toml | 2 +-
core/scripts/common/helpers.go | 5 +
core/services/chainlink/config_test.go | 4 +-
core/services/ocr/contract_tracker.go | 2 +-
docs/CONFIG.md | 160 +++++++++++++++++-
12 files changed, 255 insertions(+), 8 deletions(-)
create mode 100644 core/chains/evm/config/toml/defaults/zkSync_Goerli.toml
create mode 100644 core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml
diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go
index 0d177455e3..4cb505dc9e 100644
--- a/core/chains/evm/client/errors.go
+++ b/core/chains/evm/client/errors.go
@@ -207,7 +207,23 @@ var harmony = ClientErrors{
Fatal: harmonyFatal,
}
-var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo}
+var zkSync = ClientErrors{
+ NonceTooLow: regexp.MustCompile(`(?:: |^)nonce too low\..+actual: \d*$`),
+ NonceTooHigh: regexp.MustCompile(`(?:: |^)nonce too high\..+actual: \d*$`),
+ TerminallyUnderpriced: regexp.MustCompile(`(?:: |^)max fee per gas less than block base fee$`),
+ InsufficientEth: regexp.MustCompile(`(?:: |^)(?:insufficient balance for transfer$|insufficient funds for gas + value)`),
+ TxFeeExceedsCap: regexp.MustCompile(`(?:: |^)max priority fee per gas higher than max fee per gas$`),
+ // intrinsic gas too low - gas limit less than 14700
+ // Not enough gas for transaction validation - gas limit less than L2 fee
+ // Failed to pay the fee to the operator - gas limit less than L2+L1 fee
+ // Error function_selector = 0x, data = 0x - contract call with gas limit of 0
+ // can't start a transaction from a non-account - trying to send from an invalid address, e.g. estimating a contract -> contract tx
+ // max fee per gas higher than 2^64-1 - uint64 overflow
+ // oversized data - data too large
+ Fatal: regexp.MustCompile(`(?:: |^)(?:exceeds block gas limit|intrinsic gas too low|Not enough gas for transaction validation|Failed to pay the fee to the operator|Error function_selector = 0x, data = 0x|invalid sender. can't start a transaction from a non-account|max(?: priority)? fee per (?:gas|pubdata byte) higher than 2\^64-1|oversized data. max: \d+; actual: \d+)$`),
+}
+
+var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync}
func (s *SendError) is(errorType int) bool {
if s == nil || s.err == nil {
diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go
index a5a3cc15eb..ad8079824a 100644
--- a/core/chains/evm/client/errors_test.go
+++ b/core/chains/evm/client/errors_test.go
@@ -40,6 +40,7 @@ func Test_Eth_Errors(t *testing.T) {
{"call failed: nonce too low: address 0x0499BEA33347cb62D79A9C0b1EDA01d8d329894c current nonce (5833) > tx nonce (5511)", true, "Avalanche"},
{"call failed: OldNonce", true, "Nethermind"},
{"call failed: OldNonce, Current nonce: 22, nonce of rejected tx: 17", true, "Nethermind"},
+ {"nonce too low. allowed nonce range: 427 - 447, actual: 426", true, "zkSync"},
}
for _, test := range tests {
@@ -60,6 +61,7 @@ func Test_Eth_Errors(t *testing.T) {
{"nonce too high: address 0x336394A3219e71D9d9bd18201d34E95C1Bb7122C, tx: 8089 state: 8090", true, "Arbitrum"},
{"nonce too high", true, "Geth"},
{"nonce too high", true, "Erigon"},
+ {"nonce too high. allowed nonce range: 427 - 477, actual: 527", true, "zkSync"},
}
for _, test := range tests {
@@ -152,6 +154,7 @@ func Test_Eth_Errors(t *testing.T) {
{"FeeTooLowToCompete", true, "Nethermind"},
{"transaction underpriced", true, "Klaytn"},
{"intrinsic gas too low", true, "Klaytn"},
+ {"max fee per gas less than block base fee", true, "zkSync"},
}
for _, test := range tests {
@@ -194,6 +197,8 @@ func Test_Eth_Errors(t *testing.T) {
{"call failed: InsufficientFunds, Account balance: 4740799397601480913, cumulative cost: 22019342038993800000", true, "Nethermind"},
{"insufficient funds", true, "Klaytn"},
{"insufficient funds for gas * price + value + gatewayFee", true, "celo"},
+ {"insufficient balance for transfer", true, "zkSync"},
+ {"insufficient funds for gas + value. balance: 42719769622667482000, fee: 48098250000000, value: 42719769622667482000", true, "celo"},
}
for _, test := range tests {
err = evmclient.NewSendErrorS(test.message)
@@ -213,6 +218,7 @@ func Test_Eth_Errors(t *testing.T) {
{"invalid gas fee cap", true, "Klaytn"},
{"max fee per gas higher than max priority fee per gas", true, "Klaytn"},
{"tx fee (1.10 of currency celo) exceeds the configured cap (1.00 celo)", true, "celo"},
+ {"max priority fee per gas higher than max fee per gas", true, "zkSync"},
}
for _, test := range tests {
err = evmclient.NewSendErrorS(test.message)
@@ -329,6 +335,16 @@ func Test_Eth_Errors_Fatal(t *testing.T) {
{"`to` address of transaction in blacklist", true, "Harmony"},
{"`from` address of transaction in blacklist", true, "Harmony"},
{"staking message does not match directive message", true, "Harmony"},
+
+ {"intrinsic gas too low", true, "zkSync"},
+ {"failed to validate the transaction. reason: Validation revert: Account validation error: Not enough gas for transaction validation", true, "zkSync"},
+ {"failed to validate the transaction. reason: Validation revert: Failed to pay for the transaction: Failed to pay the fee to the operator", true, "zkSync"},
+ {"failed to validate the transaction. reason: Validation revert: Account validation error: Error function_selector = 0x, data = 0x", true, "zkSync"},
+ {"invalid sender. can't start a transaction from a non-account", true, "zkSync"},
+ {"Failed to serialize transaction: max fee per gas higher than 2^64-1", true, "zkSync"},
+ {"Failed to serialize transaction: max fee per pubdata byte higher than 2^64-1", true, "zkSync"},
+ {"Failed to serialize transaction: max priority fee per gas higher than 2^64-1", true, "zkSync"},
+ {"Failed to serialize transaction: oversized data. max: 1000000; actual: 1000000", true, "zkSync"},
}
for _, test := range tests {
diff --git a/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml b/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml
new file mode 100644
index 0000000000..04529a41b8
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml
@@ -0,0 +1,14 @@
+ChainID = '280'
+ChainType = 'zksync'
+FinalityDepth = 1
+LogPollInterval = '5s'
+MinIncomingConfirmations = 1
+NoNewHeadsThreshold = '1m'
+
+[GasEstimator]
+LimitDefault = 3_500_000
+PriceMax = 18446744073709551615
+PriceMin = 0
+
+[HeadTracker]
+HistoryDepth = 5
diff --git a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml
new file mode 100644
index 0000000000..d7808edd15
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml
@@ -0,0 +1,14 @@
+ChainID = '324'
+ChainType = 'zksync'
+FinalityDepth = 1
+LogPollInterval = '5s'
+MinIncomingConfirmations = 1
+NoNewHeadsThreshold = '1m'
+
+[GasEstimator]
+LimitDefault = 3_500_000
+PriceMax = 18446744073709551615
+PriceMin = 0
+
+[HeadTracker]
+HistoryDepth = 5
diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go
index decb68dbe9..c8b193c443 100644
--- a/core/chains/evm/gas/block_history_estimator_test.go
+++ b/core/chains/evm/gas/block_history_estimator_test.go
@@ -23,6 +23,7 @@ import (
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
@@ -1348,6 +1349,21 @@ func TestBlockHistoryEstimator_IsUsable(t *testing.T) {
assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
assert.Equal(t, true, bhe.IsUsable(tx2, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
})
+
+ t.Run("returns false if transaction is of type 0x71 or 0xff only on zkSync", func(t *testing.T) {
+ cfg.ChainTypeF = string(config.ChainZkSync)
+ tx := evmtypes.Transaction{Type: 0x71, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()}
+ assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
+
+ tx.Type = 0x02
+ assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
+
+ tx.Type = 0xff
+ assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
+
+ cfg.ChainTypeF = ""
+ assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.TestLogger(t)))
+ })
}
func TestBlockHistoryEstimator_EffectiveTipCap(t *testing.T) {
diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go
index 5c0b256bd3..4f0d2e6b2f 100644
--- a/core/chains/evm/gas/chain_specific.go
+++ b/core/chains/evm/gas/chain_specific.go
@@ -49,5 +49,12 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy
return false
}
}
+ if chainType == config.ChainZkSync {
+ // zKSync specific type for contract deployment & priority transactions
+ // https://era.zksync.io/docs/reference/concepts/transactions.html#eip-712-0x71
+ if tx.Type == 0x71 || tx.Type == 0xff {
+ return false
+ }
+ }
return true
}
diff --git a/core/config/chaintype.go b/core/config/chaintype.go
index 0110f247b7..21fb8cd297 100644
--- a/core/config/chaintype.go
+++ b/core/config/chaintype.go
@@ -17,16 +17,17 @@ const (
ChainCelo ChainType = "celo"
ChainWeMix ChainType = "wemix"
ChainKroma ChainType = "kroma"
+ ChainZkSync ChainType = "zksync"
)
var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Join([]string{
string(ChainArbitrum), string(ChainMetis), string(ChainXDai), string(ChainOptimismBedrock), string(ChainCelo),
- string(ChainKroma), string(ChainWeMix)}, ", "))
+ string(ChainKroma), string(ChainWeMix), string(ChainZkSync)}, ", "))
// IsValid returns true if the ChainType value is known or empty.
func (c ChainType) IsValid() bool {
switch c {
- case "", ChainArbitrum, ChainMetis, ChainOptimismBedrock, ChainXDai, ChainCelo, ChainKroma, ChainWeMix:
+ case "", ChainArbitrum, ChainMetis, ChainOptimismBedrock, ChainXDai, ChainCelo, ChainKroma, ChainWeMix, ChainZkSync:
return true
}
return false
diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml
index c0cdfc7a31..381ab794d6 100644
--- a/core/config/docs/chains-evm.toml
+++ b/core/config/docs/chains-evm.toml
@@ -14,7 +14,7 @@ BlockBackfillDepth = 10 # Default
# BlockBackfillSkip enables skipping of very long backfills.
BlockBackfillSkip = false # Default
# ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
-# Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma, wemix
+# Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma, wemix, zksync
ChainType = 'arbitrum' # Example
# FinalityDepth is the number of blocks after which an ethereum transaction is considered "final". Note that the default is automatically set based on chain ID so it should not be necessary to change this under normal operation.
# BlocksConsideredFinal determines how deeply we look back to ensure that transactions are confirmed onto the longest chain
diff --git a/core/scripts/common/helpers.go b/core/scripts/common/helpers.go
index d03dcec097..c141e8a29c 100644
--- a/core/scripts/common/helpers.go
+++ b/core/scripts/common/helpers.go
@@ -219,6 +219,11 @@ func explorerLinkPrefix(chainID int64) (prefix string) {
case 8453:
prefix = "https://basescan.org"
+ case 280: // zkSync Goerli testnet
+ prefix = "https://goerli.explorer.zksync.io"
+ case 324: // zkSync mainnet
+ prefix = "https://explorer.zksync.io"
+
default: // Unknown chain, return prefix as-is
prefix = ""
}
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index cc3fda167d..34fcc4bbe9 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -1190,7 +1190,7 @@ func TestConfig_Validate(t *testing.T) {
- 1: 6 errors:
- ChainType: invalid value (Foo): must not be set with this chain id
- Nodes: missing: must have at least one node
- - ChainType: invalid value (Foo): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma, wemix or omitted
+ - ChainType: invalid value (Foo): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma, wemix, zksync or omitted
- HeadTracker.HistoryDepth: invalid value (30): must be equal to or greater than FinalityDepth
- GasEstimator: 2 errors:
- FeeCapDefault: invalid value (101 wei): must be equal to PriceMax (99 wei) since you are using FixedPrice estimation with gas bumping disabled in EIP1559 mode - PriceMax will be used as the FeeCap for transactions instead of FeeCapDefault
@@ -1199,7 +1199,7 @@ func TestConfig_Validate(t *testing.T) {
- 2: 5 errors:
- ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id
- Nodes: missing: must have at least one node
- - ChainType: invalid value (Arbitrum): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma, wemix or omitted
+ - ChainType: invalid value (Arbitrum): must be one of arbitrum, metis, xdai, optimismBedrock, celo, kroma, wemix, zksync or omitted
- FinalityDepth: invalid value (0): must be greater than or equal to 1
- MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1
- 3.Nodes: 5 errors:
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index 2308fa3035..f49e556d4e 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -401,7 +401,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight
// care about the block height; we have no way of getting the L1 block
// height anyway
return 0, nil
- case "", config.ChainArbitrum, config.ChainCelo, config.ChainOptimismBedrock, config.ChainXDai, config.ChainKroma, config.ChainWeMix:
+ case "", config.ChainArbitrum, config.ChainCelo, config.ChainOptimismBedrock, config.ChainXDai, config.ChainKroma, config.ChainWeMix, config.ChainZkSync:
// continue
}
latestBlockHeight := t.getLatestBlockHeight()
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index fd8822c162..1eb9cd5023 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -2986,6 +2986,164 @@ GasLimit = 5300000
+zkSync Goerli (280)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'zksync'
+FinalityDepth = 1
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '5s'
+LogKeepBlocksDepth = 100000
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '1m0s'
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '1m0s'
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'BlockHistory'
+PriceDefault = '20 gwei'
+PriceMax = '18.446744073709551615 ether'
+PriceMin = '0'
+LimitDefault = 3500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+BumpMin = '5 gwei'
+BumpPercent = 20
+BumpThreshold = 3
+EIP1559DynamicFees = false
+FeeCapDefault = '100 gwei'
+TipCapDefault = '1 wei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 8
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[HeadTracker]
+HistoryDepth = 5
+MaxBufferSize = 3
+SamplingInterval = '1s'
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 5
+LeaseDuration = '0s'
+
+[OCR]
+ContractConfirmations = 4
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5300000
+```
+
+
+
+zkSync Mainnet (324)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'zksync'
+FinalityDepth = 1
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '5s'
+LogKeepBlocksDepth = 100000
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '1m0s'
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '1m0s'
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'BlockHistory'
+PriceDefault = '20 gwei'
+PriceMax = '18.446744073709551615 ether'
+PriceMin = '0'
+LimitDefault = 3500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+BumpMin = '5 gwei'
+BumpPercent = 20
+BumpThreshold = 3
+EIP1559DynamicFees = false
+FeeCapDefault = '100 gwei'
+TipCapDefault = '1 wei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 8
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[HeadTracker]
+HistoryDepth = 5
+MaxBufferSize = 3
+SamplingInterval = '1s'
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 5
+LeaseDuration = '0s'
+
+[OCR]
+ContractConfirmations = 4
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5300000
+```
+
+
+
Optimism Goerli (420)
```toml
@@ -5232,7 +5390,7 @@ BlockBackfillSkip enables skipping of very long backfills.
ChainType = 'arbitrum' # Example
```
ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
-Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma, wemix
+Available types: arbitrum, metis, optimismBedrock, xdai, celo, kroma, wemix, zksync
### FinalityDepth
```toml
From e4b50ff0516e172782d96ea96fcefd876742c5ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Friedemann=20F=C3=BCrst?=
<59653747+friedemannf@users.noreply.github.com>
Date: Tue, 7 Nov 2023 19:45:37 +0100
Subject: [PATCH 096/327] Bump libocr =>
13e0202ae8d7e38245422aa93af82010390f9e9b (#11212)
* Bump libocr to 13e0202ae8d7e38245422aa93af82010390f9e9b
* go mod tidy
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 ++--
go.mod | 2 +-
go.sum | 4 ++--
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 9dbe132346..b72d07978f 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -21,7 +21,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
- github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
+ github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 7025d38c20..b1e62010ab 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1476,8 +1476,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88
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=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
-github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545 h1:qOsw2ETQD/Sb/W2xuYn2KPWjvvsWA0C+l19rWFq8iNg=
-github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
+github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XOYSxpFmFqlhr5IaEh1uQ1F6CewJ30D/U/P34c=
+github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
diff --git a/go.mod b/go.mod
index d61b7b6f61..cd0fb0fab4 100644
--- a/go.mod
+++ b/go.mod
@@ -69,7 +69,7 @@ require (
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
- github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
+ github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
diff --git a/go.sum b/go.sum
index f2737ab3ae..fb97398f84 100644
--- a/go.sum
+++ b/go.sum
@@ -1477,8 +1477,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88
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=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
-github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545 h1:qOsw2ETQD/Sb/W2xuYn2KPWjvvsWA0C+l19rWFq8iNg=
-github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
+github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XOYSxpFmFqlhr5IaEh1uQ1F6CewJ30D/U/P34c=
+github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 6f2809df8c..eb542651b5 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -24,7 +24,7 @@ require (
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
- github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545
+ github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 9e1be8b814..ecafa2706e 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2382,8 +2382,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88
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=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
-github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545 h1:qOsw2ETQD/Sb/W2xuYn2KPWjvvsWA0C+l19rWFq8iNg=
-github.com/smartcontractkit/libocr v0.0.0-20231020123319-d255366a6545/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
+github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XOYSxpFmFqlhr5IaEh1uQ1F6CewJ30D/U/P34c=
+github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
From f5d6797e4f0af7a7d8e634b31daaecc098548c8c Mon Sep 17 00:00:00 2001
From: Tate
Date: Tue, 7 Nov 2023 12:21:32 -0700
Subject: [PATCH 097/327] [TT-681] Remove usages of github.com/pkg/errors
(#11213)
---
integration-tests/actions/actions.go | 18 +--
integration-tests/actions/actions_local.go | 5 +-
.../actions/automation_ocr_helpers_local.go | 3 +-
.../actions/ocr_helpers_local.go | 9 +-
integration-tests/actions/vrfv1/actions.go | 9 +-
.../actions/vrfv2_actions/vrfv2_steps.go | 27 ++--
.../actions/vrfv2plus/vrfv2plus_steps.go | 127 +++++++++---------
.../contracts/ethereum_contracts.go | 5 +-
.../contracts/ethereum_ocr2vrf_contracts.go | 23 ++--
integration-tests/docker/test_env/cl_node.go | 5 +-
.../docker/test_env/cl_node_cluster.go | 5 +-
integration-tests/docker/test_env/test_env.go | 12 +-
.../docker/test_env/test_env_builder.go | 8 +-
integration-tests/go.mod | 4 +-
integration-tests/go.sum | 4 +-
integration-tests/load/functions/config.go | 13 +-
integration-tests/load/functions/gateway.go | 20 +--
integration-tests/load/functions/setup.go | 24 ++--
integration-tests/load/vrfv2/config.go | 11 +-
integration-tests/load/vrfv2/vu.go | 7 +-
integration-tests/load/vrfv2plus/config.go | 11 +-
integration-tests/reorg/reorg_confirmer.go | 8 +-
integration-tests/smoke/ocr2_test.go | 49 -------
integration-tests/smoke/ocr2vrf_test.go | 5 +-
integration-tests/smoke/vrfv2plus_test.go | 8 +-
25 files changed, 189 insertions(+), 231 deletions(-)
diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go
index b45b8e83b9..bacf5a9dbf 100644
--- a/integration-tests/actions/actions.go
+++ b/integration-tests/actions/actions.go
@@ -5,16 +5,16 @@ import (
"crypto/ecdsa"
"encoding/json"
"fmt"
- "github.com/ethereum/go-ethereum/crypto"
"math/big"
"strings"
"testing"
+ "github.com/ethereum/go-ethereum/crypto"
+
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"go.uber.org/zap/zapcore"
@@ -262,7 +262,7 @@ func TeardownSuite(
) error {
l := logging.GetTestLogger(t)
if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel); err != nil {
- return errors.Wrap(err, "Error dumping environment logs, leaving environment running for manual retrieval")
+ return fmt.Errorf("Error dumping environment logs, leaving environment running for manual retrieval, err: %w", err)
}
// Delete all jobs to stop depleting the funds
err := DeleteAllJobs(chainlinkNodes)
@@ -330,16 +330,16 @@ func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error {
}
jobs, _, err := node.ReadJobs()
if err != nil {
- return errors.Wrap(err, "error reading jobs from chainlink node")
+ return fmt.Errorf("error reading jobs from chainlink node, err: %w", err)
}
for _, maps := range jobs.Data {
if _, ok := maps["id"]; !ok {
- return errors.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data)
+ return fmt.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data)
}
id := maps["id"].(string)
_, err := node.DeleteJob(id)
if err != nil {
- return errors.Wrap(err, "error deleting job from chainlink node")
+ return fmt.Errorf("error deleting job from chainlink node, err: %w", err)
}
}
}
@@ -350,7 +350,7 @@ func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error {
// all from a remote, k8s style environment
func ReturnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient blockchain.EVMClient) error {
if blockchainClient == nil {
- return errors.New("blockchain client is nil, unable to return funds from chainlink nodes")
+ return fmt.Errorf("blockchain client is nil, unable to return funds from chainlink nodes")
}
log.Info().Msg("Attempting to return Chainlink node funds to default network wallets")
if blockchainClient.NetworkSimulated() {
@@ -416,7 +416,7 @@ func UpgradeChainlinkNodeVersions(
nodes ...*client.ChainlinkK8sClient,
) error {
if newImage == "" && newVersion == "" {
- return errors.New("unable to upgrade node version, found empty image and version, must provide either a new image or a new version")
+ return fmt.Errorf("unable to upgrade node version, found empty image and version, must provide either a new image or a new version")
}
for _, node := range nodes {
if err := node.UpgradeVersion(testEnvironment, newImage, newVersion); err != nil {
@@ -455,7 +455,7 @@ func GenerateWallet() (common.Address, error) {
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
- return common.Address{}, errors.New("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
+ return common.Address{}, fmt.Errorf("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}
return crypto.PubkeyToAddress(*publicKeyECDSA), nil
}
diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go
index b65bac43bb..f5d2a9035f 100644
--- a/integration-tests/actions/actions_local.go
+++ b/integration-tests/actions/actions_local.go
@@ -2,7 +2,8 @@
package actions
import (
- "github.com/pkg/errors"
+ "fmt"
+
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
)
@@ -13,7 +14,7 @@ func UpgradeChainlinkNodeVersionsLocal(
nodes ...*test_env.ClNode,
) error {
if newImage == "" && newVersion == "" {
- return errors.New("unable to upgrade node version, found empty image and version, must provide either a new image or a new version")
+ return fmt.Errorf("unable to upgrade node version, found empty image and version, must provide either a new image or a new version")
}
for _, node := range nodes {
if err := node.UpgradeVersion(node.NodeConfig, newImage, newVersion); err != nil {
diff --git a/integration-tests/actions/automation_ocr_helpers_local.go b/integration-tests/actions/automation_ocr_helpers_local.go
index ccc2eea99d..f541594c4d 100644
--- a/integration-tests/actions/automation_ocr_helpers_local.go
+++ b/integration-tests/actions/automation_ocr_helpers_local.go
@@ -8,7 +8,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/lib/pq"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
@@ -187,7 +186,7 @@ func CreateOCRKeeperJobsLocal(
} else if registryVersion == ethereum.RegistryVersion_2_0 {
contractVersion = "v2.0"
} else {
- return errors.New("v2.0 and v2.1 are the only supported versions")
+ return fmt.Errorf("v2.0 and v2.1 are the only supported versions")
}
bootstrapSpec := &client.OCR2TaskJobSpec{
diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go
index 8bb4e83479..5836ee7945 100644
--- a/integration-tests/actions/ocr_helpers_local.go
+++ b/integration-tests/actions/ocr_helpers_local.go
@@ -9,7 +9,6 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
@@ -280,7 +279,7 @@ func TrackForwarderLocal(
chainID := chainClient.GetChainID()
_, _, err := node.TrackForwarder(chainID, authorizedForwarder)
if err != nil {
- return errors.Wrap(err, "failed to track forwarder")
+ return fmt.Errorf("failed to track forwarder, err: %w", err)
}
logger.Info().Str("NodeURL", node.Config.URL).
Str("ForwarderAddress", authorizedForwarder.Hex()).
@@ -305,7 +304,7 @@ func DeployOCRContractsForwarderFlowLocal(
contracts.DefaultOffChainAggregatorOptions(),
)
if err != nil {
- return nil, errors.Wrap(err, "failed to deploy offchain aggregator")
+ return nil, fmt.Errorf("failed to deploy offchain aggregator, err: %w", err)
}
ocrInstances = append(ocrInstances, ocrInstance)
err = client.WaitForEvents()
@@ -329,7 +328,7 @@ func DeployOCRContractsForwarderFlowLocal(
for _, ocrInstance := range ocrInstances {
err := ocrInstance.SetPayees(transmitters, payees)
if err != nil {
- return nil, errors.Wrap(err, "failed to set OCR payees")
+ return nil, fmt.Errorf("failed to set OCR payees, err: %w", err)
}
if err := client.WaitForEvents(); err != nil {
return nil, err
@@ -348,7 +347,7 @@ func DeployOCRContractsForwarderFlowLocal(
forwarderAddresses,
)
if err != nil {
- return nil, errors.Wrap(err, "failed to set on-chain config")
+ return nil, fmt.Errorf("failed to set on-chain config, err: %w", err)
}
if err = client.WaitForEvents(); err != nil {
return nil, err
diff --git a/integration-tests/actions/vrfv1/actions.go b/integration-tests/actions/vrfv1/actions.go
index 68d3e584ce..f8d7190709 100644
--- a/integration-tests/actions/vrfv1/actions.go
+++ b/integration-tests/actions/vrfv1/actions.go
@@ -1,7 +1,8 @@
package vrfv1
import (
- "github.com/pkg/errors"
+ "fmt"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
)
@@ -21,15 +22,15 @@ type Contracts struct {
func DeployVRFContracts(cd contracts.ContractDeployer, bc blockchain.EVMClient, lt contracts.LinkToken) (*Contracts, error) {
bhs, err := cd.DeployBlockhashStore()
if err != nil {
- return nil, errors.Wrap(err, ErrDeployBHSV1)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployBHSV1, err)
}
coordinator, err := cd.DeployVRFCoordinator(lt.Address(), bhs.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrDeployVRFCootrinatorV1)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployVRFCootrinatorV1, err)
}
consumer, err := cd.DeployVRFConsumer(lt.Address(), coordinator.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrDeployVRFConsumerV1)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployVRFConsumerV1, err)
}
if err := bc.WaitForEvents(); err != nil {
return nil, err
diff --git a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go
index 24ac217a33..a832d020b0 100644
--- a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go
+++ b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go
@@ -6,7 +6,6 @@ import (
"math/big"
"github.com/google/uuid"
- "github.com/pkg/errors"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -43,15 +42,15 @@ func DeployVRFV2Contracts(
) (*VRFV2Contracts, error) {
bhs, err := contractDeployer.DeployBlockhashStore()
if err != nil {
- return nil, errors.Wrap(err, ErrDeployBlockHashStore)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployBlockHashStore, err)
}
coordinator, err := contractDeployer.DeployVRFCoordinatorV2(linkTokenContract.Address(), bhs.Address(), linkEthFeedContract.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrDeployCoordinator)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployCoordinator, err)
}
loadTestConsumer, err := contractDeployer.DeployVRFv2LoadTestConsumer(coordinator.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrAdvancedConsumer)
+ return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err)
}
err = chainClient.WaitForEvents()
if err != nil {
@@ -70,7 +69,7 @@ func CreateVRFV2Jobs(
for _, chainlinkNode := range chainlinkNodes {
vrfKey, err := chainlinkNode.MustCreateVRFKey()
if err != nil {
- return nil, errors.Wrap(err, ErrCreatingVRFv2Key)
+ return nil, fmt.Errorf("%s, err %w", ErrCreatingVRFv2Key, err)
}
pubKeyCompressed := vrfKey.Data.ID
jobUUID := uuid.New()
@@ -79,11 +78,11 @@ func CreateVRFV2Jobs(
}
ost, err := os.String()
if err != nil {
- return nil, errors.Wrap(err, ErrParseJob)
+ return nil, fmt.Errorf("%s, err %w", ErrParseJob, err)
}
nativeTokenPrimaryKeyAddress, err := chainlinkNode.PrimaryEthAddress()
if err != nil {
- return nil, errors.Wrap(err, ErrNodePrimaryKey)
+ return nil, fmt.Errorf("%s, err %w", ErrNodePrimaryKey, err)
}
job, err := chainlinkNode.MustCreateJob(&client.VRFV2JobSpec{
Name: fmt.Sprintf("vrf-%s", jobUUID),
@@ -97,15 +96,15 @@ func CreateVRFV2Jobs(
BatchFulfillmentEnabled: false,
})
if err != nil {
- return nil, errors.Wrap(err, ErrCreatingVRFv2Job)
+ return nil, fmt.Errorf("%s, err %w", ErrCreatingVRFv2Job, err)
}
provingKey, err := VRFV2RegisterProvingKey(vrfKey, nativeTokenPrimaryKeyAddress, coordinator)
if err != nil {
- return nil, errors.Wrap(err, ErrCreatingProvingKey)
+ return nil, fmt.Errorf("%s, err %w", ErrCreatingProvingKey, err)
}
keyHash, err := coordinator.HashOfKey(context.Background(), provingKey)
if err != nil {
- return nil, errors.Wrap(err, ErrCreatingProvingKeyHash)
+ return nil, fmt.Errorf("%s, err %w", ErrCreatingProvingKeyHash, err)
}
ji := VRFV2JobInfo{
Job: job,
@@ -125,14 +124,14 @@ func VRFV2RegisterProvingKey(
) (VRFV2EncodedProvingKey, error) {
provingKey, err := actions.EncodeOnChainVRFProvingKey(*vrfKey)
if err != nil {
- return VRFV2EncodedProvingKey{}, errors.Wrap(err, ErrEncodingProvingKey)
+ return VRFV2EncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrEncodingProvingKey, err)
}
err = coordinator.RegisterProvingKey(
oracleAddress,
provingKey,
)
if err != nil {
- return VRFV2EncodedProvingKey{}, errors.Wrap(err, ErrRegisterProvingKey)
+ return VRFV2EncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrRegisterProvingKey, err)
}
return provingKey, nil
}
@@ -140,11 +139,11 @@ func VRFV2RegisterProvingKey(
func FundVRFCoordinatorV2Subscription(linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2, chainClient blockchain.EVMClient, subscriptionID uint64, linkFundingAmount *big.Int) error {
encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint64"}]`, subscriptionID)
if err != nil {
- return errors.Wrap(err, ErrABIEncodingFunding)
+ return fmt.Errorf("%s, err %w", ErrABIEncodingFunding, err)
}
_, err = linkToken.TransferAndCall(coordinator.Address(), big.NewInt(0).Mul(linkFundingAmount, big.NewInt(1e18)), encodedSubId)
if err != nil {
- return errors.Wrap(err, ErrSendingLinkToken)
+ return fmt.Errorf("%s, err %w", ErrSendingLinkToken, err)
}
return chainClient.WaitForEvents()
}
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index e720116c21..e964623fb2 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -3,17 +3,17 @@ package vrfv2plus
import (
"context"
"fmt"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
"math/big"
"sync"
"time"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils"
+
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
@@ -71,19 +71,19 @@ func DeployVRFV2_5Contracts(
) (*VRFV2_5Contracts, error) {
bhs, err := contractDeployer.DeployBlockhashStore()
if err != nil {
- return nil, errors.Wrap(err, ErrDeployBlockHashStore)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployBlockHashStore, err)
}
err = chainClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
coordinator, err := contractDeployer.DeployVRFCoordinatorV2_5(bhs.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrDeployCoordinator)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployCoordinator, err)
}
err = chainClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
consumers, err := DeployVRFV2PlusConsumers(contractDeployer, coordinator, consumerContractsAmount)
if err != nil {
@@ -91,7 +91,7 @@ func DeployVRFV2_5Contracts(
}
err = chainClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
return &VRFV2_5Contracts{coordinator, bhs, consumers}, nil
}
@@ -107,11 +107,11 @@ func DeployVRFV2PlusDirectFundingContracts(
vrfv2PlusWrapper, err := contractDeployer.DeployVRFV2PlusWrapper(linkTokenAddress, linkEthFeedAddress, coordinator.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrDeployWrapper)
+ return nil, fmt.Errorf("%s, err %w", ErrDeployWrapper, err)
}
err = chainClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
consumers, err := DeployVRFV2PlusWrapperConsumers(contractDeployer, linkTokenAddress, vrfv2PlusWrapper, consumerContractsAmount)
@@ -120,7 +120,7 @@ func DeployVRFV2PlusDirectFundingContracts(
}
err = chainClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
return &VRFV2PlusWrapperContracts{vrfv2PlusWrapper, consumers}, nil
}
@@ -130,7 +130,7 @@ func DeployVRFV2PlusConsumers(contractDeployer contracts.ContractDeployer, coord
for i := 1; i <= consumerContractsAmount; i++ {
loadTestConsumer, err := contractDeployer.DeployVRFv2PlusLoadTestConsumer(coordinator.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrAdvancedConsumer)
+ return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err)
}
consumers = append(consumers, loadTestConsumer)
}
@@ -142,7 +142,7 @@ func DeployVRFV2PlusWrapperConsumers(contractDeployer contracts.ContractDeployer
for i := 1; i <= consumerContractsAmount; i++ {
loadTestConsumer, err := contractDeployer.DeployVRFV2PlusWrapperLoadTestConsumer(linkTokenAddress, vrfV2PlusWrapper.Address())
if err != nil {
- return nil, errors.Wrap(err, ErrAdvancedConsumer)
+ return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err)
}
consumers = append(consumers, loadTestConsumer)
}
@@ -163,7 +163,7 @@ func CreateVRFV2PlusJob(
}
ost, err := os.String()
if err != nil {
- return nil, errors.Wrap(err, ErrParseJob)
+ return nil, fmt.Errorf("%s, err %w", ErrParseJob, err)
}
job, err := chainlinkNode.MustCreateJob(&client.VRFV2PlusJobSpec{
@@ -178,7 +178,7 @@ func CreateVRFV2PlusJob(
BatchFulfillmentEnabled: false,
})
if err != nil {
- return nil, errors.Wrap(err, ErrCreatingVRFv2PlusJob)
+ return nil, fmt.Errorf("%s, err %w", ErrCreatingVRFv2PlusJob, err)
}
return job, nil
@@ -191,14 +191,14 @@ func VRFV2_5RegisterProvingKey(
) (VRFV2PlusEncodedProvingKey, error) {
provingKey, err := actions.EncodeOnChainVRFProvingKey(*vrfKey)
if err != nil {
- return VRFV2PlusEncodedProvingKey{}, errors.Wrap(err, ErrEncodingProvingKey)
+ return VRFV2PlusEncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrEncodingProvingKey, err)
}
err = coordinator.RegisterProvingKey(
oracleAddress,
provingKey,
)
if err != nil {
- return VRFV2PlusEncodedProvingKey{}, errors.Wrap(err, ErrRegisterProvingKey)
+ return VRFV2PlusEncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrRegisterProvingKey, err)
}
return provingKey, nil
}
@@ -210,14 +210,14 @@ func VRFV2PlusUpgradedVersionRegisterProvingKey(
) (VRFV2PlusEncodedProvingKey, error) {
provingKey, err := actions.EncodeOnChainVRFProvingKey(*vrfKey)
if err != nil {
- return VRFV2PlusEncodedProvingKey{}, errors.Wrap(err, ErrEncodingProvingKey)
+ return VRFV2PlusEncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrEncodingProvingKey, err)
}
err = coordinator.RegisterProvingKey(
oracleAddress,
provingKey,
)
if err != nil {
- return VRFV2PlusEncodedProvingKey{}, errors.Wrap(err, ErrRegisterProvingKey)
+ return VRFV2PlusEncodedProvingKey{}, fmt.Errorf("%s, err %w", ErrRegisterProvingKey, err)
}
return provingKey, nil
}
@@ -231,11 +231,11 @@ func FundVRFCoordinatorV2_5Subscription(
) error {
encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint256"}]`, subscriptionID)
if err != nil {
- return errors.Wrap(err, ErrABIEncodingFunding)
+ return fmt.Errorf("%s, err %w", ErrABIEncodingFunding, err)
}
_, err = linkToken.TransferAndCall(coordinator.Address(), linkFundingAmountJuels, encodedSubId)
if err != nil {
- return errors.Wrap(err, ErrSendingLinkToken)
+ return fmt.Errorf("%s, err %w", ErrSendingLinkToken, err)
}
return chainClient.WaitForEvents()
}
@@ -255,7 +255,7 @@ func SetupVRFV2_5Environment(
l.Info().Msg("Deploying VRFV2 Plus contracts")
vrfv2_5Contracts, err := DeployVRFV2_5Contracts(env.ContractDeployer, env.EVMClient, numberOfConsumers)
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrDeployVRFV2_5Contracts)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrDeployVRFV2_5Contracts, err)
}
l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Setting Coordinator Config")
@@ -271,17 +271,17 @@ func SetupVRFV2_5Environment(
},
)
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrSetVRFCoordinatorConfig)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrSetVRFCoordinatorConfig, err)
}
l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Setting Link and ETH/LINK feed")
err = vrfv2_5Contracts.Coordinator.SetLINKAndLINKNativeFeed(linkToken.Address(), mockNativeLINKFeed.Address())
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrSetLinkNativeLinkFeed)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrSetLinkNativeLinkFeed, err)
}
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Int("Number of Subs to create", numberOfSubToCreate).Msg("Creating and funding subscriptions, adding consumers")
subIDs, err := CreateFundSubsAndAddConsumers(
@@ -295,25 +295,25 @@ func SetupVRFV2_5Environment(
l.Info().Str("Node URL", env.ClCluster.NodeAPIs()[0].URL()).Msg("Creating VRF Key on the Node")
vrfKey, err := env.ClCluster.NodeAPIs()[0].MustCreateVRFKey()
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrCreatingVRFv2PlusKey)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrCreatingVRFv2PlusKey, err)
}
pubKeyCompressed := vrfKey.Data.ID
l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Registering Proving Key")
provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, registerProvingKeyAgainstAddress, vrfv2_5Contracts.Coordinator)
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrRegisteringProvingKey)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrRegisteringProvingKey, err)
}
keyHash, err := vrfv2_5Contracts.Coordinator.HashOfKey(context.Background(), provingKey)
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrCreatingProvingKeyHash)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrCreatingProvingKeyHash, err)
}
chainID := env.EVMClient.GetChainID()
nativeTokenPrimaryKeyAddress, err := env.ClCluster.NodeAPIs()[0].PrimaryEthAddress()
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrNodePrimaryKey)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrNodePrimaryKey, err)
}
l.Info().Msg("Creating VRFV2 Plus Job")
@@ -326,7 +326,7 @@ func SetupVRFV2_5Environment(
vrfv2PlusConfig.MinimumConfirmations,
)
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrCreateVRFV2PlusJobs)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrCreateVRFV2PlusJobs, err)
}
// this part is here because VRFv2 can work with only a specific key
@@ -334,7 +334,7 @@ func SetupVRFV2_5Environment(
// Key = '...'
addr, err := env.ClCluster.Nodes[0].API.PrimaryEthAddress()
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrGetPrimaryKey)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrGetPrimaryKey, err)
}
nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig,
node.WithVRFv2EVMEstimator(addr),
@@ -342,7 +342,7 @@ func SetupVRFV2_5Environment(
l.Info().Msg("Restarting Node with new sending key PriceMax configuration")
err = env.ClCluster.Nodes[0].Restart(nodeConfig)
if err != nil {
- return nil, nil, nil, errors.Wrap(err, ErrRestartCLNode)
+ return nil, nil, nil, fmt.Errorf("%s, err %w", ErrRestartCLNode, err)
}
vrfv2PlusKeyData := VRFV2PlusKeyData{
@@ -391,7 +391,7 @@ func CreateFundSubsAndAddConsumers(
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
return subIDs, nil
}
@@ -409,7 +409,7 @@ func CreateSubsAndFund(
}
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
err = FundSubscriptions(env, vrfv2PlusConfig, linkToken, coordinator, subs)
if err != nil {
@@ -443,7 +443,7 @@ func AddConsumersToSubs(
for _, consumer := range consumers {
err := coordinator.AddConsumer(subID, consumer.Address())
if err != nil {
- return errors.Wrap(err, ErrAddConsumerToSub)
+ return fmt.Errorf("%s, err %w", ErrAddConsumerToSub, err)
}
}
}
@@ -475,7 +475,7 @@ func SetupVRFV2PlusWrapperEnvironment(
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
err = wrapperContracts.VRFV2PlusWrapper.SetConfig(
vrfv2PlusConfig.WrapperGasOverhead,
@@ -494,7 +494,7 @@ func SetupVRFV2PlusWrapperEnvironment(
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
//fund sub
@@ -505,7 +505,7 @@ func SetupVRFV2PlusWrapperEnvironment(
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
err = FundSubscriptions(env, vrfv2PlusConfig, linkToken, coordinator, []*big.Int{wrapperSubID})
@@ -523,7 +523,7 @@ func SetupVRFV2PlusWrapperEnvironment(
}
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
//fund consumer with Eth
@@ -533,21 +533,24 @@ func SetupVRFV2PlusWrapperEnvironment(
}
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
return wrapperContracts, wrapperSubID, nil
}
func CreateSubAndFindSubID(env *test_env.CLClusterTestEnv, coordinator contracts.VRFCoordinatorV2_5) (*big.Int, error) {
tx, err := coordinator.CreateSubscription()
if err != nil {
- return nil, errors.Wrap(err, ErrCreateVRFSubscription)
+ return nil, fmt.Errorf("%s, err %w", ErrCreateVRFSubscription, err)
}
err = env.EVMClient.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, ErrWaitTXsComplete)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
receipt, err := env.EVMClient.GetTxReceipt(tx.Hash())
+ if err != nil {
+ return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
+ }
//SubscriptionsCreated Log should be emitted with the subscription ID
subID := receipt.Logs[0].Topics[1].Big()
@@ -555,7 +558,7 @@ func CreateSubAndFindSubID(env *test_env.CLClusterTestEnv, coordinator contracts
//verify that the subscription was created
_, err = coordinator.FindSubscriptionID(subID)
if err != nil {
- return nil, errors.Wrap(err, ErrFindSubID)
+ return nil, fmt.Errorf("%s, err %w", ErrFindSubID, err)
}
return subID, nil
@@ -564,11 +567,11 @@ func CreateSubAndFindSubID(env *test_env.CLClusterTestEnv, coordinator contracts
func GetUpgradedCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion) (linkTotalBalance *big.Int, nativeTokenTotalBalance *big.Int, err error) {
linkTotalBalance, err = coordinator.GetLinkTotalBalance(context.Background())
if err != nil {
- return nil, nil, errors.Wrap(err, ErrLinkTotalBalance)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrLinkTotalBalance, err)
}
nativeTokenTotalBalance, err = coordinator.GetNativeTokenTotalBalance(context.Background())
if err != nil {
- return nil, nil, errors.Wrap(err, ErrNativeTokenBalance)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrNativeTokenBalance, err)
}
return
}
@@ -576,11 +579,11 @@ func GetUpgradedCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2Pl
func GetCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2_5) (linkTotalBalance *big.Int, nativeTokenTotalBalance *big.Int, err error) {
linkTotalBalance, err = coordinator.GetLinkTotalBalance(context.Background())
if err != nil {
- return nil, nil, errors.Wrap(err, ErrLinkTotalBalance)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrLinkTotalBalance, err)
}
nativeTokenTotalBalance, err = coordinator.GetNativeTokenTotalBalance(context.Background())
if err != nil {
- return nil, nil, errors.Wrap(err, ErrNativeTokenBalance)
+ return nil, nil, fmt.Errorf("%s, err %w", ErrNativeTokenBalance, err)
}
return
}
@@ -600,18 +603,18 @@ func FundSubscriptions(
amountWei,
)
if err != nil {
- return errors.Wrap(err, ErrFundSubWithNativeToken)
+ return fmt.Errorf("%s, err %w", ErrFundSubWithNativeToken, err)
}
//Link Billing
amountJuels := utils.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountLink))
err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, amountJuels)
if err != nil {
- return errors.Wrap(err, ErrFundSubWithLinkToken)
+ return fmt.Errorf("%s, err %w", ErrFundSubWithLinkToken, err)
}
}
err := env.EVMClient.WaitForEvents()
if err != nil {
- return errors.Wrap(err, ErrWaitTXsComplete)
+ return fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err)
}
return nil
}
@@ -638,7 +641,7 @@ func RequestRandomnessAndWaitForFulfillment(
randomnessRequestCountPerRequest,
)
if err != nil {
- return nil, errors.Wrap(err, ErrRequestRandomness)
+ return nil, fmt.Errorf("%s, err %w", ErrRequestRandomness, err)
}
return WaitForRequestAndFulfillmentEvents(
@@ -672,7 +675,7 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded(
vrfv2PlusConfig.RandomnessRequestCountPerRequest,
)
if err != nil {
- return nil, errors.Wrap(err, ErrRequestRandomness)
+ return nil, fmt.Errorf("%s, err %w", ErrRequestRandomness, err)
}
randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent(
@@ -682,7 +685,7 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded(
time.Minute*1,
)
if err != nil {
- return nil, errors.Wrap(err, ErrWaitRandomWordsRequestedEvent)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitRandomWordsRequestedEvent, err)
}
LogRandomnessRequestedEventUpgraded(l, coordinator, randomWordsRequestedEvent)
@@ -693,7 +696,7 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded(
time.Minute*2,
)
if err != nil {
- return nil, errors.Wrap(err, ErrWaitRandomWordsFulfilledEvent)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitRandomWordsFulfilledEvent, err)
}
LogRandomWordsFulfilledEventUpgraded(l, coordinator, randomWordsFulfilledEvent)
@@ -719,7 +722,7 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment(
vrfv2PlusConfig.RandomnessRequestCountPerRequest,
)
if err != nil {
- return nil, errors.Wrap(err, ErrRequestRandomnessDirectFundingNativePayment)
+ return nil, fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingNativePayment, err)
}
} else {
_, err := consumer.RequestRandomness(
@@ -729,12 +732,12 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment(
vrfv2PlusConfig.RandomnessRequestCountPerRequest,
)
if err != nil {
- return nil, errors.Wrap(err, ErrRequestRandomnessDirectFundingLinkPayment)
+ return nil, fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingLinkPayment, err)
}
}
wrapperAddress, err := consumer.GetWrapper(context.Background())
if err != nil {
- return nil, errors.Wrap(err, "error getting wrapper address")
+ return nil, fmt.Errorf("error getting wrapper address, err: %w", err)
}
return WaitForRequestAndFulfillmentEvents(
wrapperAddress.String(),
@@ -763,7 +766,7 @@ func WaitForRequestAndFulfillmentEvents(
time.Minute*1,
)
if err != nil {
- return nil, errors.Wrap(err, ErrWaitRandomWordsRequestedEvent)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitRandomWordsRequestedEvent, err)
}
LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, isNativeBilling)
@@ -774,7 +777,7 @@ func WaitForRequestAndFulfillmentEvents(
randomWordsFulfilledEventTimeout,
)
if err != nil {
- return nil, errors.Wrap(err, ErrWaitRandomWordsFulfilledEvent)
+ return nil, fmt.Errorf("%s, err %w", ErrWaitRandomWordsFulfilledEvent, err)
}
LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent, isNativeBilling)
@@ -817,7 +820,7 @@ func WaitForRequestCountEqualToFulfilmentCount(consumer contracts.VRFv2PlusLoadT
func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator contracts.VRFCoordinatorV2_5, l zerolog.Logger) error {
linkTotalBalance, err := coordinator.GetLinkTotalBalance(context.Background())
if err != nil {
- return errors.Wrap(err, "Error getting LINK total balance")
+ return fmt.Errorf("Error getting LINK total balance, err: %w", err)
}
defaultWallet := client.GetDefaultWallet().Address()
l.Info().
@@ -829,11 +832,11 @@ func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator co
linkTotalBalance,
)
if err != nil {
- return errors.Wrap(err, "Error withdrawing LINK from coordinator to default wallet")
+ return fmt.Errorf("Error withdrawing LINK from coordinator to default wallet, err: %w", err)
}
nativeTotalBalance, err := coordinator.GetNativeTokenTotalBalance(context.Background())
if err != nil {
- return errors.Wrap(err, "Error getting NATIVE total balance")
+ return fmt.Errorf("Error getting NATIVE total balance, err: %w", err)
}
l.Info().
Str("Native Token amount", linkTotalBalance.String()).
@@ -844,7 +847,7 @@ func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator co
nativeTotalBalance,
)
if err != nil {
- return errors.Wrap(err, "Error withdrawing NATIVE from coordinator to default wallet")
+ return fmt.Errorf("Error withdrawing NATIVE from coordinator to default wallet, err: %w", err)
}
return nil
}
diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go
index 5b3a93fe0c..cde6e325f2 100644
--- a/integration-tests/contracts/ethereum_contracts.go
+++ b/integration-tests/contracts/ethereum_contracts.go
@@ -13,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
@@ -2162,11 +2161,11 @@ func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string
topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]}
topicOneHash := []common.Hash{r.Logs[0].Topics[1:][0]}
if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil {
- return 0, errors.Wrap(err, "failed to decode topic value")
+ return 0, fmt.Errorf("failed to decode topic value, err: %w", err)
}
e.l.Info().Interface("NewTopicsDecoded", topicsMap).Send()
if topicsMap["subscriptionId"] == 0 {
- return 0, errors.New("failed to decode subscription ID after creation")
+ return 0, fmt.Errorf("failed to decode subscription ID after creation")
}
return topicsMap["subscriptionId"].(uint64), nil
}
diff --git a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go
index e8149b2125..cb52d1941a 100644
--- a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go
+++ b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go
@@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
@@ -230,7 +229,7 @@ func (dkgContract *EthereumDKG) WaitForTransmittedEvent(timeout time.Duration) (
case err = <-subscription.Err():
return nil, err
case <-time.After(timeout):
- return nil, errors.New("timeout waiting for DKGTransmitted event")
+ return nil, fmt.Errorf("timeout waiting for DKGTransmitted event")
case transmittedEvent := <-transmittedEventsChannel:
return transmittedEvent, nil
}
@@ -250,7 +249,7 @@ func (dkgContract *EthereumDKG) WaitForConfigSetEvent(timeout time.Duration) (*d
case err = <-subscription.Err():
return nil, err
case <-time.After(timeout):
- return nil, errors.New("timeout waiting for DKGConfigSet event")
+ return nil, fmt.Errorf("timeout waiting for DKGConfigSet event")
case configSetEvent := <-configSetEventsChannel:
return configSetEvent, nil
}
@@ -451,7 +450,7 @@ func (consumer *EthereumVRFBeaconConsumer) RequestRandomness(
) (*types.Receipt, error) {
opts, err := consumer.client.TransactionOpts(consumer.client.GetDefaultWallet())
if err != nil {
- return nil, errors.Wrap(err, "TransactionOpts failed")
+ return nil, fmt.Errorf("TransactionOpts failed, err: %w", err)
}
tx, err := consumer.vrfBeaconConsumer.TestRequestRandomness(
opts,
@@ -460,20 +459,20 @@ func (consumer *EthereumVRFBeaconConsumer) RequestRandomness(
confirmationDelayArg,
)
if err != nil {
- return nil, errors.Wrap(err, "TestRequestRandomness failed")
+ return nil, fmt.Errorf("TestRequestRandomness failed, err: %w", err)
}
err = consumer.client.ProcessTransaction(tx)
if err != nil {
- return nil, errors.Wrap(err, "ProcessTransaction failed")
+ return nil, fmt.Errorf("ProcessTransaction failed, err: %w", err)
}
err = consumer.client.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, "WaitForEvents failed")
+ return nil, fmt.Errorf("WaitForEvents failed, err: %w", err)
}
receipt, err := consumer.client.GetTxReceipt(tx.Hash())
if err != nil {
- return nil, errors.Wrap(err, "GetTxReceipt failed")
+ return nil, fmt.Errorf("GetTxReceipt failed, err: %w", err)
}
log.Info().Interface("Sub ID", subID).
Interface("Number of Words", numWords).
@@ -526,20 +525,20 @@ func (consumer *EthereumVRFBeaconConsumer) RequestRandomnessFulfillment(
arguments,
)
if err != nil {
- return nil, errors.Wrap(err, "TestRequestRandomnessFulfillment failed")
+ return nil, fmt.Errorf("TestRequestRandomnessFulfillment failed, err: %w", err)
}
err = consumer.client.ProcessTransaction(tx)
if err != nil {
- return nil, errors.Wrap(err, "ProcessTransaction failed")
+ return nil, fmt.Errorf("ProcessTransaction failed, err: %w", err)
}
err = consumer.client.WaitForEvents()
if err != nil {
- return nil, errors.Wrap(err, "WaitForEvents failed")
+ return nil, fmt.Errorf("WaitForEvents failed, err: %w", err)
}
receipt, err := consumer.client.GetTxReceipt(tx.Hash())
if err != nil {
- return nil, errors.Wrap(err, "GetTxReceipt failed")
+ return nil, fmt.Errorf("GetTxReceipt failed, err: %w", err)
}
log.Info().Interface("Sub ID", subID).
Interface("Number of Words", numWords).
diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go
index 4c40e64121..4de3d27d75 100644
--- a/integration-tests/docker/test_env/cl_node.go
+++ b/integration-tests/docker/test_env/cl_node.go
@@ -17,7 +17,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/pelletier/go-toml/v2"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
tc "github.com/testcontainers/testcontainers-go"
@@ -282,7 +281,7 @@ func (n *ClNode) StartContainer() error {
Logger: l,
})
if err != nil {
- return errors.Wrap(err, ErrStartCLNodeContainer)
+ return fmt.Errorf("%s err: %w", ErrStartCLNodeContainer, err)
}
if n.lw != nil {
if err := n.lw.ConnectContainer(context.Background(), container, "cl-node", true); err != nil {
@@ -314,7 +313,7 @@ func (n *ClNode) StartContainer() error {
},
n.l)
if err != nil {
- return errors.Wrap(err, ErrConnectNodeClient)
+ return fmt.Errorf("%s err: %w", ErrConnectNodeClient, err)
}
clClient.Config.InternalIP = n.ContainerName
n.Container = container
diff --git a/integration-tests/docker/test_env/cl_node_cluster.go b/integration-tests/docker/test_env/cl_node_cluster.go
index 5ae90bb982..08122b5744 100644
--- a/integration-tests/docker/test_env/cl_node_cluster.go
+++ b/integration-tests/docker/test_env/cl_node_cluster.go
@@ -1,8 +1,9 @@
package test_env
import (
+ "fmt"
+
"github.com/ethereum/go-ethereum/common"
- "github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/smartcontractkit/chainlink/integration-tests/client"
@@ -61,7 +62,7 @@ func (c *ClCluster) NodeCSAKeys() ([]string, error) {
for _, n := range c.Nodes {
csaKeys, err := n.GetNodeCSAKeys()
if err != nil {
- return nil, errors.Wrap(err, ErrGetNodeCSAKeys)
+ return nil, fmt.Errorf("%s, err: %w", ErrGetNodeCSAKeys, err)
}
keys = append(keys, csaKeys.Data[0].ID)
}
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index e067e46090..a6495bed54 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -8,11 +8,11 @@ import (
"math/big"
"os"
"path/filepath"
+ "runtime/debug"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/keystore"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
tc "github.com/testcontainers/testcontainers-go"
@@ -114,7 +114,7 @@ func (te *CLClusterTestEnv) StartPrivateChain() error {
for _, chain := range te.PrivateChain {
primaryNode := chain.GetPrimaryNode()
if primaryNode == nil {
- return errors.WithStack(fmt.Errorf("primary node is nil in PrivateChain interface"))
+ return fmt.Errorf("primary node is nil in PrivateChain interface, stack: %s", string(debug.Stack()))
}
err := primaryNode.Start()
if err != nil {
@@ -164,7 +164,7 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i
func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error {
for _, cl := range te.ClCluster.Nodes {
if err := cl.Fund(te.EVMClient, amount); err != nil {
- return errors.Wrap(err, ErrFundCLNode)
+ return fmt.Errorf("%s, err: %w", ErrFundCLNode, err)
}
time.Sleep(5 * time.Second)
}
@@ -181,10 +181,10 @@ func (te *CLClusterTestEnv) Terminate() error {
func (te *CLClusterTestEnv) Cleanup() error {
te.l.Info().Msg("Cleaning up test environment")
if te.t == nil {
- return errors.New("cannot cleanup test environment without a testing.T")
+ return fmt.Errorf("cannot cleanup test environment without a testing.T")
}
if te.ClCluster == nil || len(te.ClCluster.Nodes) == 0 {
- return errors.New("chainlink nodes are nil, unable cleanup chainlink nodes")
+ return fmt.Errorf("chainlink nodes are nil, unable cleanup chainlink nodes")
}
// TODO: This is an imperfect and temporary solution, see TT-590 for a more sustainable solution
@@ -196,7 +196,7 @@ func (te *CLClusterTestEnv) Cleanup() error {
}
if te.EVMClient == nil {
- return errors.New("evm client is nil, unable to return funds from chainlink nodes during cleanup")
+ return fmt.Errorf("evm client is nil, unable to return funds from chainlink nodes during cleanup")
} else if te.EVMClient.NetworkSimulated() {
te.l.Info().
Str("Network Name", te.EVMClient.GetNetworkName()).
diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go
index c07ea76262..9f64ab64c9 100644
--- a/integration-tests/docker/test_env/test_env_builder.go
+++ b/integration-tests/docker/test_env/test_env_builder.go
@@ -4,9 +4,9 @@ import (
"fmt"
"math/big"
"os"
+ "runtime/debug"
"testing"
- "github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
@@ -230,7 +230,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
case CleanUpTypeNone:
b.l.Warn().Msg("test environment won't be cleaned up")
case "":
- return b.te, errors.WithMessage(errors.New("explicit cleanup type must be set when building test environment"), "test environment builder failed")
+ return b.te, fmt.Errorf("test environment builder failed: %w", fmt.Errorf("explicit cleanup type must be set when building test environment"))
}
if b.nonDevGethNetworks != nil {
@@ -243,14 +243,14 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
for i, n := range b.te.PrivateChain {
primaryNode := n.GetPrimaryNode()
if primaryNode == nil {
- return b.te, errors.WithStack(fmt.Errorf("primary node is nil in PrivateChain interface"))
+ return b.te, fmt.Errorf("primary node is nil in PrivateChain interface, stack: %s", string(debug.Stack()))
}
nonDevNetworks = append(nonDevNetworks, *n.GetNetworkConfig())
nonDevNetworks[i].URLs = []string{primaryNode.GetInternalWsUrl()}
nonDevNetworks[i].HTTPURLs = []string{primaryNode.GetInternalHttpUrl()}
}
if nonDevNetworks == nil {
- return nil, errors.New("cannot create nodes with custom config without nonDevNetworks")
+ return nil, fmt.Errorf("cannot create nodes with custom config without nonDevNetworks")
}
err = b.te.StartClCluster(b.clNodeConfig, b.clNodesCount, b.secretsConfig)
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index eb542651b5..2ac3c38a71 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -17,12 +17,11 @@ require (
github.com/manifoldco/promptui v0.9.0
github.com/onsi/gomega v1.27.8
github.com/pelletier/go-toml/v2 v2.1.0
- github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.30.0
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.5
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
@@ -364,6 +363,7 @@ require (
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/alertmanager v0.25.1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index ecafa2706e..ce5e51a568 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2376,8 +2376,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65 h1:/iRhwYy5KFsaS9Zo1T64QxAd11HGZB5p/LHI5oVc4BU=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.5-0.20231107092923-3aa655167f65/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.5 h1:R0f13AUbon1ltHE/vudkyUnLRGaoeocIDVv+FsHZjno=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.5/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/load/functions/config.go b/integration-tests/load/functions/config.go
index 5c622401ab..451d01a6c8 100644
--- a/integration-tests/load/functions/config.go
+++ b/integration-tests/load/functions/config.go
@@ -1,12 +1,13 @@
package loadfunctions
import (
+ "fmt"
+ "math/big"
+ "os"
+
"github.com/pelletier/go-toml/v2"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "math/big"
- "os"
)
const (
@@ -103,18 +104,18 @@ func ReadConfig() (*PerformanceConfig, error) {
var cfg *PerformanceConfig
d, err := os.ReadFile(DefaultConfigFilename)
if err != nil {
- return nil, errors.Wrap(err, ErrReadPerfConfig)
+ return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err)
}
err = toml.Unmarshal(d, &cfg)
if err != nil {
- return nil, errors.Wrap(err, ErrUnmarshalPerfConfig)
+ return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err)
}
log.Debug().Interface("PerformanceConfig", cfg).Msg("Parsed performance config")
mpk := os.Getenv("MUMBAI_KEYS")
murls := os.Getenv("MUMBAI_URLS")
snet := os.Getenv("SELECTED_NETWORKS")
if mpk == "" || murls == "" || snet == "" {
- return nil, errors.New(
+ return nil, fmt.Errorf(
"ensure variables are set:\nMUMBAI_KEYS variable, private keys, comma separated\nSELECTED_NETWORKS=MUMBAI\nMUMBAI_URLS variable, websocket urls, comma separated",
)
} else {
diff --git a/integration-tests/load/functions/gateway.go b/integration-tests/load/functions/gateway.go
index aefe4fbedc..78b0f14cf1 100644
--- a/integration-tests/load/functions/gateway.go
+++ b/integration-tests/load/functions/gateway.go
@@ -8,16 +8,16 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
+ "time"
+
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/go-resty/resty/v2"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions"
"github.com/smartcontractkit/chainlink/v2/core/services/s4"
"github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
- "time"
)
type RPCResponse struct {
@@ -182,12 +182,12 @@ func EncryptS4Secrets(deployerPk *ecdsa.PrivateKey, tdh2Pk *tdh2easy.PublicKey,
donKey = bytes.Join([][]byte{b, donKey}, nil)
donPubKey, err := crypto.UnmarshalPubkey(donKey)
if err != nil {
- return "", errors.Wrap(err, "failed to unmarshal DON key")
+ return "", fmt.Errorf("failed to unmarshal DON key: %w", err)
}
eciesDONPubKey := ecies.ImportECDSAPublic(donPubKey)
signature, err := deployerPk.Sign(rand.Reader, []byte(msgJSON), nil)
if err != nil {
- return "", errors.Wrap(err, "failed to sign the msg with Ethereum key")
+ return "", fmt.Errorf("failed to sign the msg with Ethereum key: %w", err)
}
signedSecrets, err := json.Marshal(struct {
Signature []byte `json:"signature"`
@@ -197,29 +197,29 @@ func EncryptS4Secrets(deployerPk *ecdsa.PrivateKey, tdh2Pk *tdh2easy.PublicKey,
Message: msgJSON,
})
if err != nil {
- return "", errors.Wrap(err, "failed to marshal signed secrets")
+ return "", fmt.Errorf("failed to marshal signed secrets: %w", err)
}
ct, err := ecies.Encrypt(rand.Reader, eciesDONPubKey, signedSecrets, nil, nil)
if err != nil {
- return "", errors.Wrap(err, "failed to encrypt with DON key")
+ return "", fmt.Errorf("failed to encrypt with DON key: %w", err)
}
ct0xFormat, err := json.Marshal(map[string]interface{}{"0x0": base64.StdEncoding.EncodeToString(ct)})
if err != nil {
- return "", errors.Wrap(err, "failed to marshal DON key encrypted format")
+ return "", fmt.Errorf("failed to marshal DON key encrypted format: %w", err)
}
ctTDH2Format, err := tdh2easy.Encrypt(tdh2Pk, ct0xFormat)
if err != nil {
- return "", errors.Wrap(err, "failed to encrypt with TDH2 public key")
+ return "", fmt.Errorf("failed to encrypt with TDH2 public key: %w", err)
}
tdh2Message, err := ctTDH2Format.Marshal()
if err != nil {
- return "", errors.Wrap(err, "failed to marshal TDH2 encrypted msg")
+ return "", fmt.Errorf("failed to marshal TDH2 encrypted msg: %w", err)
}
finalMsg, err := json.Marshal(map[string]interface{}{
"encryptedSecrets": "0x" + hex.EncodeToString(tdh2Message),
})
if err != nil {
- return "", errors.Wrap(err, "failed to marshal secrets msg")
+ return "", fmt.Errorf("failed to marshal secrets msg: %w", err)
}
return string(finalMsg), nil
}
diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go
index 5253c531ee..81bc660b35 100644
--- a/integration-tests/load/functions/setup.go
+++ b/integration-tests/load/functions/setup.go
@@ -2,6 +2,7 @@ package loadfunctions
import (
"crypto/ecdsa"
+ "fmt"
"math/big"
mrand "math/rand"
"os"
@@ -10,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/go-resty/resty/v2"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
@@ -91,41 +91,41 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) {
log.Info().Msg("Creating new subscription")
subID, err := router.CreateSubscriptionWithConsumer(loadTestClient.Address())
if err != nil {
- return nil, errors.Wrap(err, "failed to create a new subscription")
+ return nil, fmt.Errorf("failed to create a new subscription: %w", err)
}
encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint64"}]`, subID)
if err != nil {
- return nil, errors.Wrap(err, "failed to encode subscription ID for funding")
+ return nil, fmt.Errorf("failed to encode subscription ID for funding: %w", err)
}
_, err = lt.TransferAndCall(router.Address(), big.NewInt(0).Mul(cfg.Common.Funding.SubFunds, big.NewInt(1e18)), encodedSubId)
if err != nil {
- return nil, errors.Wrap(err, "failed to transferAndCall router, LINK funding")
+ return nil, fmt.Errorf("failed to transferAndCall router, LINK funding: %w", err)
}
cfg.Common.SubscriptionID = subID
}
pKey, pubKey, err := parseEthereumPrivateKey(os.Getenv("MUMBAI_KEYS"))
if err != nil {
- return nil, errors.Wrap(err, "failed to load Ethereum private key")
+ return nil, fmt.Errorf("failed to load Ethereum private key: %w", err)
}
tpk, err := coord.GetThresholdPublicKey()
if err != nil {
- return nil, errors.Wrap(err, "failed to get Threshold public key")
+ return nil, fmt.Errorf("failed to get Threshold public key: %w", err)
}
log.Info().Hex("ThresholdPublicKeyBytesHex", tpk).Msg("Loaded coordinator keys")
donPubKey, err := coord.GetDONPublicKey()
if err != nil {
- return nil, errors.Wrap(err, "failed to get DON public key")
+ return nil, fmt.Errorf("failed to get DON public key: %w", err)
}
log.Info().Hex("DONPublicKeyHex", donPubKey).Msg("Loaded DON key")
tdh2pk, err := ParseTDH2Key(tpk)
if err != nil {
- return nil, errors.Wrap(err, "failed to unmarshal tdh2 public key")
+ return nil, fmt.Errorf("failed to unmarshal tdh2 public key: %w", err)
}
var encryptedSecrets string
if cfg.Common.Secrets != "" {
encryptedSecrets, err = EncryptS4Secrets(pKey, tdh2pk, donPubKey, cfg.Common.Secrets)
if err != nil {
- return nil, errors.Wrap(err, "failed to generate tdh2 secrets")
+ return nil, fmt.Errorf("failed to generate tdh2 secrets: %w", err)
}
slotID, slotVersion, err := UploadS4Secrets(resty.New(), &S4SecretsCfg{
GatewayURL: cfg.Common.GatewayURL,
@@ -139,7 +139,7 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) {
S4SetPayload: encryptedSecrets,
})
if err != nil {
- return nil, errors.Wrap(err, "failed to upload secrets to S4")
+ return nil, fmt.Errorf("failed to upload secrets to S4: %w", err)
}
cfg.Common.SecretsSlotID = slotID
cfg.Common.SecretsVersionID = slotVersion
@@ -168,13 +168,13 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) {
func parseEthereumPrivateKey(pk string) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) {
pKey, err := crypto.HexToECDSA(pk)
if err != nil {
- return nil, nil, errors.Wrap(err, "failed to convert Ethereum key from hex")
+ return nil, nil, fmt.Errorf("failed to convert Ethereum key from hex: %w", err)
}
publicKey := pKey.Public()
pubKey, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
- return nil, nil, errors.Wrap(err, "failed to get public key from Ethereum private key")
+ return nil, nil, fmt.Errorf("failed to get public key from Ethereum private key: %w", err)
}
log.Info().Str("Address", crypto.PubkeyToAddress(*pubKey).Hex()).Msg("Parsed private key for address")
return pKey, pubKey, nil
diff --git a/integration-tests/load/vrfv2/config.go b/integration-tests/load/vrfv2/config.go
index ee5f3ff80d..0c62cc351b 100644
--- a/integration-tests/load/vrfv2/config.go
+++ b/integration-tests/load/vrfv2/config.go
@@ -1,12 +1,13 @@
package loadvrfv2
import (
+ "fmt"
+ "math/big"
+ "os"
+
"github.com/pelletier/go-toml/v2"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "math/big"
- "os"
)
const (
@@ -63,11 +64,11 @@ func ReadConfig() (*PerformanceConfig, error) {
var cfg *PerformanceConfig
d, err := os.ReadFile(DefaultConfigFilename)
if err != nil {
- return nil, errors.Wrap(err, ErrReadPerfConfig)
+ return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err)
}
err = toml.Unmarshal(d, &cfg)
if err != nil {
- return nil, errors.Wrap(err, ErrUnmarshalPerfConfig)
+ return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err)
}
log.Debug().Interface("PerformanceConfig", cfg).Msg("Parsed performance config")
return cfg, nil
diff --git a/integration-tests/load/vrfv2/vu.go b/integration-tests/load/vrfv2/vu.go
index df05a9168e..4658388d40 100644
--- a/integration-tests/load/vrfv2/vu.go
+++ b/integration-tests/load/vrfv2/vu.go
@@ -1,13 +1,14 @@
package loadvrfv2
import (
- "github.com/pkg/errors"
+ "fmt"
+ "time"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/wasp"
- "time"
)
/* JobVolumeVU is a "virtual user" that creates a VRFv2 job and constantly requesting new randomness only for this job instance */
@@ -54,7 +55,7 @@ func (m *JobVolumeVU) Clone(_ *wasp.Generator) wasp.VirtualUser {
func (m *JobVolumeVU) Setup(_ *wasp.Generator) error {
jobs, err := vrfv2_actions.CreateVRFV2Jobs(m.nodes, m.contracts.Coordinator, m.bc, m.minIncomingConfirmations)
if err != nil {
- return errors.Wrap(err, "failed to create VRFv2 jobs in setup")
+ return fmt.Errorf("failed to create VRFv2 jobs in setup: %w", err)
}
m.jobs = jobs
m.keyHash = jobs[0].KeyHash
diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go
index a5439210c2..cba3fdcde5 100644
--- a/integration-tests/load/vrfv2plus/config.go
+++ b/integration-tests/load/vrfv2plus/config.go
@@ -2,12 +2,13 @@ package loadvrfv2plus
import (
"encoding/base64"
+ "fmt"
+ "os"
+
"github.com/pelletier/go-toml/v2"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "os"
)
const (
@@ -95,18 +96,18 @@ func ReadConfig() (*PerformanceConfig, error) {
if rawConfig == "" {
d, err = os.ReadFile(DefaultConfigFilename)
if err != nil {
- return nil, errors.Wrap(err, ErrReadPerfConfig)
+ return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err)
}
} else {
d, err = base64.StdEncoding.DecodeString(rawConfig)
}
err = toml.Unmarshal(d, &cfg)
if err != nil {
- return nil, errors.Wrap(err, ErrUnmarshalPerfConfig)
+ return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err)
}
if cfg.Soak.RandomnessRequestCountPerRequest <= cfg.Soak.RandomnessRequestCountPerRequestDeviation {
- return nil, errors.Wrap(err, ErrDeviationShouldBeLessThanOriginal)
+ return nil, fmt.Errorf("%s, err: %w", ErrDeviationShouldBeLessThanOriginal, err)
}
log.Debug().Interface("Config", cfg).Msg("Parsed config")
diff --git a/integration-tests/reorg/reorg_confirmer.go b/integration-tests/reorg/reorg_confirmer.go
index 885bed2ad4..2193131680 100644
--- a/integration-tests/reorg/reorg_confirmer.go
+++ b/integration-tests/reorg/reorg_confirmer.go
@@ -2,13 +2,13 @@ package reorg
import (
"context"
+ "fmt"
"math/big"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
@@ -70,7 +70,7 @@ type ReorgController struct {
// NewReorgController creates a type that can create reorg chaos and confirm reorg has happened
func NewReorgController(cfg *ReorgConfig) (*ReorgController, error) {
if len(cfg.Network.GetClients()) == 1 {
- return nil, errors.New("need at least 3 nodes to re-org")
+ return nil, fmt.Errorf("need at least 3 nodes to re-org")
}
ctx, ctxCancel := context.WithTimeout(context.Background(), cfg.Timeout)
rc := &ReorgController{
@@ -165,7 +165,7 @@ func (rc *ReorgController) VerifyReorgComplete() error {
}
}
if rc.currentVerifiedBlocks+1 < rc.ReorgDepth {
- return errors.New("Reorg depth has not met")
+ return fmt.Errorf("Reorg depth has not met")
}
return nil
}
@@ -217,7 +217,7 @@ func (rc *ReorgController) Wait() error {
if rc.complete {
return nil
}
- return errors.New("timeout waiting for reorg to complete")
+ return fmt.Errorf("timeout waiting for reorg to complete")
}
// forkNetwork stomp the network between target reorged node and the rest
diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go
index 1b33cdce76..a6dcdcd139 100644
--- a/integration-tests/smoke/ocr2_test.go
+++ b/integration-tests/smoke/ocr2_test.go
@@ -5,24 +5,14 @@ import (
"fmt"
"math/big"
"net/http"
- "strings"
"testing"
"time"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
- "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
- "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
- "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
- "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
- mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
- "github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
- "github.com/smartcontractkit/chainlink/integration-tests/client"
- "github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
@@ -102,42 +92,3 @@ func TestOCRv2Basic(t *testing.T) {
roundData.Answer.Int64(),
)
}
-
-func setupOCR2Test(t *testing.T, forwardersEnabled bool) (
- testEnvironment *environment.Environment,
- testNetwork blockchain.EVMNetwork,
-) {
- testNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
- evmConfig := ethereum.New(nil)
- if !testNetwork.Simulated {
- evmConfig = ethereum.New(ðereum.Props{
- NetworkName: testNetwork.Name,
- Simulated: testNetwork.Simulated,
- WsURLs: testNetwork.URLs,
- })
- }
-
- var toml string
- if forwardersEnabled {
- toml = client.AddNetworkDetailedConfig(config.BaseOCR2Config, config.ForwarderNetworkDetailConfig, testNetwork)
- } else {
- toml = client.AddNetworksConfig(config.BaseOCR2Config, testNetwork)
- }
-
- chainlinkChart := chainlink.New(0, map[string]interface{}{
- "replicas": 6,
- "toml": toml,
- })
-
- testEnvironment = environment.New(&environment.Config{
- NamespacePrefix: fmt.Sprintf("smoke-ocr2-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")),
- Test: t,
- }).
- AddHelm(mockservercfg.New(nil)).
- AddHelm(mockserver.New(nil)).
- AddHelm(evmConfig).
- AddHelm(chainlinkChart)
- err := testEnvironment.Run()
- require.NoError(t, err, "Error running test environment")
- return testEnvironment, testNetwork
-}
diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go
index 0d6a77a115..912c121d07 100644
--- a/integration-tests/smoke/ocr2vrf_test.go
+++ b/integration-tests/smoke/ocr2vrf_test.go
@@ -1,6 +1,7 @@
package smoke
import (
+ "context"
"fmt"
"math/big"
"strings"
@@ -80,7 +81,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(nil, requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(context.Background(), requestID, big.NewInt(int64(i)))
require.NoError(t, err)
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
@@ -141,7 +142,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(nil, requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(context.Background(), requestID, big.NewInt(int64(i)))
require.NoError(t, err, "Error getting Randomness result from Consumer Contract")
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness Fulfillment retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness Fulfillment retrieved from Consumer contract give an answer other than 0")
diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go
index acd548c88e..3510a1505a 100644
--- a/integration-tests/smoke/vrfv2plus_test.go
+++ b/integration-tests/smoke/vrfv2plus_test.go
@@ -3,14 +3,14 @@ package smoke
import (
"context"
"fmt"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
"math/big"
"testing"
"time"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
+
"github.com/ethereum/go-ethereum/common"
"github.com/kelseyhightower/envconfig"
- "github.com/pkg/errors"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
@@ -271,6 +271,7 @@ func TestVRFv2Plus(t *testing.T) {
subIDForCancelling := subIDsForCancelling[0]
testWalletAddress, err := actions.GenerateWallet()
+ require.NoError(t, err)
testWalletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), testWalletAddress)
require.NoError(t, err)
@@ -638,7 +639,7 @@ func TestVRFv2PlusMigration(t *testing.T) {
require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete)
_, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfv2PlusData.VRFKey, vrfv2PlusData.PrimaryEthAddress, newCoordinator)
- require.NoError(t, err, errors.Wrap(err, vrfv2plus.ErrRegisteringProvingKey))
+ require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfv2plus.ErrRegisteringProvingKey, err))
err = newCoordinator.SetConfig(
vrfv2PlusConfig.MinimumConfirmations,
@@ -651,6 +652,7 @@ func TestVRFv2PlusMigration(t *testing.T) {
FulfillmentFlatFeeNativePPM: vrfv2PlusConfig.FulfillmentFlatFeeNativePPM,
},
)
+ require.NoError(t, err)
err = newCoordinator.SetLINKAndLINKNativeFeed(linkAddress.Address(), mockETHLinkFeedAddress.Address())
require.NoError(t, err, vrfv2plus.ErrSetLinkNativeLinkFeed)
From 8c81f61f36fa9aeddde43b1c139a20c6915a3121 Mon Sep 17 00:00:00 2001
From: Tate
Date: Tue, 7 Nov 2023 12:23:45 -0700
Subject: [PATCH 098/327] [TT-685] Enforce CTF version to be tag in the form
v1.2.3 (#11209)
---
.github/actions/build-test-image/action.yml | 9 ++++++++-
.github/workflows/integration-tests.yml | 14 +++++++++++++-
2 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml
index c4b39b4d7a..683ce912ec 100644
--- a/.github/actions/build-test-image/action.yml
+++ b/.github/actions/build-test-image/action.yml
@@ -30,6 +30,13 @@ inputs:
runs:
using: composite
steps:
+ - name: Get CTF Version
+ id: version
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
+ with:
+ go-project-path: ./integration-tests
+ module-name: github.com/smartcontractkit/chainlink-testing-framework
+ enforce-semantic-tag: "true" # it has to be in the form of v1.2.3 or the image won't exist
- name: Check if image exists
id: check-image
uses: smartcontractkit/chainlink-github-actions/docker/image-exists@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12
@@ -48,7 +55,7 @@ runs:
file: ./integration-tests/test.Dockerfile
build-args: |
BASE_IMAGE=${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image
- IMAGE_VERSION=v0.38.2
+ IMAGE_VERSION=${{ steps.version.output.version }}
SUITES="${{ inputs.suites }}"
AWS_REGION: ${{ inputs.QA_AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 125ddb3f4f..382e9cbbcf 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -35,6 +35,18 @@ env:
MOD_CACHE_VERSION: 2
jobs:
+ enforce-ctf-version:
+ name: Enforce CTF Version
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Enforce CTF Version
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
+ with:
+ go-project-path: ./integration-tests
+ module-name: github.com/smartcontractkit/chainlink-testing-framework
+ enforce-semantic-tag: "true"
changes:
environment: integration
name: Check Paths That Require Tests To Run
@@ -81,7 +93,7 @@ jobs:
tag-suffix: -plugins
name: Build Chainlink Image ${{ matrix.image.name }}
runs-on: ubuntu20.04-16cores-64GB
- needs: [changes]
+ needs: [changes, enforce-ctf-version]
steps:
- name: Collect Metrics
if: needs.changes.outputs.src == 'true'
From 5af9bca45861bc61a1375cf0770570341c9a7a88 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Tue, 7 Nov 2023 14:38:42 -0500
Subject: [PATCH 099/327] [TT-524] Separate Live Testnet Tests (#11196)
* Separate Live Testnet Tests
* \n
* Remove typo
* Extrapolates building Chainlink image
---
.../actions/build-chainlink-image/action.yml | 48 +++
.github/workflows/integration-tests.yml | 243 +------------
.github/workflows/live-testnet-tests.yml | 342 ++++++++++++++++++
3 files changed, 399 insertions(+), 234 deletions(-)
create mode 100644 .github/actions/build-chainlink-image/action.yml
create mode 100644 .github/workflows/live-testnet-tests.yml
diff --git a/.github/actions/build-chainlink-image/action.yml b/.github/actions/build-chainlink-image/action.yml
new file mode 100644
index 0000000000..5041d9d1db
--- /dev/null
+++ b/.github/actions/build-chainlink-image/action.yml
@@ -0,0 +1,48 @@
+name: Build Chainlink Image
+description: A composite action that allows building and publishing the Chainlink image for integration testing
+
+inputs:
+ tag_suffix:
+ description: The suffix to append to the image tag (usually blank or "-plugins")
+ default: ""
+ dockerfile:
+ description: The path to the Dockerfile to use (usually core/chainlink.Dockerfile or plugins/chainlink.Dockerfile)
+ default: core/chainlink.Dockerfile
+ git_commit_sha:
+ description: The git commit sha to use for the image tag
+ default: ${{ github.sha }}
+ GRAFANA_CLOUD_BASIC_AUTH:
+ description: "grafana cloud basic auth"
+ GRAFANA_CLOUD_HOST:
+ description: "grafana cloud hostname"
+ AWS_REGION:
+ description: "AWS region to use for ECR"
+ AWS_ROLE_TO_ASSUME:
+ description: "AWS role to assume for ECR"
+
+runs:
+ using: composite
+ steps:
+ - name: Check if image exists
+ id: check-image
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ with:
+ repository: chainlink
+ tag: ${{ inputs.git_commit_sha }}${{ inputs.tag_suffix }}
+ AWS_REGION: ${{ inputs.AWS_REGION }}
+ AWS_ROLE_TO_ASSUME: ${{ inputs.AWS_ROLE_TO_ASSUME }}
+ - name: Build Image
+ if: steps.check-image.outputs.exists == 'false' && needs.changes.outputs.src == 'true'
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ with:
+ cl_repo: smartcontractkit/chainlink
+ cl_ref: ${{ inputs.git_commit_sha }}
+ cl_dockerfile: ${{ inputs.dockerfile }}
+ push_tag: ${{ env.CHAINLINK_IMAGE }}:${{ inputs.git_commit_sha }}${{ inputs.tag_suffix }}
+ QA_AWS_REGION: ${{ inputs.AWS_REGION }}
+ QA_AWS_ROLE_TO_ASSUME: ${{ inputs.AWS_ROLE_TO_ASSUME }}
+ - name: Print Chainlink Image Built
+ shell: sh
+ run: |
+ echo "### Chainlink node image tag used for this test run :link:" >>$GITHUB_STEP_SUMMARY
+ echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 382e9cbbcf..4c617a00c4 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -2,23 +2,10 @@ name: Integration Tests
on:
merge_group:
pull_request:
- schedule:
- - cron: "0 0 * * *"
- # - cron: "0 * * * *" # DEBUG: Run every hour to nail down flakes
push:
tags:
- "*"
workflow_dispatch:
- inputs:
- simulatedNetwork:
- description: "Run Simulated Network Tests"
- required: false
- type: boolean
- default: true
- liveNetwork:
- description: "Run Live Network Tests"
- required: false
- type: boolean
# Only run 1 of this workflow at a time per PR
concurrency:
@@ -74,9 +61,9 @@ jobs:
hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
this-job-name: Check Paths That Require Tests To Run
continue-on-error: true
-
outputs:
src: ${{ steps.changes.outputs.src }}
+
build-chainlink:
environment: integration
permissions:
@@ -108,30 +95,16 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- - name: Check if image exists
- if: needs.changes.outputs.src == 'true'
- id: check-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
- with:
- repository: chainlink
- tag: ${{ github.sha }}${{ matrix.image.tag-suffix }}
+ - name: Build Chainlink Image
+ uses: ./.github/actions/build-chainlink-image
+ with:
+ tag_suffix: ${{ matrix.image.tag-suffix }}
+ dockerfile: ${{ matrix.image.dockerfile }}
+ git_commit_sha: ${{ github.sha }}
+ GRAFANA_CLOUD_BASIC_AUTH: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ GRAFANA_CLOUD_HOST: ${{ secrets.GRAFANA_CLOUD_HOST }}
AWS_REGION: ${{ secrets.QA_AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
- - name: Build Image
- if: steps.check-image.outputs.exists == 'false' && needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
- with:
- cl_repo: smartcontractkit/chainlink
- cl_ref: ${{ github.sha }}
- cl_dockerfile: ${{ matrix.image.dockerfile }}
- push_tag: ${{ env.CHAINLINK_IMAGE }}:${{ github.sha }}${{ matrix.image.tag-suffix }}
- QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
- QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
- - name: Print Chainlink Image Built
- if: needs.changes.outputs.src == 'true'
- run: |
- echo "### Chainlink node image tag used for this test run :link:" >>$GITHUB_STEP_SUMMARY
- echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY
build-test-image:
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'schedule' || contains(join(github.event.pull_request.labels.*.name, ' '), 'build-test-image')
@@ -908,201 +881,3 @@ jobs:
matrix-aggregator-status: ${{ needs.solana-smoke-tests-matrix.result }}
continue-on-error: true
### End Solana Section
-
- ### Start Live Testnet Section
-
- testnet-smoke-tests-matrix:
- if: ${{ github.event_name == 'schedule' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && inputs.liveNetwork) }} ## Only run live tests on new tags, schedule, or on manual request
- environment: integration
- permissions:
- checks: write
- pull-requests: write
- id-token: write
- contents: read
- needs: [build-chainlink]
- env:
- SELECTED_NETWORKS: ${{ matrix.testnet }}
- CHAINLINK_COMMIT_SHA: ${{ github.sha }}
- CHAINLINK_ENV_USER: ${{ github.actor }}
- TEST_LOG_LEVEL: debug
- EVM_KEYS: ${{ secrets.QA_EVM_KEYS }}
-
- OPTIMISM_GOERLI_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_URLS }}
- OPTIMISM_GOERLI_HTTP_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_HTTP_URLS }}
-
- ARBITRUM_GOERLI_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_URLS }}
- ARBITRUM_GOERLI_HTTP_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_HTTP_URLS }}
- strategy:
- fail-fast: false
- matrix:
- # NOTE: If changing this matrix, make sure to update the matrix in the testnet-smoke-tests-notify job to be the same
- # otherwise reporting will be broken. Getting a single matrix for multiple jobs is a pain
- # https://github.com/orgs/community/discussions/26284#discussioncomment-3251198
- testnet: [OPTIMISM_GOERLI, ARBITRUM_GOERLI]
- name: Live Testnet Smoke Tests ${{ matrix.testnet }}
- runs-on: ubuntu-latest
- steps:
- - name: Checkout the repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- with:
- ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- ## Only run OCR smoke test for now
- - name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
- env:
- PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
- PYROSCOPE_ENVIRONMENT: ci-smoke-ocr-evm-${{ matrix.testnet }} # TODO: Only for OCR for now
- PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
- with:
- test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/ocr_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
- test_download_vendor_packages_command: cd ./integration-tests && go mod download
- cl_repo: ${{ env.CHAINLINK_IMAGE }}
- cl_image_tag: ${{ github.sha }}
- aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
- dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
- artifacts_location: ./integration-tests/smoke/logs
- publish_check_name: ${{ matrix.testnet }} OCR Smoke Test Results
- token: ${{ secrets.GITHUB_TOKEN }}
- go_mod_path: ./integration-tests/go.mod
- cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
- cache_restore_only: "true"
- QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
- QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
- QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
-
- - name: Collect Metrics
- if: always()
- id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
- with:
- basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
- hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
- this-job-name: Live Testnet Smoke Tests ${{ matrix.testnet }}
- test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
- continue-on-error: true
-
- testnet-smoke-tests-notify:
- name: Live Testnet Start Slack Thread
- if: ${{ always() && needs.testnet-smoke-tests-matrix.result != 'skipped' && needs.testnet-smoke-tests-matrix.result != 'cancelled' && github.event_name != 'workflow_dispatch' }}
- environment: integration
- outputs:
- thread_ts: ${{ steps.slack.outputs.thread_ts }}
- permissions:
- checks: write
- pull-requests: write
- id-token: write
- contents: read
- runs-on: ubuntu-latest
- needs: testnet-smoke-tests-matrix
- steps:
- - name: Debug Result
- run: echo ${{needs.testnet-smoke-tests-matrix.result}}
- - name: Main Slack Notification
- uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
- id: slack
- with:
- channel-id: ${{ secrets.QA_SLACK_CHANNEL }}
- payload: |
- {
- "attachments": [
- {
- "color": "${{ needs.testnet-smoke-tests-matrix.result == 'success' && '#2E7D32' || '#C62828' }}",
- "blocks": [
- {
- "type": "header",
- "text": {
- "type": "plain_text",
- "text": "Live Smoke Test Results ${{ needs.testnet-smoke-tests-matrix.result == 'success' && ':white_check_mark:' || ':x:'}}",
- "emoji": true
- }
- },
- {
- "type": "divider"
- },
- {
- "type": "section",
- "text": {
- "type": "mrkdwn",
- "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>"
- }
- }
- ]
- }
- ]
- }
- env:
- SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
-
- testnet-smoke-tests-results:
- name: Post Live Testnet Smoke Test Results
- if: ${{ always() && needs.testnet-smoke-tests-matrix.result != 'skipped' && needs.testnet-smoke-tests-matrix.result != 'cancelled' }}
- environment: integration
- permissions:
- checks: write
- pull-requests: write
- id-token: write
- contents: read
- runs-on: ubuntu-latest
- needs: testnet-smoke-tests-notify
- strategy:
- fail-fast: false
- matrix:
- # NOTE: If changing this matrix, make sure to update the matrix in the testnet-smoke-tests-matrix job to be the same
- # otherwise reporting will be broken. Getting a single matrix for multiple jobs is a pain
- # https://github.com/orgs/community/discussions/26284#discussioncomment-3251198
- testnet: [OPTIMISM_GOERLI, ARBITRUM_GOERLI]
- steps:
- - name: Get Results
- id: test-results
- run: |
- echo "Querying test results"
-
- echo "status=$(curl \
- -H "Authorization: Bearer ${{ github.token }}" \
- 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \
- | jq -r '.jobs[] | select(.name == "Live Testnet Smoke Tests ${{ matrix.testnet}}").steps[] | select(.name == "Run Tests").conclusion')" >> $GITHUB_OUTPUT
-
- echo "status=$(curl \
- -H "Authorization: Bearer ${{ github.token }}" \
- 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \
- | jq -r '.jobs[] | select(.name == "Live Testnet Smoke Tests ${{ matrix.testnet}}").steps[] | select(.name == "Run Tests").conclusion')"
- echo "thread_ts=${{ needs.testnet-smoke-tests-notify.outputs.thread_ts }}"
-
- - name: Test Details
- uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
- with:
- channel-id: ${{ secrets.QA_SLACK_CHANNEL }}
- payload: |
- {
- "thread_ts": "${{ needs.testnet-smoke-tests-notify.outputs.thread_ts }}",
- "attachments": [
- {
- "color": "${{ steps.test-results.outputs.status == 'success' && '#2E7D32' || '#C62828' }}",
- "blocks": [
- {
- "type": "header",
- "text": {
- "type": "plain_text",
- "text": "${{ matrix.testnet }} Smoke Test Results ${{ steps.test-results.outputs.status == 'success' && ':white_check_mark:' || ':x:'}}",
- "emoji": true
- }
- },
- {
- "type": "divider"
- },
- {
- "type": "section",
- "text": {
- "type": "mrkdwn",
- "text": "OCR ${{ steps.test-results.outputs.status == 'success' && ':white_check_mark:' || ':x:'}}"
- }
- }
- ]
- }
- ]
- }
- env:
- SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
-
- ### End Live Testnet Section
diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml
new file mode 100644
index 0000000000..23e9b3c04c
--- /dev/null
+++ b/.github/workflows/live-testnet-tests.yml
@@ -0,0 +1,342 @@
+name: Live Testnet Tests
+on:
+ schedule:
+ - cron: "0 0 * * *" # Run nightly
+ push:
+ tags:
+ - "*"
+ workflow_dispatch:
+
+env:
+ CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink
+ INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com
+ MOD_CACHE_VERSION: 2
+
+ CHAINLINK_COMMIT_SHA: ${{ github.sha }}
+ CHAINLINK_ENV_USER: ${{ github.actor }}
+ TEST_LOG_LEVEL: debug
+ EVM_KEYS: ${{ secrets.QA_EVM_KEYS }}
+
+ OPTIMISM_GOERLI_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_URLS }}
+ OPTIMISM_GOERLI_HTTP_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_HTTP_URLS }}
+
+ ARBITRUM_GOERLI_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_URLS }}
+ ARBITRUM_GOERLI_HTTP_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_HTTP_URLS }}
+
+jobs:
+ build-chainlink:
+ environment: integration
+ permissions:
+ id-token: write
+ contents: read
+ name: Build Chainlink Image
+ runs-on: ubuntu20.04-16cores-64GB
+ steps:
+ - name: Collect Metrics
+ id: collect-gha-metrics
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ with:
+ basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ this-job-name: Build Chainlink Image
+ continue-on-error: true
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
+ - name: Build Chainlink Image
+ uses: ./.github/actions/build-chainlink-image
+ with:
+ tag_suffix: ""
+ dockerfile: core/chainlink.Dockerfile
+ git_commit_sha: ${{ github.sha }}
+ GRAFANA_CLOUD_BASIC_AUTH: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ GRAFANA_CLOUD_HOST: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
+
+
+ sepolia-smoke-tests:
+ environment: integration
+ permissions:
+ checks: write
+ pull-requests: write
+ id-token: write
+ contents: read
+ needs: [build-chainlink]
+ env:
+ SELECTED_NETWORKS: SEPOLIA
+ strategy:
+ fail-fast: false
+ matrix:
+ product: [ocr, automation]
+ name: Sepolia ${{ matrix.product }} Tests
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
+ - name: Run Tests
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ env:
+ PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
+ PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia
+ PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
+ with:
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/${{ matrix.product }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_download_vendor_packages_command: cd ./integration-tests && go mod download
+ cl_repo: ${{ env.CHAINLINK_IMAGE }}
+ cl_image_tag: ${{ github.sha }}
+ aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
+ artifacts_location: ./integration-tests/smoke/logs
+ publish_check_name: Seplia ${{ matrix.product }} Smoke Test Results
+ token: ${{ secrets.GITHUB_TOKEN }}
+ go_mod_path: ./integration-tests/go.mod
+ cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
+ cache_restore_only: "true"
+ QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
+ QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
+ - name: Collect Metrics
+ if: always()
+ id: collect-gha-metrics
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ with:
+ basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ this-job-name: Sepolia ${{ matrix.product }} Tests
+ test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
+ continue-on-error: true
+
+ optimism-goerli-smoke-tests:
+ environment: integration
+ permissions:
+ checks: write
+ pull-requests: write
+ id-token: write
+ contents: read
+ needs: [build-chainlink]
+ env:
+ SELECTED_NETWORKS: OPTIMISM_GOERLI
+ strategy:
+ fail-fast: false
+ matrix:
+ product: [ocr, automation]
+ name: Optimism Goerli ${{ matrix.product }} Tests
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
+ - name: Run Tests
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ env:
+ PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
+ PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-optimism-goerli
+ PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
+ with:
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/${{ matrix.product }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_download_vendor_packages_command: cd ./integration-tests && go mod download
+ cl_repo: ${{ env.CHAINLINK_IMAGE }}
+ cl_image_tag: ${{ github.sha }}
+ aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
+ artifacts_location: ./integration-tests/smoke/logs
+ publish_check_name: Seplia ${{ matrix.product }} Smoke Test Results
+ token: ${{ secrets.GITHUB_TOKEN }}
+ go_mod_path: ./integration-tests/go.mod
+ cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
+ cache_restore_only: "true"
+ QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
+ QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
+ - name: Collect Metrics
+ if: always()
+ id: collect-gha-metrics
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ with:
+ basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ this-job-name: Optimism Goerli ${{ matrix.product }} Tests
+ test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
+ continue-on-error: true
+
+ arbitrum-goerli-smoke-tests:
+ environment: integration
+ permissions:
+ checks: write
+ pull-requests: write
+ id-token: write
+ contents: read
+ needs: [build-chainlink]
+ env:
+ SELECTED_NETWORKS: ARBITRUM_GOERLI
+ strategy:
+ fail-fast: false
+ matrix:
+ product: [ocr, automation]
+ name: Arbitrum Goerli ${{ matrix.product }} Tests
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
+ - name: Run Tests
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ env:
+ PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
+ PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-arbitrum-goerli
+ PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
+ with:
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/${{ matrix.product }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_download_vendor_packages_command: cd ./integration-tests && go mod download
+ cl_repo: ${{ env.CHAINLINK_IMAGE }}
+ cl_image_tag: ${{ github.sha }}
+ aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
+ artifacts_location: ./integration-tests/smoke/logs
+ publish_check_name: Arbitrum Goerli ${{ matrix.product }} Smoke Test Results
+ token: ${{ secrets.GITHUB_TOKEN }}
+ go_mod_path: ./integration-tests/go.mod
+ cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
+ cache_restore_only: "true"
+ QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
+ QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
+ - name: Collect Metrics
+ if: always()
+ id: collect-gha-metrics
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ with:
+ basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ this-job-name: Arbitrum Goerli ${{ matrix.product }} Tests
+ test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
+ continue-on-error: true
+
+ testnet-smoke-tests-notify:
+ name: Start Slack Thread
+ if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }}
+ environment: integration
+ outputs:
+ thread_ts: ${{ steps.slack.outputs.thread_ts }}
+ permissions:
+ checks: write
+ pull-requests: write
+ id-token: write
+ contents: read
+ runs-on: ubuntu-latest
+ needs: [sepolia-smoke-tests, optimism-goerli-smoke-tests, arbitrum-goerli-smoke-tests]
+ steps:
+ - name: Debug Result
+ run: echo ${{needs.*.result}}
+ - name: Main Slack Notification
+ uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
+ id: slack
+ with:
+ channel-id: ${{ secrets.QA_SLACK_CHANNEL }}
+ payload: |
+ {
+ "attachments": [
+ {
+ "color": "${{ needs.*.result == 'success' && '#2E7D32' || '#C62828' }}",
+ "blocks": [
+ {
+ "type": "header",
+ "text": {
+ "type": "plain_text",
+ "text": "Live Smoke Test Results ${{ needs.*.result == 'success' && ':white_check_mark:' || ':x:'}}",
+ "emoji": true
+ }
+ },
+ {
+ "type": "divider"
+ },
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ env:
+ SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
+
+ testnet-smoke-tests-results:
+ name: Post Test Results
+ if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }}
+ environment: integration
+ permissions:
+ checks: write
+ pull-requests: write
+ id-token: write
+ contents: read
+ runs-on: ubuntu-latest
+ needs: testnet-smoke-tests-notify
+ strategy:
+ fail-fast: false
+ matrix:
+ testnet: [sepolia, optimism-goerli, arbitrum-goerli]
+ steps:
+ - name: Get Results
+ id: test-results
+ run: |
+ echo "Querying test results"
+
+ echo "status=$(curl \
+ -H "Authorization: Bearer ${{ github.token }}" \
+ 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \
+ | jq -r '.jobs[] | select(.name == "Live Testnet Smoke Tests ${{ matrix.testnet }}-smoke-tests").steps[] | select(.name == "Run Tests").conclusion')" >> $GITHUB_OUTPUT
+
+ echo "status=$(curl \
+ -H "Authorization: Bearer ${{ github.token }}" \
+ 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \
+ | jq -r '.jobs[] | select(.name == "Live Testnet Smoke Tests ${{ matrix.testnet }}-smoke-tests"").steps[] | select(.name == "Run Tests").conclusion')"
+ echo "thread_ts=${{ needs.testnet-smoke-tests-notify.outputs.thread_ts }}"
+
+ - name: Test Details
+ uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
+ with:
+ channel-id: ${{ secrets.QA_SLACK_CHANNEL }}
+ payload: |
+ {
+ "thread_ts": "${{ needs.testnet-smoke-tests-notify.outputs.thread_ts }}",
+ "attachments": [
+ {
+ "color": "${{ steps.test-results.outputs.status == 'success' && '#2E7D32' || '#C62828' }}",
+ "blocks": [
+ {
+ "type": "header",
+ "text": {
+ "type": "plain_text",
+ "text": "${{ matrix.testnet }} Smoke Test Results ${{ steps.test-results.outputs.status == 'success' && ':white_check_mark:' || ':x:'}}",
+ "emoji": true
+ }
+ },
+ {
+ "type": "divider"
+ },
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "OCR ${{ steps.test-results.outputs.status == 'success' && ':white_check_mark:' || ':x:'}}"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ env:
+ SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
From 647ce13cfac9c3bdd7a8f86636dde775f321a22b Mon Sep 17 00:00:00 2001
From: frank zhu
Date: Tue, 7 Nov 2023 13:40:22 -0600
Subject: [PATCH 100/327] add lint and update tests for solidity foundry gha
(#11184)
* add lint and update tests for solidity foundry gha
* fix typo
* fix typo
* refactor conditional into individual steps
* remove if statement for checkout repo and add comment
---
.github/workflows/solidity-foundry.yml | 13 +++++++++----
.github/workflows/solidity.yml | 8 +++++++-
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml
index 19c879b09e..7c9df79617 100644
--- a/.github/workflows/solidity-foundry.yml
+++ b/.github/workflows/solidity-foundry.yml
@@ -34,11 +34,12 @@ jobs:
matrix:
product: [vrf, automation, llo-feeds, functions, shared]
needs: [changes]
- if: needs.changes.outputs.changes == 'true'
- name: Tests
+ name: Foundry Tests ${{ matrix.product }} ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }}
# See https://github.com/foundry-rs/foundry/issues/3827
runs-on: ubuntu-22.04
+ # The if statements for steps after checkout repo is workaround for
+ # passing required check for PRs that don't have filtered changes.
steps:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
@@ -49,15 +50,18 @@ jobs:
# and not native Foundry. This is to make sure the dependencies
# stay in sync.
- name: Setup NodeJS
+ if: needs.changes.outputs.changes == 'true'
uses: ./.github/actions/setup-nodejs
- name: Install Foundry
+ if: needs.changes.outputs.changes == 'true'
uses: foundry-rs/foundry-toolchain@v1
with:
# Has to match the `make foundry` version.
version: nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b
- name: Run Forge build
+ if: needs.changes.outputs.changes == 'true'
run: |
forge --version
forge build
@@ -67,6 +71,7 @@ jobs:
FOUNDRY_PROFILE: ${{ matrix.product }}
- name: Run Forge tests
+ if: needs.changes.outputs.changes == 'true'
run: |
forge test -vvv
id: test
@@ -75,7 +80,7 @@ jobs:
FOUNDRY_PROFILE: ${{ matrix.product }}
- name: Run Forge snapshot
- if: ${{ !contains(fromJson('["vrf"]'), matrix.product) && !contains(fromJson('["automation"]'), matrix.product) }}
+ if: ${{ !contains(fromJson('["vrf"]'), matrix.product) && !contains(fromJson('["automation"]'), matrix.product) && needs.changes.outputs.changes == 'true' }}
run: |
forge snapshot --nmt "testFuzz_\w{1,}?" --check gas-snapshots/${{ matrix.product }}.gas-snapshot
id: snapshot
@@ -84,7 +89,7 @@ jobs:
FOUNDRY_PROFILE: ${{ matrix.product }}
- name: Collect Metrics
- if: always()
+ if: needs.changes.outputs.changes == 'true'
id: collect-gha-metrics
uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml
index 782dc93a0f..069d9de45a 100644
--- a/.github/workflows/solidity.yml
+++ b/.github/workflows/solidity.yml
@@ -24,6 +24,7 @@ jobs:
src:
- 'contracts/**/*'
- '.github/workflows/solidity.yml'
+ - '.github/workflows/solidity-foundry.yml'
prepublish-test:
needs: [changes]
@@ -91,24 +92,29 @@ jobs:
this-job-name: Native Compilation
continue-on-error: true
+ # The if statements for steps after checkout repo is a workaround for
+ # passing required check for PRs that don't have filtered changes.
lint:
defaults:
run:
working-directory: contracts
needs: [changes]
- if: needs.changes.outputs.changes == 'true'
name: Lint ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }}
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup NodeJS
+ if: needs.changes.outputs.changes == 'true'
uses: ./.github/actions/setup-nodejs
- name: Run pnpm lint
+ if: needs.changes.outputs.changes == 'true'
run: pnpm lint
- name: Run solhint
+ if: needs.changes.outputs.changes == 'true'
run: pnpm solhint
- name: Collect Metrics
+ if: needs.changes.outputs.changes == 'true'
id: collect-gha-metrics
uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
with:
From 44f6d388d2c85cbb199f9550c7814528a6fa412b Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Tue, 7 Nov 2023 16:37:50 -0500
Subject: [PATCH 101/327] Removes Old Needs Check (#11220)
* Removes old Needs Check
* Properly gate action
---
.github/actions/build-chainlink-image/action.yml | 2 +-
.github/workflows/integration-tests.yml | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/actions/build-chainlink-image/action.yml b/.github/actions/build-chainlink-image/action.yml
index 5041d9d1db..ac29a3d7b8 100644
--- a/.github/actions/build-chainlink-image/action.yml
+++ b/.github/actions/build-chainlink-image/action.yml
@@ -32,7 +32,7 @@ runs:
AWS_REGION: ${{ inputs.AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ inputs.AWS_ROLE_TO_ASSUME }}
- name: Build Image
- if: steps.check-image.outputs.exists == 'false' && needs.changes.outputs.src == 'true'
+ if: steps.check-image.outputs.exists == 'false'
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
with:
cl_repo: smartcontractkit/chainlink
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 4c617a00c4..ba66a53ab6 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -96,6 +96,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Build Chainlink Image
+ if: needs.changes.outputs.src == 'true'
uses: ./.github/actions/build-chainlink-image
with:
tag_suffix: ${{ matrix.image.tag-suffix }}
From 33b9d2a2e30087dea3fdb05d46c45be817ac6679 Mon Sep 17 00:00:00 2001
From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com>
Date: Wed, 8 Nov 2023 13:12:38 +0400
Subject: [PATCH 102/327] fix build-test-image action (#11225)
---
.github/actions/build-test-image/action.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml
index 683ce912ec..a241f51d92 100644
--- a/.github/actions/build-test-image/action.yml
+++ b/.github/actions/build-test-image/action.yml
@@ -55,7 +55,7 @@ runs:
file: ./integration-tests/test.Dockerfile
build-args: |
BASE_IMAGE=${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image
- IMAGE_VERSION=${{ steps.version.output.version }}
+ IMAGE_VERSION=${{ steps.version.outputs.version }}
SUITES="${{ inputs.suites }}"
AWS_REGION: ${{ inputs.QA_AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
From ea27753bc31b7454915337984773d52528c6bd55 Mon Sep 17 00:00:00 2001
From: David Cauchi <13139524+davidcauchi@users.noreply.github.com>
Date: Wed, 8 Nov 2023 10:55:38 +0100
Subject: [PATCH 103/327] Add baseFeeWei to logs (#11204)
---
.github/workflows/on-demand-ocr-soak-test.yml | 2 +-
core/chains/evm/gas/block_history_estimator.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index b6ccad2246..4ea10cd482 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -20,7 +20,7 @@ on:
- "BSC_TESTNET"
- "SCROLL_SEPOLIA"
- "SCROLL_MAINNET"
- - "MUMBAI"
+ - "POLYGON_MUMBAI"
- "POLYGON_MAINNET"
- "LINEA_GOERLI"
- "LINEA_MAINNET"
diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go
index 42c8f05153..80ae19f109 100644
--- a/core/chains/evm/gas/block_history_estimator.go
+++ b/core/chains/evm/gas/block_history_estimator.go
@@ -163,7 +163,7 @@ func (b *BlockHistoryEstimator) setLatest(head *evmtypes.Head) {
if baseFee := head.BaseFeePerGas; baseFee != nil {
promBlockHistoryEstimatorCurrentBaseFee.WithLabelValues(b.chainID.String()).Set(float64(baseFee.Int64()))
}
- b.logger.Debugw("Set latest block", "blockNum", head.Number, "blockHash", head.Hash, "baseFee", head.BaseFeePerGas)
+ b.logger.Debugw("Set latest block", "blockNum", head.Number, "blockHash", head.Hash, "baseFee", head.BaseFeePerGas, "baseFeeWei", head.BaseFeePerGas.ToInt())
b.latestMu.Lock()
defer b.latestMu.Unlock()
b.latest = head
From b5191f1a8cf391e80a2960b65170177e439beed9 Mon Sep 17 00:00:00 2001
From: ilija42 <57732589+ilija42@users.noreply.github.com>
Date: Wed, 8 Nov 2023 14:23:41 +0100
Subject: [PATCH 104/327] BCF-2749 add tests for ocr enhancedTelemetry service
creation (#11206)
* Add Enhanced telemetry is disabled log to newServicesMercury delegate
* Add test to check if eaTelemetry service was created in ocr servicseForSpec based on ocr spec flag
---
core/services/job/runner_integration_test.go | 68 ++++++++++++++++++++
core/services/ocr2/delegate.go | 2 +
2 files changed, 70 insertions(+)
diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go
index 7e8ed5e87f..deb4bff6b0 100644
--- a/core/services/job/runner_integration_test.go
+++ b/core/services/job/runner_integration_test.go
@@ -528,6 +528,74 @@ answer1 [type=median index=0];
require.NoError(t, err)
})
+ t.Run("test enhanced telemetry service creation", func(t *testing.T) {
+ testCases := []struct {
+ jbCaptureEATelemetry bool
+ specCaptureEATelemetry bool
+ expected bool
+ }{{false, false, false},
+ {true, false, false},
+ {false, true, true},
+ {true, true, true},
+ }
+
+ for _, tc := range testCases {
+
+ config = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ c.P2P.V1.Enabled = ptr(true)
+ c.OCR.CaptureEATelemetry = ptr(tc.specCaptureEATelemetry)
+ })
+
+ relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore})
+ legacyChains = evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders)
+
+ kb, err := keyStore.OCR().Create()
+ require.NoError(t, err)
+
+ s := fmt.Sprintf(minimalNonBootstrapTemplate, cltest.NewEIP55Address(), transmitterAddress.Hex(), kb.ID(), "http://blah.com", "")
+ jb, err := ocr.ValidatedOracleSpecToml(legacyChains, s)
+ require.NoError(t, err)
+ err = toml.Unmarshal([]byte(s), &jb)
+ require.NoError(t, err)
+
+ jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s"))
+ err = jobORM.CreateJob(&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)
+ require.NoError(t, pw.Start(testutils.Context(t)))
+ sd := ocr.NewDelegate(
+ db,
+ jobORM,
+ keyStore,
+ nil,
+ pw,
+ monitoringEndpoint,
+ legacyChains,
+ lggr,
+ config.Database(),
+ srvctest.Start(t, utils.NewMailboxMonitor(t.Name())),
+ )
+
+ jb.OCROracleSpec.CaptureEATelemetry = tc.jbCaptureEATelemetry
+ services, err := sd.ServicesForSpec(jb)
+ require.NoError(t, err)
+
+ enhancedTelemetryServiceCreated := false
+ for _, service := range services {
+ _, ok := service.(*ocrcommon.EnhancedTelemetryService[ocrcommon.EnhancedTelemetryData])
+ enhancedTelemetryServiceCreated = ok
+ if enhancedTelemetryServiceCreated {
+ break
+ }
+ }
+
+ require.Equal(t, tc.expected, enhancedTelemetryServiceCreated)
+ }
+ })
+
t.Run("test job spec error is created", func(t *testing.T) {
// Create a keystore with an ocr key bundle and p2p key.
kb, err := keyStore.OCR().Create()
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 75147ca233..1e87915bd1 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -700,6 +700,8 @@ func (d *Delegate) newServicesMercury(
if ocrcommon.ShouldCollectEnhancedTelemetryMercury(jb) {
enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, chEnhancedTelem, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), synchronization.EnhancedEAMercury), lggr.Named("EnhancedTelemetryMercury"))
mercuryServices = append(mercuryServices, enhancedTelemService)
+ } else {
+ lggr.Infow("Enhanced telemetry is disabled for mercury job", "job", jb.Name)
}
return mercuryServices, err2
From c3e889f1456d052ec0e96af383669bb7685d3a05 Mon Sep 17 00:00:00 2001
From: Bartek Tofel
Date: Wed, 8 Nov 2023 17:00:30 +0100
Subject: [PATCH 105/327] Log poller on demand streamlining (#11231)
* move workflow to correct directory
* streamline on-demand values a bit
* get RPC urls and private keys from secrets
* download and run from inside the test folder
* checkout repo before running tests
* get inputs and mask them
* fix step ordering in workflow
* fix default image tag
* use latest pumba@CTF
* run one test
* fix directory name
* run on powerful runner
* add guide explaining how to use log poller tests
* update LP readme
---
.github/workflows/on-demand-log-poller.yml | 71 +++++---
integration-tests/LOG_POLLER.md | 163 ++++++++++++++++++
integration-tests/docker/test_env/test_env.go | 17 ++
.../reorg/log_poller_maybe_reorg_test.go | 4 +-
.../universal/log_poller/config.go | 11 +-
.../universal/log_poller/scenarios.go | 2 +-
6 files changed, 235 insertions(+), 33 deletions(-)
create mode 100644 integration-tests/LOG_POLLER.md
diff --git a/.github/workflows/on-demand-log-poller.yml b/.github/workflows/on-demand-log-poller.yml
index c5470a5a3d..42f901ec30 100644
--- a/.github/workflows/on-demand-log-poller.yml
+++ b/.github/workflows/on-demand-log-poller.yml
@@ -24,43 +24,64 @@ on:
required: true
chainlinkVersion:
description: Chainlink version to use
- default: "v2.7.0-beta0"
+ default: "2.7.0-beta1"
required: true
selectedNetworks:
- description: Network to use (only Sepolia or Mumbai)
- default: "Sepolia"
- required: true
- fundingKey:
- description: Private key used to fund the contracts (must have sufficient ETH and LINK!)
- required: true
- rpcURL:
- description: RPC URL to use
+ type: choice
+ options:
+ - "SIMULATED"
+ - "SEPOLIA"
+ - "MUMBAI"
+ fundingPrivateKey:
+ description: Private funding key (Skip for Simulated)
required: true
+ type: string
wsURL:
- description: WS URL to use
+ description: WS URL for the network (Skip for Simulated)
required: true
+ type: string
+ httpURL:
+ description: HTTP URL for the network (Skip for Simulated)
+ required: true
+ type: string
jobs:
test:
- runs-on: ubuntu-latest
+ env:
+ CONTRACTS: ${{ inputs.contracts }}
+ EVENTS_PER_TX: ${{ inputs.eventsPerTx }}
+ LOAD_DURATION: ${{ inputs.loadDuration }}
+ USE_FINALITY_TAG: ${{ inputs.useFinalityTag }}
+ CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }}
+ CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }}
+ SELECTED_NETWORKS: ${{ inputs.selectedNetworks }}
+ REF_NAME: ${{ github.head_ref || github.ref_name }}
+ runs-on: ubuntu20.04-8cores-32GB
steps:
- - uses: actions/checkout@v3
+ - name: Get Inputs
+ run: |
+ EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH)
+ EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH)
+ EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH)
+
+ echo ::add-mask::$EVM_URLS
+ echo ::add-mask::$EVM_HTTP_URLS
+ echo ::add-mask::$EVM_KEYS
+
+ echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV
+ echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV
+ echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ env.REF_NAME }}
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version-file: "integration-tests/go.mod"
cache: true
- - name: Show overrides
- env:
- CONTRACTS: ${{ inputs.contracts }}
- EVENTS_PER_TX: ${{ inputs.eventsPerTx }}
- LOAD_DURATION: ${{ inputs.loadDuration }}
- USE_FINALITY_TAG: ${{ inputs.useFinalityTag }}
- CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }}
- CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }}
- SELECTED_NETWORKS: ${{ inputs.selectedNetworks }}
- EVM_KEYS: ${{ inputs.fundingKey }}
- EVM_HTTP_URLS: ${{ inputs.rpcURL }}
- EVM_URLS: ${{ inputs.wsURL }}
+ - name: Run tests
run: |
- go test -v -timeout 5h -run=TestLogPollerFromEnv integration-tests/reorg/log_poller_maybe_reorg_test.go
\ No newline at end of file
+ cd integration-tests
+ go mod download
+ go test -v -timeout 5h -v -count=1 -run ^TestLogPollerFromEnv$ ./reorg/log_poller_maybe_reorg_test.go
diff --git a/integration-tests/LOG_POLLER.md b/integration-tests/LOG_POLLER.md
new file mode 100644
index 0000000000..6e98fba552
--- /dev/null
+++ b/integration-tests/LOG_POLLER.md
@@ -0,0 +1,163 @@
+# How to run Log Poller's tests
+
+## Limitations
+* currently they can only be run in Docker, not in Kubernetes
+* when using `looped` runner it's not possible to directly control execution time
+* WASP's `gun` implementation is imperfect in terms of generated load
+
+## Configuration
+Due to unfinished migration to TOML config tests use a mixed configuration approach:
+* network, RPC endpoints, funding keys, etc need to be provided by env vars
+* test-specific configuration can be provided by TOML file or via a `Config` struct (to which TOML is parsed anyway) additionally some of it can be overridden by env vars (for ease of use in CI)
+** smoke tests use the programmatical approach
+** load test uses the TOML approach
+
+## Approximated test scenario
+Different tests might have slightly modified scenarios, but generally they follow this pattern:
+* start CL nodes
+* setup OCR
+* upload Automation Registry 2.1
+* deploy UpKeep Consumers
+* deploy test contracts
+* register filters for test contracts
+* make sure all CL nodes have filters registered
+* emit test logs
+* wait for log poller to finalise last block in which logs were emitted
+** block number is determined either by finality tag or fixed finality depth depending on network configuration
+* wait for all CL nodes to have expected log count
+* compare logs that present in the EVM node with logs in CL nodes
+
+All of the checks use fluent waits.
+
+### Required env vars
+* `CHAINLINK_IMAGE`
+* `CHAINLINK_VERSION`
+* `SELECTED_NETWORKS`
+
+### Env vars required for live testnet tests
+* `EVM_WS_URL` -- RPC websocket
+* `EVM_HTTP_URL` -- RPC HTTP
+* `EVM_KEYS` -- private keys used for funding
+
+Since on live testnets we are using existing and canonical LINK contracts funding keys need to contain enough LINK to pay for the test. There's an automated check that fails during setup if there's not enough LINK. Approximately `9 LINK` is required for each UpKeep contract test uses to register a `LogTrigger`. Test contract emits 3 types of events and unless configured otherwise (programmatically!) all of them will be used, which means that due to Automation's limitation we need to register a separate `LogTrigger` for each event type for each contract. So if you want to test with 100 contracts, then you'd need to register 300 UpKeep contracts and thus your funding address needs to have at least 2700 LINK.
+
+### Programmatical config
+There are two load generators available:
+* `looped` -- it's a simple generator that just loops over all contracts and emits events at random intervals
+* `wasp` -- based on WASP load testing tool, it's more sophisticated and allows to control execution time
+
+#### Looped config
+```
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2, # number of test contracts to deploy
+ EventsPerTx: 4, # number of events to emit in a single transaction
+ UseFinalityTag: false, # if set to true then Log Poller will use finality tag returned by chain, when determining last finalised block (won't work on a simulated network, it requires eth2)
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100, # number of times each contract will be called
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200, # minimum number of milliseconds to wait before emitting events
+ MaxEmitWaitTimeMs: 500, # maximum number of milliseconds to wait before emitting events
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events { # modify that function to emit only logs you want
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+```
+
+Remember that final number of events emitted will be `Contracts * EventsPerTx * ExecutionCount * len(eventToEmit)`. And that that last number by default is equal to `3` (that's because we want to emit different event types, not just one). You can change that by overriding `EventsToEmit` field.
+
+#### WASP config
+```
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 4,
+ UseFinalityTag: false,
+ },
+ Wasp: &logpoller.WaspConfig{
+ Load: &logpoller.Load{
+ RPS: 10, # requests per second
+ LPS: 0, # logs per second
+ RateLimitUnitDuration: models.MustNewDuration(5 * time.Minutes), # for how long the load should be limited (ramp-up period)
+ Duration: models.MustNewDuration(5 * time.Minutes), # how long to generate the load for
+ CallTimeout: models.MustNewDuration(5 * time.Minutes), # how long to wait for a single call to finish
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+```
+
+Remember that you cannot specify both `RPS` and `LPS`. If you want to use `LPS` then omit `RPS` field. Also remember that depending on the events you decide to emit RPS might mean 1 request or might mean 3 requests (if you go with the default `EventsToEmit`).
+
+For other nuances do check [gun.go][integration-tests/universal/log_poller/gun.go].
+
+### TOML config
+That config follows the same structure as programmatical config shown above.
+
+Sample config: [config.toml](integration-tests/load/log_poller/config.toml)
+
+Use this snippet instead of creating the `Config` struct programmatically:
+```
+ cfg, err := lp_helpers.ReadConfig(lp_helpers.DefaultConfigFilename)
+ require.NoError(t, err)
+```
+
+And remember to add events you want emit:
+```
+ eventsToEmit := []abi.Event{}
+ for _, event := range lp_helpers.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+```
+
+### Timeouts
+Various checks inside the tests have hardcoded timeouts, which might not be suitable for your execution parameters, for example if you decided to emit 1M logs, then waiting for all of them to be indexed for `1m` might not be enough. Remember to adjust them accordingly.
+
+Sample snippet:
+```
+ gom.Eventually(func(g gomega.Gomega) {
+ logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), totalLogsEmitted, expectedFilters, l, coreLogger, testEnv.ClCluster)
+ if err != nil {
+ l.Warn().Err(err).Msg("Error checking if CL nodes have expected log count. Retrying...")
+ }
+ g.Expect(logCountMatches).To(gomega.BeTrue(), "Not all CL nodes have expected log count")
+ }, "1m", "30s").Should(gomega.Succeed()) # 1m is the timeout for all nodes to have expected log count
+```
+
+## Tests
+* [Load](integration-tests/load/log_poller/log_poller_test.go)
+* [Smoke](integration-tests/smoke/log_poller/log_poller_test.go)
+
+## Running tests
+After setting all the environment variables you can run the test with:
+```
+# run in the root folder of chainlink repo
+go test -v -test.timeout=2700s -run TestLogPollerReplay integration-tests/smoke/log_poller_test.go
+```
+
+Remember to adjust test timeout accordingly to match expected duration.
+
+
+## Github Actions
+If all of that seems too complicated use this [on-demand workflow](https://github.com/smartcontractkit/chainlink/actions/workflows/on-demand-log-poller.yml).
+
+Execution time here is an approximation, so depending on network conditions it might be slightly longer or shorter.
\ No newline at end of file
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index a6495bed54..b3fc1c0cf6 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -187,6 +187,8 @@ func (te *CLClusterTestEnv) Cleanup() error {
return fmt.Errorf("chainlink nodes are nil, unable cleanup chainlink nodes")
}
+ te.logWhetherAllContainersAreRunning()
+
// TODO: This is an imperfect and temporary solution, see TT-590 for a more sustainable solution
// Collect logs if the test fails, or if we just want them
if te.t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" {
@@ -216,6 +218,21 @@ func (te *CLClusterTestEnv) Cleanup() error {
return nil
}
+func (te *CLClusterTestEnv) logWhetherAllContainersAreRunning() {
+ for _, node := range te.ClCluster.Nodes {
+ isCLRunning := node.Container.IsRunning()
+ isDBRunning := node.PostgresDb.Container.IsRunning()
+
+ if !isCLRunning {
+ te.l.Warn().Str("Node", node.ContainerName).Msg("Chainlink node was not running, when test ended")
+ }
+
+ if !isDBRunning {
+ te.l.Warn().Str("Node", node.ContainerName).Msg("Postgres DB is not running, when test ended")
+ }
+ }
+}
+
// collectTestLogs collects the logs from all the Chainlink nodes in the test environment and writes them to local files
func (te *CLClusterTestEnv) collectTestLogs() error {
te.l.Info().Msg("Collecting test logs")
diff --git a/integration-tests/reorg/log_poller_maybe_reorg_test.go b/integration-tests/reorg/log_poller_maybe_reorg_test.go
index 4e802bdb09..0176fdbbdd 100644
--- a/integration-tests/reorg/log_poller_maybe_reorg_test.go
+++ b/integration-tests/reorg/log_poller_maybe_reorg_test.go
@@ -20,8 +20,8 @@ func TestLogPollerFromEnv(t *testing.T) {
ExecutionCount: 100,
},
FuzzConfig: logpoller.FuzzConfig{
- MinEmitWaitTimeMs: 800,
- MaxEmitWaitTimeMs: 1200,
+ MinEmitWaitTimeMs: 400,
+ MaxEmitWaitTimeMs: 600,
},
},
}
diff --git a/integration-tests/universal/log_poller/config.go b/integration-tests/universal/log_poller/config.go
index 623fa6606e..7297e81124 100644
--- a/integration-tests/universal/log_poller/config.go
+++ b/integration-tests/universal/log_poller/config.go
@@ -112,11 +112,12 @@ func (c *Config) OverrideFromEnv() error {
if c.General.Generator == GeneratorType_WASP {
c.Wasp.Load.Duration = &d
} else {
- // make the looped generator approximately run for desired duration
- // on average we will emit 1 event per second
- c.LoopedConfig.FuzzConfig.MinEmitWaitTimeMs = 900
- c.LoopedConfig.FuzzConfig.MaxEmitWaitTimeMs = 1100
- c.LoopedConfig.ContractConfig.ExecutionCount = int(d.Duration().Seconds())
+ // this is completely arbitrary and practice shows that even with this values
+ // test executes much longer than specified, probably due to network latency
+ c.LoopedConfig.FuzzConfig.MinEmitWaitTimeMs = 400
+ c.LoopedConfig.FuzzConfig.MaxEmitWaitTimeMs = 600
+ // divide by 4 based on past runs, but we should do it in a better way
+ c.LoopedConfig.ContractConfig.ExecutionCount = int(d.Duration().Seconds() / 4)
}
}
diff --git a/integration-tests/universal/log_poller/scenarios.go b/integration-tests/universal/log_poller/scenarios.go
index d14a3bcb2a..1110a2f8ca 100644
--- a/integration-tests/universal/log_poller/scenarios.go
+++ b/integration-tests/universal/log_poller/scenarios.go
@@ -309,7 +309,7 @@ func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string
require.Equal(t, "Replay started", response.Data.Attributes.Message, "Unexpected response message from log poller's replay")
}
- l.Warn().Str("Duration", consistencyTimeout).Msg("Waiting for logs to be processed by all nodes and for chain to advance beyond finality")
+ l.Warn().Str("Duration", consistencyTimeout).Msg("Waiting for replay logs to be processed by all nodes")
gom.Eventually(func(g gomega.Gomega) {
logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), totalLogsEmitted, expectedFilters, l, coreLogger, testEnv.ClCluster)
From 7be2d6516addfaaab435d34dfac0039cfa63479b Mon Sep 17 00:00:00 2001
From: Ilja Pavlovs
Date: Wed, 8 Nov 2023 18:40:17 +0200
Subject: [PATCH 106/327] chore/VRF-722-externalise-oracleWithdraw-address
(#11216)
* VRF-722: made eoa address configurable which is used for VRF Key registration in VRF super scripts
* VRF-722: PR comments
---
core/scripts/common/vrf/model/model.go | 5 ++
core/scripts/common/vrf/setup-envs/README.md | 4 +-
core/scripts/common/vrf/setup-envs/main.go | 27 +++++---
core/scripts/vrfv2/testnet/README.md | 16 +++--
.../vrfv2/testnet/v2scripts/super_scripts.go | 54 +++++++++-------
core/scripts/vrfv2plus/testnet/README.md | 11 +++-
.../testnet/v2plusscripts/super_scripts.go | 63 ++++++++++++-------
7 files changed, 117 insertions(+), 63 deletions(-)
diff --git a/core/scripts/common/vrf/model/model.go b/core/scripts/common/vrf/model/model.go
index bd0e3bbe36..42deb42453 100644
--- a/core/scripts/common/vrf/model/model.go
+++ b/core/scripts/common/vrf/model/model.go
@@ -44,3 +44,8 @@ type ContractAddresses struct {
CoordinatorAddress common.Address
BatchCoordinatorAddress common.Address
}
+
+type VRFKeyRegistrationConfig struct {
+ VRFKeyUncompressedPubKey string
+ RegisterAgainstAddress string
+}
diff --git a/core/scripts/common/vrf/setup-envs/README.md b/core/scripts/common/vrf/setup-envs/README.md
index 33515338a2..f3b391f0ee 100644
--- a/core/scripts/common/vrf/setup-envs/README.md
+++ b/core/scripts/common/vrf/setup-envs/README.md
@@ -35,7 +35,9 @@ go run . \
--min-confs=3 \
--num-eth-keys=1 \
--num-vrf-keys=1 \
---sending-key-funding-amount="1e17"
+--sending-key-funding-amount="1e17" \
+--register-vrf-key-against-address=
```
Optional parameters - will not be deployed if specified (NOT WORKING YET)
diff --git a/core/scripts/common/vrf/setup-envs/main.go b/core/scripts/common/vrf/setup-envs/main.go
index 6748408f47..7c2530ffd4 100644
--- a/core/scripts/common/vrf/setup-envs/main.go
+++ b/core/scripts/common/vrf/setup-envs/main.go
@@ -85,6 +85,8 @@ func main() {
batchBHSAddressString := flag.String("batch-bhs-address", "", "address of Batch BHS contract")
coordinatorAddressString := flag.String("coordinator-address", "", "address of VRF Coordinator contract")
batchCoordinatorAddressString := flag.String("batch-coordinator-address", "", "address Batch VRF Coordinator contract")
+ registerVRFKeyAgainstAddress := flag.String("register-vrf-key-against-address", "", "VRF Key registration against address - "+
+ "from this address you can perform `coordinator.oracleWithdraw` to withdraw earned funds from rand request fulfilments")
e := helpers.SetupEnv(false)
flag.Parse()
@@ -171,6 +173,11 @@ func main() {
BatchCoordinatorAddress: common.HexToAddress(*batchCoordinatorAddressString),
}
+ vrfKeyRegistrationConfig := model.VRFKeyRegistrationConfig{
+ VRFKeyUncompressedPubKey: nodesMap[model.VRFPrimaryNodeName].VrfKeys[0],
+ RegisterAgainstAddress: *registerVRFKeyAgainstAddress,
+ }
+
var jobSpecs model.JobSpecs
switch *vrfVersion {
@@ -188,10 +195,10 @@ func main() {
}
coordinatorConfigV2 := v2scripts.CoordinatorConfigV2{
- MinConfs: minConfs,
- MaxGasLimit: &constants.MaxGasLimit,
- StalenessSeconds: &constants.StalenessSeconds,
- GasAfterPayment: &constants.GasAfterPayment,
+ MinConfs: *minConfs,
+ MaxGasLimit: constants.MaxGasLimit,
+ StalenessSeconds: constants.StalenessSeconds,
+ GasAfterPayment: constants.GasAfterPayment,
FallbackWeiPerUnitLink: constants.FallbackWeiPerUnitLink,
FeeConfig: feeConfigV2,
}
@@ -199,7 +206,7 @@ func main() {
jobSpecs = v2scripts.VRFV2DeployUniverse(
e,
subscriptionBalanceJuels,
- &nodesMap[model.VRFPrimaryNodeName].VrfKeys[0],
+ vrfKeyRegistrationConfig,
contractAddresses,
coordinatorConfigV2,
*batchFulfillmentEnabled,
@@ -211,10 +218,10 @@ func main() {
FulfillmentFlatFeeNativePPM: uint32(constants.FlatFeeNativePPM),
}
coordinatorConfigV2Plus := v2plusscripts.CoordinatorConfigV2Plus{
- MinConfs: minConfs,
- MaxGasLimit: &constants.MaxGasLimit,
- StalenessSeconds: &constants.StalenessSeconds,
- GasAfterPayment: &constants.GasAfterPayment,
+ MinConfs: *minConfs,
+ MaxGasLimit: constants.MaxGasLimit,
+ StalenessSeconds: constants.StalenessSeconds,
+ GasAfterPayment: constants.GasAfterPayment,
FallbackWeiPerUnitLink: constants.FallbackWeiPerUnitLink,
FeeConfig: feeConfigV2Plus,
}
@@ -223,7 +230,7 @@ func main() {
e,
subscriptionBalanceJuels,
subscriptionBalanceNativeWei,
- &nodesMap[model.VRFPrimaryNodeName].VrfKeys[0],
+ vrfKeyRegistrationConfig,
contractAddresses,
coordinatorConfigV2Plus,
*batchFulfillmentEnabled,
diff --git a/core/scripts/vrfv2/testnet/README.md b/core/scripts/vrfv2/testnet/README.md
index 1b2d986f55..b527c576fd 100644
--- a/core/scripts/vrfv2/testnet/README.md
+++ b/core/scripts/vrfv2/testnet/README.md
@@ -57,11 +57,19 @@ To deploy a full VRF environment on-chain, run:
```shell
go run . deploy-universe \
---sending-key-funding-amount 100000000000000000 \
---subscription-balance=10000000000000000000 \
+--subscription-balance=5000000000000000000 \ #5 LINK
--uncompressed-pub-key= \
---vrf-primary-node-sending-keys="" \
---batch-fulfillment-enabled false
+--vrf-primary-node-sending-keys="" \ #used to fund the keys and for sample VRF Job Spec generation
+--sending-key-funding-amount 100000000000000000 \ #0.1 ETH, fund addresses specified in vrf-primary-node-sending-keys
+--batch-fulfillment-enabled false \ #only used for sample VRF Job Spec generation
+--register-vrf-key-against-address=<"from this address you can perform `coordinator.oracleWithdraw` to withdraw earned funds from rand request fulfilments>
+```
+```shell
+go run . deploy-universe \
+--subscription-balance=5000000000000000000 \
+--uncompressed-pub-key="0xf3706e247a7b205c8a8bd25a6e8c4650474da496151371085d45beeead27e568c1a5e8330c7fa718f8a31226efbff6632ed6f8ed470b637aa9be2b948e9dcef6" \
+--batch-fulfillment-enabled false \
+--register-vrf-key-against-address="0x23b5613fc04949F4A53d1cc8d6BCCD21ffc38C11"
```
## Deploying the Consumer Contract
diff --git a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
index 23ad8e1374..b623ae6308 100644
--- a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
+++ b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
@@ -26,10 +26,10 @@ import (
)
type CoordinatorConfigV2 struct {
- MinConfs *int
- MaxGasLimit *int64
- StalenessSeconds *int64
- GasAfterPayment *int64
+ MinConfs int
+ MaxGasLimit int64
+ StalenessSeconds int64
+ GasAfterPayment int64
FallbackWeiPerUnitLink *big.Int
FeeConfig vrf_coordinator_v2.VRFCoordinatorV2FeeConfig
}
@@ -52,7 +52,10 @@ func DeployUniverseViaCLI(e helpers.Environment) {
// optional flags
fallbackWeiPerUnitLinkString := deployCmd.String("fallback-wei-per-unit-link", constants.FallbackWeiPerUnitLink.String(), "fallback wei/link ratio")
- registerKeyUncompressedPubKey := deployCmd.String("uncompressed-pub-key", "", "uncompressed public key")
+ registerVRFKeyUncompressedPubKey := deployCmd.String("uncompressed-pub-key", "", "uncompressed public key")
+ registerVRFKeyAgainstAddress := deployCmd.String("register-vrf-key-against-address", "", "VRF Key registration against address - "+
+ "from this address you can perform `coordinator.oracleWithdraw` to withdraw earned funds from rand request fulfilments")
+
vrfPrimaryNodeSendingKeysString := deployCmd.String("vrf-primary-node-sending-keys", "", "VRF Primary Node sending keys")
minConfs := deployCmd.Int("min-confs", constants.MinConfs, "min confs")
@@ -119,18 +122,23 @@ func DeployUniverseViaCLI(e helpers.Environment) {
}
coordinatorConfig := CoordinatorConfigV2{
- MinConfs: minConfs,
- MaxGasLimit: maxGasLimit,
- StalenessSeconds: stalenessSeconds,
- GasAfterPayment: gasAfterPayment,
+ MinConfs: *minConfs,
+ MaxGasLimit: *maxGasLimit,
+ StalenessSeconds: *stalenessSeconds,
+ GasAfterPayment: *gasAfterPayment,
FallbackWeiPerUnitLink: fallbackWeiPerUnitLink,
FeeConfig: feeConfig,
}
+ vrfKeyRegistrationConfig := model.VRFKeyRegistrationConfig{
+ VRFKeyUncompressedPubKey: *registerVRFKeyUncompressedPubKey,
+ RegisterAgainstAddress: *registerVRFKeyAgainstAddress,
+ }
+
VRFV2DeployUniverse(
e,
subscriptionBalanceJuels,
- registerKeyUncompressedPubKey,
+ vrfKeyRegistrationConfig,
contractAddresses,
coordinatorConfig,
*batchFulfillmentEnabled,
@@ -147,7 +155,7 @@ func DeployUniverseViaCLI(e helpers.Environment) {
func VRFV2DeployUniverse(
e helpers.Environment,
subscriptionBalanceJuels *big.Int,
- registerKeyUncompressedPubKey *string,
+ vrfKeyRegistrationConfig model.VRFKeyRegistrationConfig,
contractAddresses model.ContractAddresses,
coordinatorConfig CoordinatorConfigV2,
batchFulfillmentEnabled bool,
@@ -155,14 +163,14 @@ func VRFV2DeployUniverse(
) model.JobSpecs {
var compressedPkHex string
var keyHash common.Hash
- if len(*registerKeyUncompressedPubKey) > 0 {
+ if len(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey) > 0 {
// Put key in ECDSA format
- if strings.HasPrefix(*registerKeyUncompressedPubKey, "0x") {
- *registerKeyUncompressedPubKey = strings.Replace(*registerKeyUncompressedPubKey, "0x", "04", 1)
+ if strings.HasPrefix(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, "0x") {
+ vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey = strings.Replace(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, "0x", "04", 1)
}
// Generate compressed public key and key hash
- pubBytes, err := hex.DecodeString(*registerKeyUncompressedPubKey)
+ pubBytes, err := hex.DecodeString(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey)
helpers.PanicErr(err)
pk, err := crypto.UnmarshalPubkey(pubBytes)
helpers.PanicErr(err)
@@ -217,10 +225,10 @@ func VRFV2DeployUniverse(
SetCoordinatorConfig(
e,
*coordinator,
- uint16(*coordinatorConfig.MinConfs),
- uint32(*coordinatorConfig.MaxGasLimit),
- uint32(*coordinatorConfig.StalenessSeconds),
- uint32(*coordinatorConfig.GasAfterPayment),
+ uint16(coordinatorConfig.MinConfs),
+ uint32(coordinatorConfig.MaxGasLimit),
+ uint32(coordinatorConfig.StalenessSeconds),
+ uint32(coordinatorConfig.GasAfterPayment),
coordinatorConfig.FallbackWeiPerUnitLink,
coordinatorConfig.FeeConfig,
)
@@ -228,12 +236,12 @@ func VRFV2DeployUniverse(
fmt.Println("\nConfig set, getting current config from deployed contract...")
PrintCoordinatorConfig(coordinator)
- if len(*registerKeyUncompressedPubKey) > 0 {
+ if len(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey) > 0 {
fmt.Println("\nRegistering proving key...")
//NOTE - register proving key against EOA account, and not against Oracle's sending address in other to be able
// easily withdraw funds from Coordinator contract back to EOA account
- RegisterCoordinatorProvingKey(e, *coordinator, *registerKeyUncompressedPubKey, e.Owner.From.String())
+ RegisterCoordinatorProvingKey(e, *coordinator, vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, vrfKeyRegistrationConfig.RegisterAgainstAddress)
fmt.Println("\nProving key registered, getting proving key hashes from deployed contract...")
_, _, provingKeyHashes, configErr := coordinator.GetRequestConfig(nil)
@@ -271,7 +279,7 @@ func VRFV2DeployUniverse(
contractAddresses.BatchCoordinatorAddress, //batchCoordinatorAddress
batchFulfillmentEnabled, //batchFulfillmentEnabled
compressedPkHex, //publicKey
- *coordinatorConfig.MinConfs, //minIncomingConfirmations
+ coordinatorConfig.MinConfs, //minIncomingConfirmations
e.ChainID, //evmChainID
strings.Join(util.MapToAddressArr(nodesMap[model.VRFPrimaryNodeName].SendingKeys), "\",\""), //fromAddresses
contractAddresses.CoordinatorAddress,
@@ -348,7 +356,7 @@ func VRFV2DeployUniverse(
"\nVRF Subscription Id:", subID,
"\nVRF Subscription Balance:", *subscriptionBalanceJuels,
"\nPossible VRF Request command: ",
- fmt.Sprintf("go run . eoa-load-test-request-with-metrics --consumer-address=%s --sub-id=%d --key-hash=%s --request-confirmations %d --requests 1 --runs 1 --cb-gas-limit 1_000_000", consumerAddress, subID, keyHash, *coordinatorConfig.MinConfs),
+ fmt.Sprintf("go run . eoa-load-test-request-with-metrics --consumer-address=%s --sub-id=%d --key-hash=%s --request-confirmations %d --requests 1 --runs 1 --cb-gas-limit 1_000_000", consumerAddress, subID, keyHash, coordinatorConfig.MinConfs),
"\nRetrieve Request Status: ",
fmt.Sprintf("go run . eoa-load-test-read-metrics --consumer-address=%s", consumerAddress),
"\nA node can now be configured to run a VRF job with the below job spec :\n",
diff --git a/core/scripts/vrfv2plus/testnet/README.md b/core/scripts/vrfv2plus/testnet/README.md
index b95ec99d5f..6402569c56 100644
--- a/core/scripts/vrfv2plus/testnet/README.md
+++ b/core/scripts/vrfv2plus/testnet/README.md
@@ -58,7 +58,16 @@ cd /core/scripts/vrfv2/testnet
- Not specifying `--link-eth-feed` would make the super script deploy a new LINK-ETH feed contract and use it for funding VRF V2+ subscription
```shell
-go run . deploy-universe --link-address=$LINK --link-eth-feed=$LINK_ETH_FEED --subscription-balance= --uncompressed-pub-key=$PUB_KEY --oracle-address=$ORACLE_ADDRESS
+go run . deploy-universe \
+--link-address=$LINK \
+--link-eth-feed=$LINK_ETH_FEED \
+--subscription-balance=5000000000000000000 \ #5 LINK
+--subscription-balance-native=1000000000000000000 \ #1 ETH
+--uncompressed-pub-key= \
+--vrf-primary-node-sending-keys="" \ #used to fund the keys and for sample VRF Job Spec generation
+--sending-key-funding-amount 100000000000000000 \ #0.1 ETH, fund addresses specified in vrf-primary-node-sending-keys
+--batch-fulfillment-enabled false \ #only used for sample VRF Job Spec generation
+--register-vrf-key-against-address="" # from this address you can perform `coordinator.oracleWithdraw` to withdraw earned funds from rand request fulfilments
```
## Deploying the Consumer Contract
diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
index 752e06bbb2..50584d885a 100644
--- a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
+++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
@@ -39,10 +39,10 @@ import (
var coordinatorV2PlusABI = evmtypes.MustGetABI(vrf_coordinator_v2plus_interface.IVRFCoordinatorV2PlusInternalABI)
type CoordinatorConfigV2Plus struct {
- MinConfs *int
- MaxGasLimit *int64
- StalenessSeconds *int64
- GasAfterPayment *int64
+ MinConfs int
+ MaxGasLimit int64
+ StalenessSeconds int64
+ GasAfterPayment int64
FallbackWeiPerUnitLink *big.Int
FeeConfig vrf_coordinator_v2_5.VRFCoordinatorV25FeeConfig
}
@@ -481,7 +481,10 @@ func DeployUniverseViaCLI(e helpers.Environment) {
// optional flags
fallbackWeiPerUnitLinkString := deployCmd.String("fallback-wei-per-unit-link", "6e16", "fallback wei/link ratio")
- registerKeyUncompressedPubKey := deployCmd.String("uncompressed-pub-key", "", "uncompressed public key")
+ registerVRFKeyUncompressedPubKey := deployCmd.String("uncompressed-pub-key", "", "uncompressed public key")
+ registerVRFKeyAgainstAddress := deployCmd.String("register-vrf-key-against-address", "", "VRF Key registration against address - "+
+ "from this address you can perform `coordinator.oracleWithdraw` to withdraw earned funds from rand request fulfilments")
+
vrfPrimaryNodeSendingKeysString := deployCmd.String("vrf-primary-node-sending-keys", "", "VRF Primary Node sending keys")
minConfs := deployCmd.Int("min-confs", constants.MinConfs, "min confs")
nodeSendingKeyFundingAmount := deployCmd.String("sending-key-funding-amount", constants.NodeSendingKeyFundingAmount, "CL node sending key funding amount")
@@ -505,10 +508,17 @@ func DeployUniverseViaCLI(e helpers.Environment) {
FulfillmentFlatFeeNativePPM: uint32(*flatFeeEthPPM),
}
- vrfPrimaryNodeSendingKeys := strings.Split(*vrfPrimaryNodeSendingKeysString, ",")
+ var vrfPrimaryNodeSendingKeys []string
+ if len(*vrfPrimaryNodeSendingKeysString) > 0 {
+ vrfPrimaryNodeSendingKeys = strings.Split(*vrfPrimaryNodeSendingKeysString, ",")
+ }
nodesMap := make(map[string]model.Node)
+ fundingAmount, ok := new(big.Int).SetString(*nodeSendingKeyFundingAmount, 10)
+ if !ok {
+ panic(fmt.Sprintf("failed to parse node sending key funding amount '%s'", *nodeSendingKeyFundingAmount))
+ }
nodesMap[model.VRFPrimaryNodeName] = model.Node{
SendingKeys: util.MapToSendingKeyArr(vrfPrimaryNodeSendingKeys),
SendingKeyFundingAmount: fundingAmount,
@@ -529,19 +539,24 @@ func DeployUniverseViaCLI(e helpers.Environment) {
}
coordinatorConfig := CoordinatorConfigV2Plus{
- MinConfs: minConfs,
- MaxGasLimit: maxGasLimit,
- StalenessSeconds: stalenessSeconds,
- GasAfterPayment: gasAfterPayment,
+ MinConfs: *minConfs,
+ MaxGasLimit: *maxGasLimit,
+ StalenessSeconds: *stalenessSeconds,
+ GasAfterPayment: *gasAfterPayment,
FallbackWeiPerUnitLink: fallbackWeiPerUnitLink,
FeeConfig: feeConfig,
}
+ vrfKeyRegistrationConfig := model.VRFKeyRegistrationConfig{
+ VRFKeyUncompressedPubKey: *registerVRFKeyUncompressedPubKey,
+ RegisterAgainstAddress: *registerVRFKeyAgainstAddress,
+ }
+
VRFV2PlusDeployUniverse(
e,
subscriptionBalanceJuels,
subscriptionBalanceNativeWei,
- registerKeyUncompressedPubKey,
+ vrfKeyRegistrationConfig,
contractAddresses,
coordinatorConfig,
*batchFulfillmentEnabled,
@@ -558,7 +573,7 @@ func DeployUniverseViaCLI(e helpers.Environment) {
func VRFV2PlusDeployUniverse(e helpers.Environment,
subscriptionBalanceJuels *big.Int,
subscriptionBalanceNativeWei *big.Int,
- registerKeyUncompressedPubKey *string,
+ vrfKeyRegistrationConfig model.VRFKeyRegistrationConfig,
contractAddresses model.ContractAddresses,
coordinatorConfig CoordinatorConfigV2Plus,
batchFulfillmentEnabled bool,
@@ -566,14 +581,14 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
) model.JobSpecs {
var compressedPkHex string
var keyHash common.Hash
- if len(*registerKeyUncompressedPubKey) > 0 {
+ if len(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey) > 0 {
// Put key in ECDSA format
- if strings.HasPrefix(*registerKeyUncompressedPubKey, "0x") {
- *registerKeyUncompressedPubKey = strings.Replace(*registerKeyUncompressedPubKey, "0x", "04", 1)
+ if strings.HasPrefix(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, "0x") {
+ vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey = strings.Replace(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, "0x", "04", 1)
}
// Generate compressed public key and key hash
- pubBytes, err := hex.DecodeString(*registerKeyUncompressedPubKey)
+ pubBytes, err := hex.DecodeString(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey)
helpers.PanicErr(err)
pk, err := crypto.UnmarshalPubkey(pubBytes)
helpers.PanicErr(err)
@@ -628,10 +643,10 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
SetCoordinatorConfig(
e,
*coordinator,
- uint16(*coordinatorConfig.MinConfs),
- uint32(*coordinatorConfig.MaxGasLimit),
- uint32(*coordinatorConfig.StalenessSeconds),
- uint32(*coordinatorConfig.GasAfterPayment),
+ uint16(coordinatorConfig.MinConfs),
+ uint32(coordinatorConfig.MaxGasLimit),
+ uint32(coordinatorConfig.StalenessSeconds),
+ uint32(coordinatorConfig.GasAfterPayment),
coordinatorConfig.FallbackWeiPerUnitLink,
coordinatorConfig.FeeConfig,
)
@@ -639,12 +654,12 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
fmt.Println("\nConfig set, getting current config from deployed contract...")
PrintCoordinatorConfig(coordinator)
- if len(*registerKeyUncompressedPubKey) > 0 {
+ if len(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey) > 0 {
fmt.Println("\nRegistering proving key...")
//NOTE - register proving key against EOA account, and not against Oracle's sending address in other to be able
// easily withdraw funds from Coordinator contract back to EOA account
- RegisterCoordinatorProvingKey(e, *coordinator, *registerKeyUncompressedPubKey, e.Owner.From.String())
+ RegisterCoordinatorProvingKey(e, *coordinator, vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, vrfKeyRegistrationConfig.RegisterAgainstAddress)
fmt.Println("\nProving key registered, getting proving key hashes from deployed contract...")
_, _, provingKeyHashes, configErr := coordinator.GetRequestConfig(nil)
@@ -690,7 +705,7 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
contractAddresses.BatchCoordinatorAddress, //batchCoordinatorAddress
batchFulfillmentEnabled, //batchFulfillmentEnabled
compressedPkHex, //publicKey
- *coordinatorConfig.MinConfs, //minIncomingConfirmations
+ coordinatorConfig.MinConfs, //minIncomingConfirmations
e.ChainID, //evmChainID
strings.Join(util.MapToAddressArr(nodesMap[model.VRFPrimaryNodeName].SendingKeys), "\",\""), //fromAddresses
contractAddresses.CoordinatorAddress,
@@ -768,7 +783,7 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
"\nVRF Subscription LINK Balance:", *subscriptionBalanceJuels,
"\nVRF Subscription Native Balance:", *subscriptionBalanceNativeWei,
"\nPossible VRF Request command: ",
- fmt.Sprintf("go run . eoa-load-test-request-with-metrics --consumer-address=%s --sub-id=%d --key-hash=%s --request-confirmations %d --requests 1 --runs 1 --cb-gas-limit 1_000_000", consumerAddress, subID, keyHash, *coordinatorConfig.MinConfs),
+ fmt.Sprintf("go run . eoa-load-test-request-with-metrics --consumer-address=%s --sub-id=%d --key-hash=%s --request-confirmations %d --requests 1 --runs 1 --cb-gas-limit 1_000_000", consumerAddress, subID, keyHash, coordinatorConfig.MinConfs),
"\nRetrieve Request Status: ",
fmt.Sprintf("go run . eoa-load-test-read-metrics --consumer-address=%s", consumerAddress),
"\nA node can now be configured to run a VRF job with the below job spec :\n",
From c80fb93bc127b0021d4d2f98ff64001154661c54 Mon Sep 17 00:00:00 2001
From: Lei
Date: Wed, 8 Nov 2023 08:52:15 -0800
Subject: [PATCH 107/327] remove duplicate contracts (#11127)
---
.../native_solc_compile_all_automation | 2 -
.../automation/testhelpers/KeeperBase.sol | 21 ----------
.../testhelpers/KeeperCompatibleInterface.sol | 42 -------------------
.../automation/testhelpers/KeeperConsumer.sol | 4 +-
.../testhelpers/PerformDataChecker.sol | 2 +-
.../keeper_consumer_wrapper.go | 4 +-
...rapper-dependency-versions-do-not-edit.txt | 11 +----
7 files changed, 6 insertions(+), 80 deletions(-)
delete mode 100644 contracts/src/v0.8/automation/testhelpers/KeeperBase.sol
delete mode 100644 contracts/src/v0.8/automation/testhelpers/KeeperCompatibleInterface.sol
diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation
index beb557de12..1c54d67713 100755
--- a/contracts/scripts/native_solc_compile_all_automation
+++ b/contracts/scripts/native_solc_compile_all_automation
@@ -63,8 +63,6 @@ compileContract automation/v2_1/AutomationForwarderLogic.sol
compileContract automation/testhelpers/LogTriggeredStreamsLookup.sol
compileContract automation/testhelpers/DummyProtocol.sol
-compileContract automation/testhelpers/KeeperBase.sol
-compileContract automation/testhelpers/KeeperCompatibleInterface.sol
compileContract automation/testhelpers/KeeperConsumer.sol
compileContract automation/testhelpers/KeeperConsumerPerformance.sol
compileContract automation/testhelpers/PerformDataChecker.sol
diff --git a/contracts/src/v0.8/automation/testhelpers/KeeperBase.sol b/contracts/src/v0.8/automation/testhelpers/KeeperBase.sol
deleted file mode 100644
index 6fe41607f7..0000000000
--- a/contracts/src/v0.8/automation/testhelpers/KeeperBase.sol
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity 0.8.16;
-
-contract KeeperBase {
- /**
- * @notice method that allows it to be simulated via eth_call by checking that
- * the sender is the zero address.
- */
- function preventExecution() internal view {
- require(tx.origin == address(0), "only for simulated backend");
- }
-
- /**
- * @notice modifier that allows it to be simulated via eth_call by checking
- * that the sender is the zero address.
- */
- modifier cannotExecute() {
- preventExecution();
- _;
- }
-}
diff --git a/contracts/src/v0.8/automation/testhelpers/KeeperCompatibleInterface.sol b/contracts/src/v0.8/automation/testhelpers/KeeperCompatibleInterface.sol
deleted file mode 100644
index 113f5ef6a5..0000000000
--- a/contracts/src/v0.8/automation/testhelpers/KeeperCompatibleInterface.sol
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-License-Identifier: MIT
-
-pragma solidity 0.8.16;
-
-interface KeeperCompatibleInterface {
- /**
- * @notice method that is simulated by the keepers to see if any work actually
- * needs to be performed. This method does does not actually need to be
- * executable, and since it is only ever simulated it can consume lots of gas.
- * @dev To ensure that it is never called, you may want to add the
- * cannotExecute modifier from KeeperBase to your implementation of this
- * method.
- * @param checkData specified in the upkeep registration so it is always the
- * same for a registered upkeep. This can easily be broken down into specific
- * arguments using `abi.decode`, so multiple upkeeps can be registered on the
- * same contract and easily differentiated by the contract.
- * @return upkeepNeeded boolean to indicate whether the keeper should call
- * performUpkeep or not.
- * @return performData bytes that the keeper should call performUpkeep with, if
- * upkeep is needed. If you would like to encode data to decode later, try
- * `abi.encode`.
- */
- function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
-
- /**
- * @notice method that is actually executed by the keepers, via the registry.
- * The data returned by the checkUpkeep simulation will be passed into
- * this method to actually be executed.
- * @dev The input to this method should not be trusted, and the caller of the
- * method should not even be restricted to any single registry. Anyone should
- * be able call it, and the input should be validated, there is no guarantee
- * that the data passed in is the performData returned from checkUpkeep. This
- * could happen due to malicious keepers, racing keepers, or simply a state
- * change while the performUpkeep transaction is waiting for confirmation.
- * Always validate the data passed in.
- * @param performData is the data which was passed back from the checkData
- * simulation. If it is encoded, it can easily be decoded into other types by
- * calling `abi.decode`. This data should not be trusted, and should be
- * validated against the contract's current state.
- */
- function performUpkeep(bytes calldata performData) external;
-}
diff --git a/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol b/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol
index ba4694234a..fb492f376c 100644
--- a/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol
+++ b/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol
@@ -1,7 +1,7 @@
pragma solidity 0.8.16;
-import "./KeeperCompatibleInterface.sol";
-import "./KeeperBase.sol";
+import "../interfaces/KeeperCompatibleInterface.sol";
+import "../KeeperBase.sol";
contract KeeperConsumer is KeeperCompatibleInterface, KeeperBase {
uint public counter;
diff --git a/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol b/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol
index 03c57ea8e4..268942f931 100644
--- a/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol
+++ b/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
-import "./KeeperCompatibleInterface.sol";
+import "../interfaces/KeeperCompatibleInterface.sol";
contract PerformDataChecker is KeeperCompatibleInterface {
uint256 public counter;
diff --git a/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go b/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go
index 8a4ee2c4de..feb614aa83 100644
--- a/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go
+++ b/core/gethwrappers/generated/keeper_consumer_wrapper/keeper_consumer_wrapper.go
@@ -29,8 +29,8 @@ var (
)
var KeeperConsumerMetaData = &bind.MetaData{
- ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"updateInterval\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTimeStamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x60a060405234801561001057600080fd5b5060405161036c38038061036c83398101604081905261002f9161003f565b6080524260015560008055610058565b60006020828403121561005157600080fd5b5051919050565b6080516102fa610072600039600060cc01526102fa6000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806361bc221a1161005057806361bc221a1461009d5780636e04ff0d146100a6578063947a36fb146100c757600080fd5b80633f3b3b271461006c5780634585e33b14610088575b600080fd5b61007560015481565b6040519081526020015b60405180910390f35b61009b6100963660046101c5565b6100ee565b005b61007560005481565b6100b96100b43660046101c5565b610103565b60405161007f929190610237565b6100757f000000000000000000000000000000000000000000000000000000000000000081565b6000546100fc9060016102ad565b6000555050565b6000606061010f610157565b6001848481818080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250959a92995091975050505050505050565b32156101c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920666f722073696d756c61746564206261636b656e64000000000000604482015260640160405180910390fd5b565b600080602083850312156101d857600080fd5b823567ffffffffffffffff808211156101f057600080fd5b818501915085601f83011261020457600080fd5b81358181111561021357600080fd5b86602082850101111561022557600080fd5b60209290920196919550909350505050565b821515815260006020604081840152835180604085015260005b8181101561026d57858101830151858201606001528201610251565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b808201808211156102e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000810000a",
+ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"updateInterval\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTimeStamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ Bin: "0x60a060405234801561001057600080fd5b5060405161033838038061033883398101604081905261002f9161003f565b6080524260015560008055610058565b60006020828403121561005157600080fd5b5051919050565b6080516102c6610072600039600060cc01526102c66000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806361bc221a1161005057806361bc221a1461009d5780636e04ff0d146100a6578063947a36fb146100c757600080fd5b80633f3b3b271461006c5780634585e33b14610088575b600080fd5b61007560015481565b6040519081526020015b60405180910390f35b61009b610096366004610191565b6100ee565b005b61007560005481565b6100b96100b4366004610191565b610103565b60405161007f929190610203565b6100757f000000000000000000000000000000000000000000000000000000000000000081565b6000546100fc906001610279565b6000555050565b6000606061010f610157565b6001848481818080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250959a92995091975050505050505050565b321561018f576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600080602083850312156101a457600080fd5b823567ffffffffffffffff808211156101bc57600080fd5b818501915085601f8301126101d057600080fd5b8135818111156101df57600080fd5b8660208285010111156101f157600080fd5b60209290920196919550909350505050565b821515815260006020604081840152835180604085015260005b818110156102395785810183015185820160600152820161021d565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b808201808211156102b3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000810000a",
}
var KeeperConsumerABI = KeeperConsumerMetaData.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 a14b461fa7..6482c01cf8 100644
--- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -1,10 +1,4 @@
GETH_VERSION: 1.12.0
-KeeperConsumer: ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.bin 53d7902867ce421641ffa9de63204b89ab9dc157b93f0beb9ac08c6450365a70
-KeeperConsumerPerformance: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90
-PerformDataChecker: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73
-UpkeepCounter: ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.bin 77f000229a501f638dd2dc439859257f632894c728b31e68aea4f6d6c52f1b71
-UpkeepPerformCounterRestrictive: ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin 20955b21acceb58355fa287b29194a73edf5937067ba7140667301017cb2b24c
-VRFv2Consumer: ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.abi ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer.bin 12368b3b5e06392440143a13b94c0ea2f79c4c897becc3b060982559e10ace40
aggregator_v2v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.bin 95e8814b408bb05bf21742ef580d98698b7db6a9bac6a35c3de12b23aec4ee28
aggregator_v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.bin 351b55d3b0f04af67db6dfb5c92f1c64479400ca1fec77afc20bc0ce65cb49ab
authorized_forwarder: ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin 8ea76c883d460f8353a45a493f2aebeb5a2d9a7b4619d1bc4fff5fb590bb3e10
@@ -24,14 +18,12 @@ cron_upkeep_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeep.ab
dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.bin 583a448170b13abf7ed64e406e8177d78c9e55ab44efd141eee60de23a71ee3b
flags_wrapper: ../../contracts/solc/v0.6/Flags/Flags.abi ../../contracts/solc/v0.6/Flags/Flags.bin 2034d1b562ca37a63068851915e3703980276e8d5f7db6db8a3351a49d69fc4a
flux_aggregator_wrapper: ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.bin a3b0a6396c4aa3b5ee39b3c4bd45efc89789d4859379a8a92caca3a0496c5794
-functions_billing_registry_events_mock: ../../contracts/solc/v0.8.6/FunctionsBillingRegistryEventsMock/FunctionsBillingRegistryEventsMock.abi ../../contracts/solc/v0.8.6/FunctionsBillingRegistryEventsMock/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
-functions_oracle_events_mock: ../../contracts/solc/v0.8.6/FunctionsOracleEventsMock/FunctionsOracleEventsMock.abi ../../contracts/solc/v0.8.6/FunctionsOracleEventsMock/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
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_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin 6501bb9bcf5048bab2737b00685c6984a24867e234ddf5b60a65904eee9a4ebc
i_log_automation: ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.bin 296beccb6af655d6fc3a6e676b244831cce2da6688d3afc4f21f8738ae59e03e
keeper_consumer_performance_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90
-keeper_consumer_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.bin 53d7902867ce421641ffa9de63204b89ab9dc157b93f0beb9ac08c6450365a70
+keeper_consumer_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.abi ../../contracts/solc/v0.8.16/KeeperConsumer/KeeperConsumer.bin 2c6163b145082fbab74b7343577a9cec8fda8b0da9daccf2a82581b1f5a84b83
keeper_registrar_wrapper1_2: ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.bin e49b2f8b23da17af1ed2209b8ae0968cc04350554d636711e6c24a3ad3118692
keeper_registrar_wrapper1_2_mock: ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.bin 5b155a7cb3def309fd7525de1d7cd364ebf8491bdc3060eac08ea0ff55ab29bc
keeper_registrar_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistrar2_0/KeeperRegistrar2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistrar2_0/KeeperRegistrar2_0.bin 647f125c2f0dafabcdc545cb77b15dc2ec3ea9429357806813179b1fd555c2d2
@@ -84,7 +76,6 @@ vrf_coordinator_mock: ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordina
vrf_coordinator_v2: ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.bin 295f35ce282060317dfd01f45959f5a2b05ba26913e422fbd4fb6bf90b107006
vrf_coordinator_v2_5: ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2_5/VRFCoordinatorV2_5.bin b0e7c42a30b36d9d31fa9a3f26bad7937152e3dddee5bd8dd3d121390c879ab6
vrf_coordinator_v2_plus_v2_example: ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus_V2Example/VRFCoordinatorV2Plus_V2Example.bin 4a5b86701983b1b65f0a8dfa116b3f6d75f8f706fa274004b57bdf5992e4cec3
-vrf_coordinator_v2plus: ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2Plus.bin e4409bbe361258273458a5c99408b3d7f0cc57a2560dee91c0596cc6d6f738be
vrf_coordinator_v2plus_interface: ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.abi ../../contracts/solc/v0.8.6/IVRFCoordinatorV2PlusInternal/IVRFCoordinatorV2PlusInternal.bin 834a2ce0e83276372a0e1446593fd89798f4cf6dc95d4be0113e99fadf61558b
vrf_external_sub_owner_example: ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.abi ../../contracts/solc/v0.8.6/VRFExternalSubOwnerExample/VRFExternalSubOwnerExample.bin 14f888eb313930b50233a6f01ea31eba0206b7f41a41f6311670da8bb8a26963
vrf_load_test_external_sub_owner: ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.abi ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.bin 2097faa70265e420036cc8a3efb1f1e0836ad2d7323b295b9a26a125dbbe6c7d
From 027068e06365716c615dcbbd7bdcf462e9a228c1 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Wed, 8 Nov 2023 11:33:29 -0600
Subject: [PATCH 108/327] bump deps (#11148)
* bump deps
- github.com/go-webauthn/webauthn v0.8.6
- github.com/prometheus/common v0.45.0
- github.com/prometheus/prometheus v0.47.2
- github.com/tidwall/gjson v1.17.0
- gonum.org/v1/gonum v0.14.0
* Use UnmarshalFirst to maintain compatibility
---------
Co-authored-by: Ryan Tinianov
---
core/cbor/cbor.go | 7 +++---
core/scripts/go.mod | 20 +++++++--------
core/scripts/go.sum | 53 +++++++++++++++++-----------------------
go.mod | 20 +++++++--------
go.sum | 53 +++++++++++++++++-----------------------
integration-tests/go.mod | 22 ++++++++---------
integration-tests/go.sum | 48 ++++++++++++++++--------------------
7 files changed, 102 insertions(+), 121 deletions(-)
diff --git a/core/cbor/cbor.go b/core/cbor/cbor.go
index 754e572934..cc3f74e423 100644
--- a/core/cbor/cbor.go
+++ b/core/cbor/cbor.go
@@ -17,7 +17,7 @@ func ParseDietCBOR(b []byte) (map[string]interface{}, error) {
b = autoAddMapDelimiters(b)
var m map[interface{}]interface{}
- if err := cbor.Unmarshal(b, &m); err != nil {
+ if _, err := cbor.UnmarshalFirst(b, &m); err != nil {
return nil, err
}
@@ -38,7 +38,8 @@ func ParseDietCBOR(b []byte) (map[string]interface{}, error) {
// "top-level map" requirement of "diet" CBOR.
func ParseDietCBORToStruct(b []byte, v interface{}) error {
b = autoAddMapDelimiters(b)
- return cbor.Unmarshal(b, v)
+ _, err := cbor.UnmarshalFirst(b, v)
+ return err
}
// ParseStandardCBOR parses CBOR in "standards compliant" mode.
@@ -49,7 +50,7 @@ func ParseStandardCBOR(b []byte) (a interface{}, err error) {
if len(b) == 0 {
return nil, nil
}
- if err = cbor.Unmarshal(b, &a); err != nil {
+ if _, err = cbor.UnmarshalFirst(b, &a); err != nil {
return nil, err
}
return
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index b72d07978f..aada3850db 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -106,7 +106,7 @@ require (
github.com/fatih/color v1.15.0 // indirect
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
- github.com/fxamacker/cbor/v2 v2.4.0 // indirect
+ github.com/fxamacker/cbor/v2 v2.5.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gagliardetto/binary v0.7.1 // indirect
github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 // indirect
@@ -132,13 +132,13 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
- github.com/go-webauthn/revoke v0.1.9 // indirect
- github.com/go-webauthn/webauthn v0.8.2 // indirect
+ github.com/go-webauthn/webauthn v0.8.6 // indirect
+ github.com/go-webauthn/x v0.1.4 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.3 // indirect
- github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+ github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
@@ -146,7 +146,7 @@ require (
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
- github.com/google/go-tpm v0.3.3 // indirect
+ github.com/google/go-tpm v0.9.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect
@@ -254,7 +254,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/minio/sha256-simd v0.1.1 // indirect
@@ -289,9 +289,9 @@ require (
github.com/pressly/goose/v3 v3.15.1 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.44.0 // indirect
+ github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
- github.com/prometheus/prometheus v0.46.0 // indirect
+ github.com/prometheus/prometheus v0.47.2 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rjeczalik/notify v0.9.3 // indirect
@@ -325,7 +325,7 @@ require (
github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect
github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect
github.com/tidwall/btree v1.6.0 // indirect
- github.com/tidwall/gjson v1.16.0 // indirect
+ github.com/tidwall/gjson v1.17.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
@@ -367,7 +367,7 @@ require (
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
- gonum.org/v1/gonum v0.13.0 // indirect
+ gonum.org/v1/gonum v0.14.0 // indirect
google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index b1e62010ab..4f42c84d4e 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -391,8 +391,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
-github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
+github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
+github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gagliardetto/binary v0.6.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0=
@@ -478,10 +478,10 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
-github.com/go-webauthn/revoke v0.1.9 h1:gSJ1ckA9VaKA2GN4Ukp+kiGTk1/EXtaDb1YE8RknbS0=
-github.com/go-webauthn/revoke v0.1.9/go.mod h1:j6WKPnv0HovtEs++paan9g3ar46gm1NarktkXBaPR+w=
-github.com/go-webauthn/webauthn v0.8.2 h1:8KLIbpldjz9KVGHfqEgJNbkhd7bbRXhNw4QWFJE15oA=
-github.com/go-webauthn/webauthn v0.8.2/go.mod h1:d+ezx/jMCNDiqSMzOchuynKb9CVU1NM9BumOnokfcVQ=
+github.com/go-webauthn/webauthn v0.8.6 h1:bKMtL1qzd2WTFkf1mFTVbreYrwn7dsYmEPjTq6QN90E=
+github.com/go-webauthn/webauthn v0.8.6/go.mod h1:emwVLMCI5yx9evTTvr0r+aOZCdWJqMfbRhF0MufyUog=
+github.com/go-webauthn/x v0.1.4 h1:sGmIFhcY70l6k7JIDfnjVBiAAFEssga5lXIUXe0GtAs=
+github.com/go-webauthn/x v0.1.4/go.mod h1:75Ug0oK6KYpANh5hDOanfDI+dvPWHk788naJVG/37H8=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
@@ -499,9 +499,12 @@ github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q8
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
+github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
@@ -567,12 +570,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
-github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
-github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
-github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo=
-github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4=
-github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0=
-github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4=
+github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
+github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -626,7 +625,6 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
@@ -1180,8 +1178,8 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
@@ -1388,16 +1386,16 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
+github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/prometheus/prometheus v0.46.0 h1:9JSdXnsuT6YsbODEhSQMwxNkGwPExfmzqG73vCMk/Kw=
-github.com/prometheus/prometheus v0.46.0/go.mod h1:10L5IJE5CEsjee1FnOcVswYXlPIscDWWt3IJ2UDYrz4=
+github.com/prometheus/prometheus v0.47.2 h1:jWcnuQHz1o1Wu3MZ6nMJDuTI0kU5yJp9pkxh8XEkNvI=
+github.com/prometheus/prometheus v0.47.2/go.mod h1:J/bmOSjgH7lFxz2gZhrWEZs2i64vMS+HIuZfmYNhJ/M=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
@@ -1507,7 +1505,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
@@ -1518,7 +1515,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
-github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
@@ -1565,8 +1561,8 @@ github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
-github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
-github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
+github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -1814,7 +1810,6 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -1869,8 +1864,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
-golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
+golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
+golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1957,7 +1952,6 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2089,8 +2083,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
-gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
+gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
+gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -2176,7 +2170,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
diff --git a/go.mod b/go.mod
index cd0fb0fab4..e6af9533dc 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
github.com/esote/minmaxheap v1.0.0
github.com/ethereum/go-ethereum v1.12.0
github.com/fatih/color v1.15.0
- github.com/fxamacker/cbor/v2 v2.4.0
+ github.com/fxamacker/cbor/v2 v2.5.0
github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27
github.com/getsentry/sentry-go v0.19.0
github.com/gin-contrib/cors v1.4.0
@@ -22,7 +22,7 @@ require (
github.com/gin-contrib/sessions v0.0.5
github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4
github.com/gin-gonic/gin v1.9.1
- github.com/go-webauthn/webauthn v0.8.2
+ github.com/go-webauthn/webauthn v0.8.6
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8
github.com/google/uuid v1.3.1
github.com/gorilla/securecookie v1.1.1
@@ -57,8 +57,8 @@ require (
github.com/pressly/goose/v3 v3.15.1
github.com/prometheus/client_golang v1.17.0
github.com/prometheus/client_model v0.5.0
- github.com/prometheus/common v0.44.0
- github.com/prometheus/prometheus v0.46.0
+ github.com/prometheus/common v0.45.0
+ github.com/prometheus/prometheus v0.47.2
github.com/robfig/cron/v3 v3.0.1
github.com/rogpeppe/go-internal v1.11.0
github.com/scylladb/go-reflectx v1.0.1
@@ -79,7 +79,7 @@ require (
github.com/spf13/cast v1.5.1
github.com/stretchr/testify v1.8.4
github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a
- github.com/tidwall/gjson v1.16.0
+ github.com/tidwall/gjson v1.17.0
github.com/ugorji/go/codec v1.2.11
github.com/ulule/limiter/v3 v3.11.2
github.com/umbracle/ethgo v0.1.3
@@ -96,7 +96,7 @@ require (
golang.org/x/text v0.13.0
golang.org/x/time v0.3.0
golang.org/x/tools v0.14.0
- gonum.org/v1/gonum v0.13.0
+ gonum.org/v1/gonum v0.14.0
google.golang.org/grpc v1.58.3
google.golang.org/protobuf v1.31.0
gopkg.in/guregu/null.v2 v2.1.2
@@ -182,13 +182,13 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
- github.com/go-webauthn/revoke v0.1.9 // indirect
+ github.com/go-webauthn/x v0.1.4 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.3.1+incompatible // indirect
github.com/gogo/protobuf v1.3.3 // indirect
- github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+ github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
@@ -196,7 +196,7 @@ require (
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
- github.com/google/go-tpm v0.3.3 // indirect
+ github.com/google/go-tpm v0.9.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/gorilla/context v1.1.1 // indirect
@@ -287,7 +287,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/minio/sha256-simd v0.1.1 // indirect
diff --git a/go.sum b/go.sum
index fb97398f84..5c70c22a75 100644
--- a/go.sum
+++ b/go.sum
@@ -386,8 +386,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
-github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
+github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
+github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gagliardetto/binary v0.6.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0=
@@ -475,10 +475,10 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
-github.com/go-webauthn/revoke v0.1.9 h1:gSJ1ckA9VaKA2GN4Ukp+kiGTk1/EXtaDb1YE8RknbS0=
-github.com/go-webauthn/revoke v0.1.9/go.mod h1:j6WKPnv0HovtEs++paan9g3ar46gm1NarktkXBaPR+w=
-github.com/go-webauthn/webauthn v0.8.2 h1:8KLIbpldjz9KVGHfqEgJNbkhd7bbRXhNw4QWFJE15oA=
-github.com/go-webauthn/webauthn v0.8.2/go.mod h1:d+ezx/jMCNDiqSMzOchuynKb9CVU1NM9BumOnokfcVQ=
+github.com/go-webauthn/webauthn v0.8.6 h1:bKMtL1qzd2WTFkf1mFTVbreYrwn7dsYmEPjTq6QN90E=
+github.com/go-webauthn/webauthn v0.8.6/go.mod h1:emwVLMCI5yx9evTTvr0r+aOZCdWJqMfbRhF0MufyUog=
+github.com/go-webauthn/x v0.1.4 h1:sGmIFhcY70l6k7JIDfnjVBiAAFEssga5lXIUXe0GtAs=
+github.com/go-webauthn/x v0.1.4/go.mod h1:75Ug0oK6KYpANh5hDOanfDI+dvPWHk788naJVG/37H8=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
@@ -496,9 +496,12 @@ github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q8
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
+github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
@@ -564,12 +567,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
-github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
-github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
-github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo=
-github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4=
-github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0=
-github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4=
+github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
+github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -623,7 +622,6 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
@@ -1181,8 +1179,8 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
@@ -1391,16 +1389,16 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
+github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/prometheus/prometheus v0.46.0 h1:9JSdXnsuT6YsbODEhSQMwxNkGwPExfmzqG73vCMk/Kw=
-github.com/prometheus/prometheus v0.46.0/go.mod h1:10L5IJE5CEsjee1FnOcVswYXlPIscDWWt3IJ2UDYrz4=
+github.com/prometheus/prometheus v0.47.2 h1:jWcnuQHz1o1Wu3MZ6nMJDuTI0kU5yJp9pkxh8XEkNvI=
+github.com/prometheus/prometheus v0.47.2/go.mod h1:J/bmOSjgH7lFxz2gZhrWEZs2i64vMS+HIuZfmYNhJ/M=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
@@ -1509,7 +1507,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
@@ -1520,7 +1517,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
-github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
@@ -1567,8 +1563,8 @@ github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
-github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
-github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
+github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -1817,7 +1813,6 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -1873,8 +1868,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
-golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
+golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
+golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1960,7 +1955,6 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2094,8 +2088,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
-gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
+gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
+gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -2181,7 +2175,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 2ac3c38a71..8fe63a46d2 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -142,7 +142,7 @@ require (
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fvbommel/sortorder v1.0.2 // indirect
- github.com/fxamacker/cbor/v2 v2.4.0 // indirect
+ github.com/fxamacker/cbor/v2 v2.5.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gagliardetto/binary v0.7.1 // indirect
github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 // indirect
@@ -174,15 +174,15 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
- github.com/go-webauthn/revoke v0.1.9 // indirect
- github.com/go-webauthn/webauthn v0.8.2 // indirect
+ github.com/go-webauthn/webauthn v0.8.6 // indirect
+ github.com/go-webauthn/x v0.1.4 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.3 // indirect
github.com/gogo/status v1.1.1 // indirect
- github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+ github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
@@ -191,7 +191,7 @@ require (
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
- github.com/google/go-tpm v0.3.3 // indirect
+ github.com/google/go-tpm v0.9.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect
@@ -316,7 +316,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
@@ -369,11 +369,11 @@ require (
github.com/prometheus/alertmanager v0.25.1 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.44.0 // indirect
+ github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/prometheus/exporter-toolkit v0.10.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
- github.com/prometheus/prometheus v0.46.0 // indirect
+ github.com/prometheus/prometheus v0.47.2 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
@@ -409,7 +409,7 @@ require (
github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect
github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect
github.com/tidwall/btree v1.6.0 // indirect
- github.com/tidwall/gjson v1.16.0 // indirect
+ github.com/tidwall/gjson v1.17.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
@@ -456,14 +456,14 @@ require (
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
- golang.org/x/oauth2 v0.10.0 // indirect
+ golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
- gonum.org/v1/gonum v0.13.0 // indirect
+ gonum.org/v1/gonum v0.14.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index ce5e51a568..b8e8b205c8 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -994,8 +994,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
-github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
-github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
+github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
+github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gagliardetto/binary v0.6.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0=
@@ -1134,10 +1134,10 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/go-webauthn/revoke v0.1.9 h1:gSJ1ckA9VaKA2GN4Ukp+kiGTk1/EXtaDb1YE8RknbS0=
-github.com/go-webauthn/revoke v0.1.9/go.mod h1:j6WKPnv0HovtEs++paan9g3ar46gm1NarktkXBaPR+w=
-github.com/go-webauthn/webauthn v0.8.2 h1:8KLIbpldjz9KVGHfqEgJNbkhd7bbRXhNw4QWFJE15oA=
-github.com/go-webauthn/webauthn v0.8.2/go.mod h1:d+ezx/jMCNDiqSMzOchuynKb9CVU1NM9BumOnokfcVQ=
+github.com/go-webauthn/webauthn v0.8.6 h1:bKMtL1qzd2WTFkf1mFTVbreYrwn7dsYmEPjTq6QN90E=
+github.com/go-webauthn/webauthn v0.8.6/go.mod h1:emwVLMCI5yx9evTTvr0r+aOZCdWJqMfbRhF0MufyUog=
+github.com/go-webauthn/x v0.1.4 h1:sGmIFhcY70l6k7JIDfnjVBiAAFEssga5lXIUXe0GtAs=
+github.com/go-webauthn/x v0.1.4/go.mod h1:75Ug0oK6KYpANh5hDOanfDI+dvPWHk788naJVG/37H8=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
@@ -1189,9 +1189,12 @@ github.com/gogo/status v1.0.3/go.mod h1:SavQ51ycCLnc7dGyJxp8YAmudx8xqiVrRf+6IXRs
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg=
github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
+github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
@@ -1266,12 +1269,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
-github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
-github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
-github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo=
-github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4=
-github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0=
-github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4=
+github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
+github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -1351,7 +1350,6 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
@@ -1987,8 +1985,9 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
@@ -2262,8 +2261,8 @@ github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
+github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
github.com/prometheus/exporter-toolkit v0.8.2/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0=
@@ -2419,7 +2418,6 @@ github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
@@ -2430,7 +2428,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
-github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
@@ -2482,8 +2479,8 @@ github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e/go.mod h1:
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
-github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
-github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
+github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
@@ -2801,7 +2798,6 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -2900,8 +2896,8 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri
golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
-golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
-golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
+golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
+golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -3007,7 +3003,6 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -3192,8 +3187,8 @@ gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJ
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA=
-gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
-gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
+gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
+gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY=
@@ -3407,7 +3402,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
From 4ccd1c5e63a398ae17b0ede50e3785630277a20d Mon Sep 17 00:00:00 2001
From: Cedric
Date: Wed, 8 Nov 2023 17:35:58 +0000
Subject: [PATCH 109/327] Randomize database names when using heavyweight ORM
(#11233)
---
core/chains/evm/logpoller/log_poller_test.go | 6 ++--
core/chains/evm/txmgr/broadcaster_test.go | 4 +--
core/cmd/shell_local_test.go | 6 ++--
core/internal/cltest/heavyweight/orm.go | 24 ++++++++-------
core/internal/features/features_test.go | 15 +++++-----
.../features/ocr2/features_ocr2_test.go | 11 ++++---
.../fluxmonitorv2/flux_monitor_test.go | 18 ++----------
.../fluxmonitorv2/integrations_test.go | 2 +-
core/services/keeper/integration_test.go | 6 ++--
.../v1/internal/testutils.go | 7 ++---
.../ocr2/plugins/mercury/helpers_test.go | 2 +-
.../evm21/logprovider/integration_test.go | 3 +-
.../plugins/ocr2keeper/integration_21_test.go | 4 +--
.../plugins/ocr2keeper/integration_test.go | 11 ++++---
.../internal/ocr2vrf_integration_test.go | 2 +-
core/services/pg/event_broadcaster_test.go | 2 +-
core/services/pg/lease_lock_test.go | 4 +--
core/services/pipeline/orm_test.go | 14 ++++-----
core/services/vrf/v1/integration_test.go | 5 ++--
core/services/vrf/v2/bhs_feeder_test.go | 2 +-
.../vrf/v2/integration_helpers_test.go | 29 +++++++++----------
.../vrf/v2/integration_v2_plus_test.go | 2 +-
core/services/vrf/v2/integration_v2_test.go | 10 +++----
core/store/migrate/migrate_test.go | 10 +++----
24 files changed, 92 insertions(+), 107 deletions(-)
diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go
index 471c728cdd..5f013ca914 100644
--- a/core/chains/evm/logpoller/log_poller_test.go
+++ b/core/chains/evm/logpoller/log_poller_test.go
@@ -85,7 +85,7 @@ func populateDatabase(t testing.TB, o *logpoller.DbORM, chainID *big.Int) (commo
func BenchmarkSelectLogsCreatedAfter(b *testing.B) {
chainId := big.NewInt(137)
- _, db := heavyweight.FullTestDBV2(b, "logs_scale", nil)
+ _, db := heavyweight.FullTestDBV2(b, nil)
o := logpoller.NewORM(chainId, db, logger.TestLogger(b), pgtest.NewQConfig(false))
event, address, _ := populateDatabase(b, o, chainId)
@@ -103,7 +103,7 @@ func BenchmarkSelectLogsCreatedAfter(b *testing.B) {
func TestPopulateLoadedDB(t *testing.T) {
t.Skip("Only for local load testing and query analysis")
- _, db := heavyweight.FullTestDBV2(t, "logs_scale", nil)
+ _, db := heavyweight.FullTestDBV2(t, nil)
chainID := big.NewInt(137)
o := logpoller.NewORM(big.NewInt(137), db, logger.TestLogger(t), pgtest.NewQConfig(true))
@@ -1328,7 +1328,7 @@ func TestNotifyAfterInsert(t *testing.T) {
// Use a non-transactional db for this test because notify events
// are not delivered until the transaction is committed.
var dbURL string
- _, sqlxDB := heavyweight.FullTestDBV2(t, "notify_after_insert_log", func(c *chainlink.Config, s *chainlink.Secrets) {
+ _, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
dbURL = s.Database.URL.URL().String()
})
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index ca2697ca99..fcbc7a1f4c 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -75,7 +75,7 @@ func NewTestEthBroadcaster(
}
func TestEthBroadcaster_Lifecycle(t *testing.T) {
- cfg, db := heavyweight.FullTestDBV2(t, "eth_broadcaster_optimistic_locking", nil)
+ cfg, db := heavyweight.FullTestDBV2(t, nil)
txStore := cltest.NewTestTxStore(t, db, cfg.Database())
evmcfg := evmtest.NewChainScopedConfig(t, cfg)
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
@@ -565,7 +565,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) {
func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testing.T) {
// non-transactional DB needed because we deliberately test for FK violation
- cfg, db := heavyweight.FullTestDBV2(t, "eth_broadcaster_optimistic_locking", nil)
+ cfg, db := heavyweight.FullTestDBV2(t, nil)
txStore := cltest.NewTestTxStore(t, db, cfg.Database())
ccfg := evmtest.NewChainScopedConfig(t, cfg)
evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM())
diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go
index a73e98a935..4d906214ef 100644
--- a/core/cmd/shell_local_test.go
+++ b/core/cmd/shell_local_test.go
@@ -280,7 +280,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) {
// Use a non-transactional db for this test because we need to
// test multiple connections to the database, and changes made within
// the transaction cannot be seen from another connection.
- config, sqlxDB := heavyweight.FullTestDBV2(t, "rebroadcasttransactions", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Dialect = dialects.Postgres
// evm config is used in this test. but if set, it must be pass config validation.
// simplest to make it nil
@@ -359,7 +359,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
// Use the non-transactional db for this test because we need to
// test multiple connections to the database, and changes made within
// the transaction cannot be seen from another connection.
- config, sqlxDB := heavyweight.FullTestDBV2(t, "rebroadcasttransactions_outsiderange", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Dialect = dialects.Postgres
// evm config is used in this test. but if set, it must be pass config validation.
// simplest to make it nil
@@ -437,7 +437,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- config, sqlxDB := heavyweight.FullTestDBV2(t, "rebroadcasttransactions_outsiderange", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Dialect = dialects.Postgres
c.EVM = nil
diff --git a/core/internal/cltest/heavyweight/orm.go b/core/internal/cltest/heavyweight/orm.go
index 2f9370f35a..b46e7114cf 100644
--- a/core/internal/cltest/heavyweight/orm.go
+++ b/core/internal/cltest/heavyweight/orm.go
@@ -7,13 +7,14 @@ import (
"database/sql"
"errors"
"fmt"
- "math/rand"
"net/url"
"os"
"path"
"runtime"
+ "strings"
"testing"
+ "github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -30,21 +31,25 @@ import (
// FullTestDBV2 creates a pristine DB which runs in a separate database than the normal
// unit tests, so you can do things like use other Postgres connection types with it.
-func FullTestDBV2(t testing.TB, name string, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
- return prepareFullTestDBV2(t, name, false, true, overrideFn)
+func FullTestDBV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
+ return prepareFullTestDBV2(t, false, true, overrideFn)
}
// FullTestDBNoFixturesV2 is the same as FullTestDB, but it does not load fixtures.
-func FullTestDBNoFixturesV2(t testing.TB, name string, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
- return prepareFullTestDBV2(t, name, false, false, overrideFn)
+func FullTestDBNoFixturesV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
+ return prepareFullTestDBV2(t, false, false, overrideFn)
}
// FullTestDBEmptyV2 creates an empty DB (without migrations).
-func FullTestDBEmptyV2(t testing.TB, name string, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
- return prepareFullTestDBV2(t, name, true, false, overrideFn)
+func FullTestDBEmptyV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
+ return prepareFullTestDBV2(t, true, false, overrideFn)
}
-func prepareFullTestDBV2(t testing.TB, name string, empty bool, loadFixtures bool, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
+func generateName() string {
+ return strings.ReplaceAll(uuid.New().String(), "-", "")
+}
+
+func prepareFullTestDBV2(t testing.TB, empty bool, loadFixtures bool, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
testutils.SkipShort(t, "FullTestDB")
if empty && loadFixtures {
@@ -59,8 +64,7 @@ func prepareFullTestDBV2(t testing.TB, name string, empty bool, loadFixtures boo
})
require.NoError(t, os.MkdirAll(gcfg.RootDir(), 0700))
- name = fmt.Sprintf("%s_%x", name, rand.Intn(0xFFF)) // to avoid name collisions
- migrationTestDBURL, err := dropAndCreateThrowawayTestDB(gcfg.Database().URL(), name, empty)
+ migrationTestDBURL, err := dropAndCreateThrowawayTestDB(gcfg.Database().URL(), generateName(), empty)
require.NoError(t, err)
db, err := pg.NewConnection(migrationTestDBURL, dialects.Postgres, gcfg.Database())
require.NoError(t, err)
diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go
index 23451bf29f..b5f42d8bf3 100644
--- a/core/internal/features/features_test.go
+++ b/core/internal/features/features_test.go
@@ -675,11 +675,11 @@ func setupOCRContracts(t *testing.T) (*bind.TransactOpts, *backends.SimulatedBac
return owner, b, ocrContractAddress, ocrContract, flagsContract, flagsContractAddress
}
-func setupNode(t *testing.T, owner *bind.TransactOpts, portV1, portV2 int, dbName string,
+func setupNode(t *testing.T, owner *bind.TransactOpts, portV1, portV2 int,
b *backends.SimulatedBackend, ns ocrnetworking.NetworkingStack, overrides func(c *chainlink.Config, s *chainlink.Secrets),
) (*cltest.TestApplication, string, common.Address, ocrkey.KeyV2) {
p2pKey := keystest.NewP2PKeyV2(t)
- config, _ := heavyweight.FullTestDBV2(t, dbName, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test.
c.OCR.Enabled = ptr(true)
@@ -748,7 +748,6 @@ func setupForwarderEnabledNode(
owner *bind.TransactOpts,
portV1,
portV2 int,
- dbName string,
b *backends.SimulatedBackend,
ns ocrnetworking.NetworkingStack,
overrides func(c *chainlink.Config, s *chainlink.Secrets),
@@ -760,7 +759,7 @@ func setupForwarderEnabledNode(
ocrkey.KeyV2,
) {
p2pKey := keystest.NewP2PKeyV2(t)
- config, _ := heavyweight.FullTestDBV2(t, dbName, func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test.
c.OCR.Enabled = ptr(true)
@@ -867,7 +866,7 @@ func TestIntegration_OCR(t *testing.T) {
// Note it's plausible these ports could be occupied on a CI machine.
// May need a port randomize + retry approach if we observe collisions.
- appBootstrap, bootstrapPeerID, _, _ := setupNode(t, owner, bootstrapNodePortV1, bootstrapNodePortV2, fmt.Sprintf("b_%d", test.id), b, test.ns, nil)
+ appBootstrap, bootstrapPeerID, _, _ := setupNode(t, owner, bootstrapNodePortV1, bootstrapNodePortV2, b, test.ns, nil)
var (
oracles []confighelper.OracleIdentityExtra
transmitters []common.Address
@@ -878,7 +877,7 @@ func TestIntegration_OCR(t *testing.T) {
for i := 0; i < numOracles; i++ {
portV1 := ports[2*i]
portV2 := ports[2*i+1]
- app, peerID, transmitter, key := setupNode(t, owner, portV1, portV2, fmt.Sprintf("o%d_%d", i, test.id), b, test.ns, func(c *chainlink.Config, s *chainlink.Secrets) {
+ app, peerID, transmitter, key := setupNode(t, owner, portV1, portV2, b, test.ns, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].FlagsContractAddress = ptr(ethkey.EIP55AddressFromAddress(flagsContractAddress))
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(test.eip1559)
if test.ns != ocrnetworking.NetworkingStackV1 {
@@ -1092,7 +1091,7 @@ func TestIntegration_OCR_ForwarderFlow(t *testing.T) {
// Note it's plausible these ports could be occupied on a CI machine.
// May need a port randomize + retry approach if we observe collisions.
- appBootstrap, bootstrapPeerID, _, _ := setupNode(t, owner, bootstrapNodePortV1, bootstrapNodePortV2, fmt.Sprintf("b_%d", 1), b, ocrnetworking.NetworkingStackV2, nil)
+ appBootstrap, bootstrapPeerID, _, _ := setupNode(t, owner, bootstrapNodePortV1, bootstrapNodePortV2, b, ocrnetworking.NetworkingStackV2, nil)
var (
oracles []confighelper.OracleIdentityExtra
@@ -1105,7 +1104,7 @@ func TestIntegration_OCR_ForwarderFlow(t *testing.T) {
for i := 0; i < numOracles; i++ {
portV1 := ports[2*i]
portV2 := ports[2*i+1]
- app, peerID, transmitter, forwarder, key := setupForwarderEnabledNode(t, owner, portV1, portV2, fmt.Sprintf("o%d_%d", i, 1), b, ocrnetworking.NetworkingStackV2, func(c *chainlink.Config, s *chainlink.Secrets) {
+ app, peerID, transmitter, forwarder, key := setupForwarderEnabledNode(t, owner, portV1, portV2, b, ocrnetworking.NetworkingStackV2, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Feature.LogPoller = ptr(true)
c.EVM[0].FlagsContractAddress = ptr(ethkey.EIP55AddressFromAddress(flagsContractAddress))
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go
index 25b6781c4e..3e22093568 100644
--- a/core/internal/features/ocr2/features_ocr2_test.go
+++ b/core/internal/features/ocr2/features_ocr2_test.go
@@ -105,13 +105,12 @@ func setupNodeOCR2(
t *testing.T,
owner *bind.TransactOpts,
port int,
- dbName string,
useForwarder bool,
b *backends.SimulatedBackend,
p2pV2Bootstrappers []commontypes.BootstrapperLocator,
) *ocr2Node {
p2pKey := keystest.NewP2PKeyV2(t)
- config, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", dbName, port), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test.
c.Feature.LogPoller = ptr(true)
@@ -193,7 +192,7 @@ func TestIntegration_OCR2(t *testing.T) {
lggr := logger.TestLogger(t)
bootstrapNodePort := freeport.GetOne(t)
- bootstrapNode := setupNodeOCR2(t, owner, bootstrapNodePort, "bootstrap", false /* useForwarders */, b, nil)
+ bootstrapNode := setupNodeOCR2(t, owner, bootstrapNodePort, false /* useForwarders */, b, nil)
var (
oracles []confighelper2.OracleIdentityExtra
@@ -203,7 +202,7 @@ func TestIntegration_OCR2(t *testing.T) {
)
ports := freeport.GetN(t, 4)
for i := 0; i < 4; i++ {
- node := setupNodeOCR2(t, owner, ports[i], fmt.Sprintf("oracle%d", i), false /* useForwarders */, b, []commontypes.BootstrapperLocator{
+ node := setupNodeOCR2(t, owner, ports[i], false /* useForwarders */, b, []commontypes.BootstrapperLocator{
// Supply the bootstrap IP and port as a V2 peer address
{PeerID: bootstrapNode.peerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}},
})
@@ -477,7 +476,7 @@ func TestIntegration_OCR2_ForwarderFlow(t *testing.T) {
lggr := logger.TestLogger(t)
bootstrapNodePort := freeport.GetOne(t)
- bootstrapNode := setupNodeOCR2(t, owner, bootstrapNodePort, "bootstrap", true /* useForwarders */, b, nil)
+ bootstrapNode := setupNodeOCR2(t, owner, bootstrapNodePort, true /* useForwarders */, b, nil)
var (
oracles []confighelper2.OracleIdentityExtra
@@ -488,7 +487,7 @@ func TestIntegration_OCR2_ForwarderFlow(t *testing.T) {
)
ports := freeport.GetN(t, 4)
for i := uint16(0); i < 4; i++ {
- node := setupNodeOCR2(t, owner, ports[i], fmt.Sprintf("oracle%d", i), true /* useForwarders */, b, []commontypes.BootstrapperLocator{
+ node := setupNodeOCR2(t, owner, ports[i], true /* useForwarders */, b, []commontypes.BootstrapperLocator{
// Supply the bootstrap IP and port as a V2 peer address
{PeerID: bootstrapNode.peerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}},
})
diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go
index 0d1eb085a8..26ec520e7c 100644
--- a/core/services/fluxmonitorv2/flux_monitor_test.go
+++ b/core/services/fluxmonitorv2/flux_monitor_test.go
@@ -3,7 +3,6 @@ package fluxmonitorv2_test
import (
"fmt"
"math/big"
- "strings"
"testing"
"time"
@@ -26,7 +25,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
@@ -284,8 +282,8 @@ func setupStoreWithKey(t *testing.T) (*sqlx.DB, common.Address) {
}
// setupStoreWithKey setups a new store and adds a key to the keystore
-func setupFullDBWithKey(t *testing.T, name string) (*sqlx.DB, common.Address) {
- cfg, db := heavyweight.FullTestDBV2(t, name, nil)
+func setupFullDBWithKey(t *testing.T) (*sqlx.DB, common.Address) {
+ cfg, db := heavyweight.FullTestDBV2(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth()
_, nodeAddr := cltest.MustInsertRandomKey(t, ethKeyStore)
@@ -906,18 +904,8 @@ func TestFluxMonitor_HibernationTickerFiresMultipleTimes(t *testing.T) {
g.Eventually(func() int { return len(pollOccured) }, testutils.WaitTimeout(t)).Should(gomega.Equal(3))
}
-// chainlink_test_TestFluxMonitor_HibernationIsEnteredAndRetryTickerStopped
-// 63 bytes is max and chainlink_test_ takes up 15, plus 4 for a random hex suffix.
-func dbName(s string) string {
- diff := len(cmd.TestDBNamePrefix) + len("_FFF")
- if len(s) <= diff {
- return strings.ReplaceAll(strings.ToLower(s), "/", "")
- }
- return strings.ReplaceAll(strings.ToLower(s[len(s)-diff:]), "/", "")
-}
-
func TestFluxMonitor_HibernationIsEnteredAndRetryTickerStopped(t *testing.T) {
- db, nodeAddr := setupFullDBWithKey(t, "hibernation")
+ db, nodeAddr := setupFullDBWithKey(t)
oracles := []common.Address{nodeAddr, testutils.NewAddress()}
const (
diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go
index 2c45ed5ad8..b2f24e08d5 100644
--- a/core/services/fluxmonitorv2/integrations_test.go
+++ b/core/services/fluxmonitorv2/integrations_test.go
@@ -206,7 +206,7 @@ func startApplication(
fa fluxAggregatorUniverse,
overrides func(c *chainlink.Config, s *chainlink.Secrets),
) *cltest.TestApplication {
- config, _ := heavyweight.FullTestDBV2(t, dbName(t.Name()), overrides)
+ config, _ := heavyweight.FullTestDBV2(t, overrides)
app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, fa.backend, fa.key)
require.NoError(t, app.Start(testutils.Context(t)))
return app
diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go
index 39431063bc..f76ef93574 100644
--- a/core/services/keeper/integration_test.go
+++ b/core/services/keeper/integration_test.go
@@ -236,7 +236,7 @@ func TestKeeperEthIntegration(t *testing.T) {
backend.Commit()
// setup app
- config, db := heavyweight.FullTestDBV2(t, fmt.Sprintf("keeper_eth_integration_%s", test.name), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].GasEstimator.EIP1559DynamicFees = &test.eip1559
c.Keeper.MaxGracePeriod = ptr[int64](0) // avoid waiting to re-submit for upkeeps
c.Keeper.Registry.SyncInterval = models.MustNewDuration(24 * time.Hour) // disable full sync ticker for test
@@ -393,7 +393,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) {
backend.Commit()
// setup app
- config, db := heavyweight.FullTestDBV2(t, "keeper_forwarder_flow", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Feature.LogPoller = ptr(true)
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
c.Keeper.MaxGracePeriod = ptr[int64](0) // avoid waiting to re-submit for upkeeps
@@ -540,7 +540,7 @@ func TestMaxPerformDataSize(t *testing.T) {
backend.Commit()
// setup app
- config, db := heavyweight.FullTestDBV2(t, "keeper_max_perform_data_test", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Keeper.MaxGracePeriod = ptr[int64](0) // avoid waiting to re-submit for upkeeps
c.Keeper.Registry.SyncInterval = models.MustNewDuration(24 * time.Hour) // disable full sync ticker for test
c.Keeper.Registry.MaxPerformDataSize = ptr(uint32(maxPerformDataSize)) // set the max perform data size
diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go
index 5c824323eb..9f63d60eef 100644
--- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go
+++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go
@@ -302,7 +302,6 @@ func StartNewNode(
t *testing.T,
owner *bind.TransactOpts,
port int,
- dbName string,
b *backends.SimulatedBackend,
maxGas uint32,
p2pV2Bootstrappers []commontypes.BootstrapperLocator,
@@ -310,7 +309,7 @@ func StartNewNode(
thresholdKeyShare string,
) *Node {
p2pKey := keystest.NewP2PKeyV2(t)
- config, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", dbName, port), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = ptr(true)
c.Feature.LogPoller = ptr(true)
@@ -550,7 +549,7 @@ func CreateFunctionsNodes(
}
bootstrapPort := freeport.GetOne(t)
- bootstrapNode = StartNewNode(t, owner, bootstrapPort, "bootstrap", b, uint32(maxGas), nil, nil, "")
+ bootstrapNode = StartNewNode(t, owner, bootstrapPort, b, uint32(maxGas), nil, nil, "")
AddBootstrapJob(t, bootstrapNode.App, routerAddress)
// oracle nodes with jobs, bridges and mock EAs
@@ -568,7 +567,7 @@ func CreateFunctionsNodes(
} else {
ocr2Keystore = ocr2Keystores[i]
}
- oracleNode := StartNewNode(t, owner, ports[i], fmt.Sprintf("oracle%d", i), b, uint32(maxGas), []commontypes.BootstrapperLocator{
+ oracleNode := StartNewNode(t, owner, ports[i], b, uint32(maxGas), []commontypes.BootstrapperLocator{
{PeerID: bootstrapNode.PeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapPort)}},
}, ocr2Keystore, thresholdKeyShare)
oracleNodes = append(oracleNodes, oracleNode.App)
diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go
index 60904b5813..588f772120 100644
--- a/core/services/ocr2/plugins/mercury/helpers_test.go
+++ b/core/services/ocr2/plugins/mercury/helpers_test.go
@@ -163,7 +163,7 @@ func setupNode(
p2paddresses := []string{fmt.Sprintf("127.0.0.1:%d", port)}
- config, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", dbName, port), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
// [JobPipeline]
// MaxSuccessfulRuns = 0
c.JobPipeline.MaxSuccessfulRuns = ptr(uint64(0))
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index dad3542039..63ed4114b8 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -3,7 +3,6 @@ package logprovider_test
import (
"context"
"errors"
- "fmt"
"math/big"
"testing"
"time"
@@ -693,7 +692,7 @@ func setupBackend(t *testing.T) (*backends.SimulatedBackend, func(), []*bind.Tra
func ptr[T any](v T) *T { return &v }
func setupDB(t *testing.T) *sqlx.DB {
- _, db := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", "chainlink_test", 5432), func(c *chainlink.Config, s *chainlink.Secrets) {
+ _, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Feature.LogPoller = ptr(true)
c.OCR.Enabled = ptr(false)
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
index 15280de73c..562f972bc4 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
@@ -479,7 +479,7 @@ func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IK
// Setup bootstrap + oracle nodes
bootstrapNodePort := freeport.GetOne(t)
- appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNode(t, bootstrapNodePort, "bootstrap_keeper_ocr", nodeKeys[0], backend, nil, mServer)
+ appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNode(t, bootstrapNodePort, nodeKeys[0], backend, nil, mServer)
bootstrapNode := Node{
appBootstrap, bootstrapTransmitter, bootstrapKb,
}
@@ -490,7 +490,7 @@ func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IK
// Set up the minimum 4 oracles all funded
ports := freeport.GetN(t, 4)
for i := 0; i < 4; i++ {
- app, peerID, transmitter, kb := setupNode(t, ports[i], fmt.Sprintf("oracle_keeper%d", i), nodeKeys[i+1], backend, []commontypes.BootstrapperLocator{
+ app, peerID, transmitter, kb := setupNode(t, ports[i], nodeKeys[i+1], backend, []commontypes.BootstrapperLocator{
// Supply the bootstrap IP and port as a V2 peer address
{PeerID: bootstrapPeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}},
}, mServer)
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
index 7c881a18eb..f50321631c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
@@ -111,7 +111,6 @@ func deployKeeper20Registry(
func setupNode(
t *testing.T,
port int,
- dbName string,
nodeKey ethkey.KeyV2,
backend *backends.SimulatedBackend,
p2pV2Bootstrappers []commontypes.BootstrapperLocator,
@@ -119,7 +118,7 @@ func setupNode(
) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) {
p2pKey := keystest.NewP2PKeyV2(t)
p2paddresses := []string{fmt.Sprintf("127.0.0.1:%d", port)}
- cfg, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", dbName, port), func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Feature.LogPoller = ptr(true)
c.OCR.Enabled = ptr(false)
@@ -240,7 +239,7 @@ func TestIntegration_KeeperPluginBasic(t *testing.T) {
// Setup bootstrap + oracle nodes
bootstrapNodePort := freeport.GetOne(t)
- appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNode(t, bootstrapNodePort, "bootstrap_keeper_ocr", nodeKeys[0], backend, nil, NewSimulatedMercuryServer())
+ appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNode(t, bootstrapNodePort, nodeKeys[0], backend, nil, NewSimulatedMercuryServer())
bootstrapNode := Node{
appBootstrap, bootstrapTransmitter, bootstrapKb,
}
@@ -251,7 +250,7 @@ func TestIntegration_KeeperPluginBasic(t *testing.T) {
// Set up the minimum 4 oracles all funded
ports := freeport.GetN(t, 4)
for i := 0; i < 4; i++ {
- app, peerID, transmitter, kb := setupNode(t, ports[i], fmt.Sprintf("oracle_keeper%d", i), nodeKeys[i+1], backend, []commontypes.BootstrapperLocator{
+ app, peerID, transmitter, kb := setupNode(t, ports[i], nodeKeys[i+1], backend, []commontypes.BootstrapperLocator{
// Supply the bootstrap IP and port as a V2 peer address
{PeerID: bootstrapPeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}},
}, NewSimulatedMercuryServer())
@@ -501,7 +500,7 @@ func TestIntegration_KeeperPluginForwarderEnabled(t *testing.T) {
effectiveTransmitters := make([]common.Address, 0)
// Setup bootstrap + oracle nodes
bootstrapNodePort := freeport.GetOne(t)
- appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNode(t, bootstrapNodePort, "bootstrap_keeper_ocr", nodeKeys[0], backend, nil, NewSimulatedMercuryServer())
+ appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNode(t, bootstrapNodePort, nodeKeys[0], backend, nil, NewSimulatedMercuryServer())
bootstrapNode := Node{
appBootstrap, bootstrapTransmitter, bootstrapKb,
@@ -513,7 +512,7 @@ func TestIntegration_KeeperPluginForwarderEnabled(t *testing.T) {
// Set up the minimum 4 oracles all funded
ports := freeport.GetN(t, 4)
for i := 0; i < 4; i++ {
- app, peerID, transmitter, kb := setupNode(t, ports[i], fmt.Sprintf("oracle_keeper%d", i), nodeKeys[i+1], backend, []commontypes.BootstrapperLocator{
+ app, peerID, transmitter, kb := setupNode(t, ports[i], nodeKeys[i+1], backend, []commontypes.BootstrapperLocator{
// Supply the bootstrap IP and port as a V2 peer address
{PeerID: bootstrapPeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}},
}, NewSimulatedMercuryServer())
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 cf7a408725..0dbb6a5915 100644
--- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
@@ -226,7 +226,7 @@ func setupNodeOCR2(
p2pV2Bootstrappers []commontypes.BootstrapperLocator,
) *ocr2Node {
p2pKey := keystest.NewP2PKeyV2(t)
- config, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", dbName, port), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test.
c.Feature.LogPoller = ptr(true)
diff --git a/core/services/pg/event_broadcaster_test.go b/core/services/pg/event_broadcaster_test.go
index bea7dfb5a8..a82e26e058 100644
--- a/core/services/pg/event_broadcaster_test.go
+++ b/core/services/pg/event_broadcaster_test.go
@@ -16,7 +16,7 @@ import (
)
func TestEventBroadcaster(t *testing.T) {
- config, _ := heavyweight.FullTestDBNoFixturesV2(t, "event_broadcaster", nil)
+ config, _ := heavyweight.FullTestDBNoFixturesV2(t, nil)
eventBroadcaster := cltest.NewEventBroadcaster(t, config.Database().URL())
require.NoError(t, eventBroadcaster.Start(testutils.Context(t)))
diff --git a/core/services/pg/lease_lock_test.go b/core/services/pg/lease_lock_test.go
index 9f857ffa20..483e03e003 100644
--- a/core/services/pg/lease_lock_test.go
+++ b/core/services/pg/lease_lock_test.go
@@ -24,7 +24,7 @@ func newLeaseLock(t *testing.T, db *sqlx.DB, cfg pg.LeaseLockConfig) pg.LeaseLoc
}
func Test_LeaseLock(t *testing.T) {
- cfg, db := heavyweight.FullTestDBNoFixturesV2(t, "leaselock", func(c *chainlink.Config, s *chainlink.Secrets) {
+ cfg, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
t := true
c.Database.Lock.Enabled = &t
})
@@ -207,7 +207,7 @@ func Test_LeaseLock(t *testing.T) {
require.NoError(t, db.Close())
t.Run("on virgin database", func(t *testing.T) {
- _, db := heavyweight.FullTestDBEmptyV2(t, "leaselock", nil)
+ _, db := heavyweight.FullTestDBEmptyV2(t, nil)
cfg := pg.LeaseLockConfig{
DefaultQueryTimeout: cfg.Database().DefaultQueryTimeout(),
LeaseDuration: 15 * time.Second,
diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go
index f916c24f0a..295ad20a00 100644
--- a/core/services/pipeline/orm_test.go
+++ b/core/services/pipeline/orm_test.go
@@ -33,11 +33,11 @@ type ormconfig struct {
func (ormconfig) JobPipelineMaxSuccessfulRuns() uint64 { return 123456 }
-func setupORM(t *testing.T, name string) (db *sqlx.DB, orm pipeline.ORM) {
+func setupORM(t *testing.T, heavy bool) (db *sqlx.DB, orm pipeline.ORM) {
t.Helper()
- if name != "" {
- _, db = heavyweight.FullTestDBV2(t, name, nil)
+ if heavy {
+ _, db = heavyweight.FullTestDBV2(t, nil)
} else {
db = pgtest.NewSqlxDB(t)
}
@@ -47,12 +47,12 @@ func setupORM(t *testing.T, name string) (db *sqlx.DB, orm pipeline.ORM) {
return
}
-func setupHeavyORM(t *testing.T, name string) (db *sqlx.DB, orm pipeline.ORM) {
- return setupORM(t, name)
+func setupHeavyORM(t *testing.T) (db *sqlx.DB, orm pipeline.ORM) {
+ return setupORM(t, true)
}
func setupLiteORM(t *testing.T) (db *sqlx.DB, orm pipeline.ORM) {
- return setupORM(t, "")
+ return setupORM(t, false)
}
func Test_PipelineORM_CreateSpec(t *testing.T) {
@@ -464,7 +464,7 @@ func Test_PipelineORM_DeleteRun(t *testing.T) {
}
func Test_PipelineORM_DeleteRunsOlderThan(t *testing.T) {
- _, orm := setupHeavyORM(t, "pipeline_runs_reaper")
+ _, orm := setupHeavyORM(t)
var runsIds []int64
diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go
index b7e6be4318..a7dca56776 100644
--- a/core/services/vrf/v1/integration_test.go
+++ b/core/services/vrf/v1/integration_test.go
@@ -2,7 +2,6 @@ package v1_test
import (
"encoding/hex"
- "fmt"
"math/big"
"strings"
"testing"
@@ -46,7 +45,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) {
for _, tt := range tests {
test := tt
t.Run(test.name, func(t *testing.T) {
- config, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("vrf_jpv2_%v", test.eip1559), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].GasEstimator.EIP1559DynamicFees = &test.eip1559
c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID)
})
@@ -129,7 +128,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) {
func TestIntegration_VRF_WithBHS(t *testing.T) {
t.Parallel()
- config, _ := heavyweight.FullTestDBV2(t, "vrf_with_bhs", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
c.EVM[0].BlockBackfillDepth = ptr[uint32](500)
c.Feature.LogPoller = ptr(true)
diff --git a/core/services/vrf/v2/bhs_feeder_test.go b/core/services/vrf/v2/bhs_feeder_test.go
index 0da28378d0..219fe1c8fd 100644
--- a/core/services/vrf/v2/bhs_feeder_test.go
+++ b/core/services/vrf/v2/bhs_feeder_test.go
@@ -51,7 +51,7 @@ func TestStartHeartbeats(t *testing.T) {
keys = append(keys, ownerKey, vrfKey)
- config, _ := heavyweight.FullTestDBV2(t, "vrfv2_needs_blockhash_store", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, gasLanePriceWei, keySpecificOverrides...)(c, s)
c.EVM[0].MinIncomingConfirmations = ptr[uint32](2)
c.Feature.LogPoller = ptr(true)
diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go
index 60a7cd18d2..a086cbbb09 100644
--- a/core/services/vrf/v2/integration_helpers_test.go
+++ b/core/services/vrf/v2/integration_helpers_test.go
@@ -1,7 +1,6 @@
package v2_test
import (
- "fmt"
"math/big"
"strings"
"testing"
@@ -62,7 +61,7 @@ func testSingleConsumerHappyPath(
key1 := cltest.MustGenerateRandomKey(t)
key2 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_happypath", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -202,7 +201,7 @@ func testMultipleConsumersNeedBHS(
GasEstimator: toml.KeySpecificGasEstimator{PriceMax: gasLanePriceWei},
})
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_needs_blockhash_store", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), keySpecificOverrides...)(c, s)
c.EVM[0].MinIncomingConfirmations = ptr[uint32](2)
c.Feature.LogPoller = ptr(true)
@@ -349,7 +348,7 @@ func testMultipleConsumersNeedTrustedBHS(
uni.backend.Commit()
}
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_needs_trusted_blockhash_store", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), keySpecificOverrides...)(c, s)
c.EVM[0].MinIncomingConfirmations = ptr[uint32](2)
c.EVM[0].GasEstimator.LimitDefault = ptr(uint32(5_000_000))
@@ -531,7 +530,7 @@ func testSingleConsumerHappyPathBatchFulfillment(
) {
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_batch_happypath", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -635,7 +634,7 @@ func testSingleConsumerNeedsTopUp(
) {
key := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(1000)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_needstopup", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(1000), toml.KeySpecific{
// Gas lane.
Key: ptr(key.EIP55Address),
@@ -739,7 +738,7 @@ func testBlockHeaderFeeder(
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_test_block_header_feeder", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, gasLanePriceWei, toml.KeySpecific{
// Gas lane.
Key: ptr(vrfKey.EIP55Address),
@@ -894,7 +893,7 @@ func testSingleConsumerForcedFulfillment(
key1 := cltest.MustGenerateRandomKey(t)
key2 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, fmt.Sprintf("vrfv2_singleconsumer_forcefulfill_%v", batchEnabled), func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1061,7 +1060,7 @@ func testSingleConsumerEIP150(
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, _ := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_eip150_happypath", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), v2.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1129,7 +1128,7 @@ func testSingleConsumerEIP150Revert(
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, _ := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_eip150_revert", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), v2.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1192,7 +1191,7 @@ func testSingleConsumerBigGasCallbackSandwich(
) {
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(100)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_bigcallback_sandwich", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(100), v2.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1308,7 +1307,7 @@ func testSingleConsumerMultipleGasLanes(
expensiveKey := cltest.MustGenerateRandomKey(t)
cheapGasLane := assets.GWei(10)
expensiveGasLane := assets.GWei(1000)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_multiplegaslanes", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), v2.KeySpecific{
// Cheap gas lane.
Key: ptr(cheapKey.EIP55Address),
@@ -1428,7 +1427,7 @@ func testSingleConsumerAlwaysRevertingCallbackStillFulfilled(
) {
key := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_alwaysrevertingcallback", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), v2.KeySpecific{
// Gas lane.
Key: ptr(key.EIP55Address),
@@ -1496,7 +1495,7 @@ func testConsumerProxyHappyPath(
key1 := cltest.MustGenerateRandomKey(t)
key2 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_consumerproxy_happypath", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), v2.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1624,7 +1623,7 @@ func testMaliciousConsumer(
batchEnabled bool,
vrfVersion vrfcommon.Version,
) {
- config, _ := heavyweight.FullTestDBV2(t, "vrf_v2plus_integration_malicious", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].GasEstimator.LimitDefault = ptr[uint32](2_000_000)
c.EVM[0].GasEstimator.PriceMax = assets.GWei(1)
c.EVM[0].GasEstimator.PriceDefault = assets.GWei(1)
diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go
index 094d7d060e..75026423f4 100644
--- a/core/services/vrf/v2/integration_v2_plus_test.go
+++ b/core/services/vrf/v2/integration_v2_plus_test.go
@@ -1141,7 +1141,7 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) {
uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false)
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2plus_migration", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index 3a691ec2e2..e50ed91491 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -967,7 +967,7 @@ func testEoa(
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, _ := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_eoa_request", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1128,7 +1128,7 @@ func TestVRFV2Integration_SingleConsumer_Wrapper(t *testing.T) {
callBackGasLimit := int64(100_000) // base callback gas.
key1 := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_singleconsumer_wrapper", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1208,7 +1208,7 @@ func TestVRFV2Integration_Wrapper_High_Gas(t *testing.T) {
key1 := cltest.MustGenerateRandomKey(t)
callBackGasLimit := int64(2_000_000) // base callback gas.
gasLanePriceWei := assets.GWei(10)
- config, db := heavyweight.FullTestDBV2(t, "vrfv2_wrapper_high_gas_revert", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, assets.GWei(10), toml.KeySpecific{
// Gas lane.
Key: ptr(key1.EIP55Address),
@@ -1585,7 +1585,7 @@ func TestIntegrationVRFV2(t *testing.T) {
gasPrice := assets.GWei(1)
key := cltest.MustGenerateRandomKey(t)
gasLanePriceWei := assets.GWei(10)
- config, _ := heavyweight.FullTestDBV2(t, "vrf_v2_integration", func(c *chainlink.Config, s *chainlink.Secrets) {
+ config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
simulatedOverrides(t, gasPrice, toml.KeySpecific{
Key: &key.EIP55Address,
GasEstimator: toml.KeySpecificGasEstimator{PriceMax: gasLanePriceWei},
@@ -2003,7 +2003,7 @@ func TestFulfillmentCost(t *testing.T) {
}
func TestStartingCountsV1(t *testing.T) {
- cfg, db := heavyweight.FullTestDBNoFixturesV2(t, "vrf_test_starting_counts", nil)
+ cfg, db := heavyweight.FullTestDBNoFixturesV2(t, nil)
lggr := logger.TestLogger(t)
qCfg := pgtest.NewQConfig(false)
diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go
index fe218589d2..ef105c75ff 100644
--- a/core/store/migrate/migrate_test.go
+++ b/core/store/migrate/migrate_test.go
@@ -73,7 +73,7 @@ func getOCR2Spec100() OffchainReporting2OracleSpec100 {
}
func TestMigrate_0100_BootstrapConfigs(t *testing.T) {
- cfg, db := heavyweight.FullTestDBEmptyV2(t, migrationDir, nil)
+ cfg, db := heavyweight.FullTestDBEmptyV2(t, nil)
lggr := logger.TestLogger(t)
err := goose.UpTo(db.DB, migrationDir, 99)
require.NoError(t, err)
@@ -342,7 +342,7 @@ ON jobs.offchainreporting2_oracle_spec_id = ocr2.id`
}
func TestMigrate_101_GenericOCR2(t *testing.T) {
- _, db := heavyweight.FullTestDBEmptyV2(t, migrationDir, nil)
+ _, db := heavyweight.FullTestDBEmptyV2(t, nil)
err := goose.UpTo(db.DB, migrationDir, 100)
require.NoError(t, err)
@@ -392,7 +392,7 @@ func TestMigrate_101_GenericOCR2(t *testing.T) {
func TestMigrate(t *testing.T) {
lggr := logger.TestLogger(t)
- _, db := heavyweight.FullTestDBEmptyV2(t, migrationDir, nil)
+ _, db := heavyweight.FullTestDBEmptyV2(t, nil)
err := goose.UpTo(db.DB, migrationDir, 100)
require.NoError(t, err)
@@ -443,7 +443,7 @@ func TestSetMigrationENVVars(t *testing.T) {
}
func TestDatabaseBackFillWithMigration202(t *testing.T) {
- _, db := heavyweight.FullTestDBEmptyV2(t, migrationDir, nil)
+ _, db := heavyweight.FullTestDBEmptyV2(t, nil)
err := goose.UpTo(db.DB, migrationDir, 201)
require.NoError(t, err)
@@ -523,7 +523,7 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) {
maxLogsSize := 100_000
// Disable Goose logging for benchmarking
goose.SetLogger(goose.NopLogger())
- _, db := heavyweight.FullTestDBEmptyV2(b, migrationDir, nil)
+ _, db := heavyweight.FullTestDBEmptyV2(b, nil)
err := goose.UpTo(db.DB, migrationDir, previousMigration)
require.NoError(b, err)
From 5d4961b70ec804589ea66bb33e087f1da41a9e33 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Wed, 8 Nov 2023 12:10:56 -0600
Subject: [PATCH 110/327] core/store/migration/migrations: rm last sqlx.NewTx
use (#11230)
---
core/store/migrate/migrations/0036_external_job_id.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/store/migrate/migrations/0036_external_job_id.go b/core/store/migrate/migrations/0036_external_job_id.go
index 82f26206d8..8637bd38f5 100644
--- a/core/store/migrate/migrations/0036_external_job_id.go
+++ b/core/store/migrate/migrations/0036_external_job_id.go
@@ -45,7 +45,7 @@ func Up36(ctx context.Context, tx *sql.Tx) error {
// Update all jobs to have an external_job_id.
// We do this to avoid using the uuid postgres extension.
var jobIDs []int32
- txx := sqlx.NewTx(tx, "postgres")
+ txx := sqlx.Tx{Tx: tx}
if err := txx.SelectContext(ctx, &jobIDs, "SELECT id FROM jobs"); err != nil {
return err
}
From b8caeda1aee8b7127bb2d0a208630ce42beee46d Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Wed, 8 Nov 2023 16:13:59 -0500
Subject: [PATCH 111/327] (test): Amend Functions onTokenTransferTest to be
able to fuzz with full LINK supply (#11234)
---
.../gas-snapshots/functions.gas-snapshot | 10 ++---
.../tests/v1_X/FunctionsSubscriptions.t.sol | 42 ++++++++++++-------
2 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index d575c8ca19..e742be2754 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -130,11 +130,11 @@ FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Reve
FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13459)
FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 59592)
FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15010)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 28446, ~: 28446)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 30958, ~: 30958)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14293, ~: 14293)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 35938, ~: 35938)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 59686, ~: 59686)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43685, ~: 45548)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46197, ~: 48060)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14295, ~: 14295)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51089, ~: 53040)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 86057, ~: 89604)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15638)
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
index 8f08a6c1e8..5a54bcc84c 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol
@@ -309,11 +309,22 @@ contract FunctionsSubscriptions_OwnerWithdraw is FunctionsFulfillmentSetup {
}
/// @notice #onTokenTransfer
-contract FunctionsSubscriptions_OnTokenTransfer is FunctionsSubscriptionSetup {
+contract FunctionsSubscriptions_OnTokenTransfer is FunctionsClientSetup {
+ uint64 s_subscriptionId;
+
+ function setUp() public virtual override {
+ FunctionsClientSetup.setUp();
+
+ // Create subscription, but do not fund it
+ s_subscriptionId = s_functionsRouter.createSubscription();
+ s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient));
+ }
+
function test_OnTokenTransfer_RevertIfPaused(uint96 fundingAmount) public {
// Funding amount must be less than LINK total supply
- vm.assume(fundingAmount < 1_000_000_000 * 1e18);
- vm.assume(fundingAmount > 0);
+ uint256 totalSupplyJuels = 1_000_000_000 * 1e18;
+ vm.assume(fundingAmount <= totalSupplyJuels);
+ vm.assume(fundingAmount >= 0);
s_functionsRouter.pause();
vm.expectRevert("Pausable: paused");
@@ -322,8 +333,9 @@ contract FunctionsSubscriptions_OnTokenTransfer is FunctionsSubscriptionSetup {
function test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96 fundingAmount) public {
// Funding amount must be less than LINK total supply
- vm.assume(fundingAmount < 1_000_000_000 * 1e18);
- vm.assume(fundingAmount > 0);
+ uint256 totalSupplyJuels = 1_000_000_000 * 1e18;
+ vm.assume(fundingAmount <= totalSupplyJuels);
+ vm.assume(fundingAmount >= 0);
vm.expectRevert(FunctionsSubscriptions.OnlyCallableFromLink.selector);
s_functionsRouter.onTokenTransfer(address(s_functionsRouter), fundingAmount, abi.encode(s_subscriptionId));
@@ -331,8 +343,9 @@ contract FunctionsSubscriptions_OnTokenTransfer is FunctionsSubscriptionSetup {
function test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96 fundingAmount) public {
// Funding amount must be less than LINK total supply
- vm.assume(fundingAmount < 1_000_000_000 * 1e18);
- vm.assume(fundingAmount > 0);
+ uint256 totalSupplyJuels = 1_000_000_000 * 1e18;
+ vm.assume(fundingAmount <= totalSupplyJuels);
+ vm.assume(fundingAmount >= 0);
vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector);
s_linkToken.transferAndCall(address(s_functionsRouter), fundingAmount, new bytes(0));
@@ -340,8 +353,9 @@ contract FunctionsSubscriptions_OnTokenTransfer is FunctionsSubscriptionSetup {
function test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96 fundingAmount) public {
// Funding amount must be less than LINK total supply
- vm.assume(fundingAmount < 1_000_000_000 * 1e18);
- vm.assume(fundingAmount > 0);
+ uint256 totalSupplyJuels = 1_000_000_000 * 1e18;
+ vm.assume(fundingAmount <= totalSupplyJuels);
+ vm.assume(fundingAmount >= 0);
vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector);
uint64 invalidSubscriptionId = 123456789;
@@ -349,17 +363,15 @@ contract FunctionsSubscriptions_OnTokenTransfer is FunctionsSubscriptionSetup {
}
function test_OnTokenTransfer_Success(uint96 fundingAmount) public {
- uint96 subscriptionBalanceBefore = s_functionsRouter.getSubscription(s_subscriptionId).balance;
-
// Funding amount must be less than LINK total supply
- uint96 TOTAL_LINK = 1_000_000_000 * 1e18;
+ uint256 totalSupplyJuels = 1_000_000_000 * 1e18;
// Some of the total supply is already in the subscription account
- vm.assume(fundingAmount < TOTAL_LINK - subscriptionBalanceBefore);
- vm.assume(fundingAmount > 0);
+ vm.assume(fundingAmount <= totalSupplyJuels);
+ vm.assume(fundingAmount >= 0);
s_linkToken.transferAndCall(address(s_functionsRouter), fundingAmount, abi.encode(s_subscriptionId));
uint96 subscriptionBalanceAfter = s_functionsRouter.getSubscription(s_subscriptionId).balance;
- assertEq(subscriptionBalanceBefore + fundingAmount, subscriptionBalanceAfter);
+ assertEq(fundingAmount, subscriptionBalanceAfter);
}
}
From 6481bed281200e17ca09508b839dc90223fe3ffb Mon Sep 17 00:00:00 2001
From: Lukasz <120112546+lukaszcl@users.noreply.github.com>
Date: Thu, 9 Nov 2023 11:42:50 +0100
Subject: [PATCH 112/327] Add GetAPIClient to ClNode E2E docker wrapper
(#11240)
---
integration-tests/docker/test_env/cl_node.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go
index 4de3d27d75..6e74e54a4f 100644
--- a/integration-tests/docker/test_env/cl_node.go
+++ b/integration-tests/docker/test_env/cl_node.go
@@ -203,6 +203,10 @@ func (n *ClNode) GetContainerName() string {
return strings.Replace(name, "/", "", -1)
}
+func (n *ClNode) GetAPIClient() *client.ChainlinkClient {
+ return n.API
+}
+
func (n *ClNode) GetPeerUrl() (string, error) {
p2pKeys, err := n.API.MustReadP2PKeys()
if err != nil {
From dd2c5ef1a71d821d97f199573b04df71dcab6172 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Thu, 9 Nov 2023 12:58:22 +0100
Subject: [PATCH 113/327] Move Sol files from top level to project dirs
(#11227)
* mv agg interfaces
* rm unused ownable interface
* mv AuthorizedReceiverInterface
* mv libs to llo-feeds
* fix interfaces/AggregatorV2V3Interface ref
* rm dup interface
---
.../gas-snapshots/llo-feeds.gas-snapshot | 20 +++++++++++++++++++
.../scripts/native_solc_compile_all_feeds | 2 +-
contracts/src/v0.8/ValidatorProxy.sol | 2 +-
.../automation/v1_2/KeeperRegistry1_2.sol | 2 +-
.../automation/v1_3/KeeperRegistryBase1_3.sol | 2 +-
.../automation/v2_0/KeeperRegistryBase2_0.sol | 2 +-
.../automation/v2_1/KeeperRegistryBase2_1.sol | 2 +-
.../shared/interfaces/OwnableInterface.sol | 10 ----------
.../functions/dev/v1_X/FunctionsBilling.sol | 2 +-
.../functions/v1_0_0/FunctionsBilling.sol | 2 +-
.../v0.8/interfaces/FeedRegistryInterface.sol | 2 +-
.../arbitrum/ArbitrumSequencerUptimeFeed.sol | 6 +++---
.../l2ep/dev/arbitrum/ArbitrumValidator.sol | 2 +-
.../optimism/OptimismSequencerUptimeFeed.sol | 6 +++---
.../l2ep/dev/optimism/OptimismValidator.sol | 2 +-
contracts/src/v0.8/llo-feeds/FeeManager.sol | 2 +-
.../src/v0.8/llo-feeds/RewardManager.sol | 2 +-
contracts/src/v0.8/llo-feeds/Verifier.sol | 2 +-
.../src/v0.8/llo-feeds/VerifierProxy.sol | 2 +-
.../v0.8/llo-feeds/interfaces/IFeeManager.sol | 2 +-
.../llo-feeds/interfaces/IRewardManager.sol | 2 +-
.../v0.8/llo-feeds/interfaces/IVerifier.sol | 2 +-
.../interfaces/IVerifierFeeManager.sol | 2 +-
.../llo-feeds/interfaces/IVerifierProxy.sol | 2 +-
.../{ => llo-feeds}/libraries/ByteUtil.sol | 0
.../v0.8/{ => llo-feeds}/libraries/Common.sol | 0
.../test/ByteUtilTest.t.sol | 2 +-
.../test/fee-manager/BaseFeeManager.t.sol | 2 +-
.../FeeManager.getFeeAndReward.t.sol | 2 +-
.../fee-manager/FeeManager.processFee.t.sol | 2 +-
.../llo-feeds/test/gas/Gas_VerifierTest.t.sol | 2 +-
.../llo-feeds/test/mocks/ErroredVerifier.sol | 2 +-
.../reward-manager/BaseRewardManager.t.sol | 2 +-
.../reward-manager/RewardManager.claim.t.sol | 2 +-
.../RewardManager.setRecipients.t.sol | 2 +-
...RewardManager.updateRewardRecipients.t.sol | 2 +-
.../test/verifier/BaseVerifierTest.t.sol | 2 +-
.../VerifierProxySetVerifierTest.t.sol | 2 +-
.../VerifierSetConfigFromSourceTest.t.sol | 2 +-
.../test/verifier/VerifierSetConfigTest.t.sol | 2 +-
.../test/verifier/VerifierVerifyTest.t.sol | 2 +-
.../v0.8/mocks/MockAggregatorValidator.sol | 2 +-
.../dev/AuthorizedReceiver.sol | 2 +-
.../v0.8/operatorforwarder/dev/Operator.sol | 2 +-
.../AuthorizedReceiverInterface.sol | 0
.../interfaces/AggregatorInterface.sol | 0
.../interfaces/AggregatorV2V3Interface.sol | 0
.../interfaces/AggregatorV3Interface.sol | 0
.../AggregatorValidatorInterface.sol | 0
.../src/v0.8/shared/token/ERC677/ERC677.sol | 2 +-
.../shared/token/ERC677/IERC677Receiver.sol | 6 ------
contracts/src/v0.8/tests/FeedConsumer.sol | 2 +-
.../src/v0.8/tests/MockETHLINKAggregator.sol | 2 +-
contracts/src/v0.8/tests/MockV3Aggregator.sol | 2 +-
.../transmission/dev/ERC-4337/Paymaster.sol | 2 +-
contracts/src/v0.8/vrf/VRFCoordinatorV2.sol | 2 +-
contracts/src/v0.8/vrf/VRFV2Wrapper.sol | 2 +-
.../src/v0.8/vrf/dev/SubscriptionAPI.sol | 2 +-
.../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol | 2 +-
.../VRFCoordinatorV2TestHelper.sol | 2 +-
.../test/v0.8/dev/ArbitrumValidator.test.ts | 2 +-
.../test/v0.8/dev/OptimismValidator.test.ts | 2 +-
62 files changed, 76 insertions(+), 72 deletions(-)
delete mode 100644 contracts/src/v0.8/dev/shared/interfaces/OwnableInterface.sol
rename contracts/src/v0.8/{ => llo-feeds}/libraries/ByteUtil.sol (100%)
rename contracts/src/v0.8/{ => llo-feeds}/libraries/Common.sol (100%)
rename contracts/src/v0.8/{libraries => llo-feeds}/test/ByteUtilTest.t.sol (99%)
rename contracts/src/v0.8/{ => operatorforwarder/dev}/interfaces/AuthorizedReceiverInterface.sol (100%)
rename contracts/src/v0.8/{ => shared}/interfaces/AggregatorInterface.sol (100%)
rename contracts/src/v0.8/{ => shared}/interfaces/AggregatorV2V3Interface.sol (100%)
rename contracts/src/v0.8/{ => shared}/interfaces/AggregatorV3Interface.sol (100%)
rename contracts/src/v0.8/{ => shared}/interfaces/AggregatorValidatorInterface.sol (100%)
delete mode 100644 contracts/src/v0.8/shared/token/ERC677/IERC677Receiver.sol
diff --git a/contracts/gas-snapshots/llo-feeds.gas-snapshot b/contracts/gas-snapshots/llo-feeds.gas-snapshot
index a9877fbe33..ad9339a341 100644
--- a/contracts/gas-snapshots/llo-feeds.gas-snapshot
+++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot
@@ -1,3 +1,23 @@
+ByteUtilTest:test_readAddress() (gas: 542)
+ByteUtilTest:test_readAddressMultiWord() (gas: 540)
+ByteUtilTest:test_readAddressWithEmptyArray() (gas: 3274)
+ByteUtilTest:test_readAddressWithNotEnoughBytes() (gas: 3314)
+ByteUtilTest:test_readUint192Max() (gas: 485)
+ByteUtilTest:test_readUint192Min() (gas: 508)
+ByteUtilTest:test_readUint192MultiWord() (gas: 486)
+ByteUtilTest:test_readUint192WithEmptyArray() (gas: 3274)
+ByteUtilTest:test_readUint192WithNotEnoughBytes() (gas: 3314)
+ByteUtilTest:test_readUint256Max() (gas: 502)
+ByteUtilTest:test_readUint256Min() (gas: 546)
+ByteUtilTest:test_readUint256MultiWord() (gas: 500)
+ByteUtilTest:test_readUint256WithEmptyArray() (gas: 3296)
+ByteUtilTest:test_readUint256WithNotEnoughBytes() (gas: 3293)
+ByteUtilTest:test_readUint32Max() (gas: 507)
+ByteUtilTest:test_readUint32Min() (gas: 487)
+ByteUtilTest:test_readUint32MultiWord() (gas: 552)
+ByteUtilTest:test_readUint32WithEmptyArray() (gas: 3253)
+ByteUtilTest:test_readUint32WithNotEnoughBytes() (gas: 3272)
+ByteUtilTest:test_readZeroAddress() (gas: 519)
FeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52282)
FeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52235)
FeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78440)
diff --git a/contracts/scripts/native_solc_compile_all_feeds b/contracts/scripts/native_solc_compile_all_feeds
index eac5a6b70c..2c5808d466 100755
--- a/contracts/scripts/native_solc_compile_all_feeds
+++ b/contracts/scripts/native_solc_compile_all_feeds
@@ -30,6 +30,6 @@ compileContract () {
}
# Aggregators
-compileContract interfaces/AggregatorV2V3Interface.sol
+compileContract shared/interfaces/AggregatorV2V3Interface.sol
compileContract Chainlink.sol
compileContract ChainlinkClient.sol
diff --git a/contracts/src/v0.8/ValidatorProxy.sol b/contracts/src/v0.8/ValidatorProxy.sol
index 35909ad87d..627af73b39 100644
--- a/contracts/src/v0.8/ValidatorProxy.sol
+++ b/contracts/src/v0.8/ValidatorProxy.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol";
-import {AggregatorValidatorInterface} from "./interfaces/AggregatorValidatorInterface.sol";
+import {AggregatorValidatorInterface} from "./shared/interfaces/AggregatorValidatorInterface.sol";
import {TypeAndVersionInterface} from "./interfaces/TypeAndVersionInterface.sol";
// solhint-disable custom-errors
diff --git a/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol b/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol
index 262b8357f7..2fa1ee6188 100644
--- a/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol
+++ b/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol
@@ -7,7 +7,7 @@ import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../KeeperBase.sol";
import "../../interfaces/TypeAndVersionInterface.sol";
-import "../../interfaces/AggregatorV3Interface.sol";
+import "../../shared/interfaces/AggregatorV3Interface.sol";
import "../interfaces/KeeperCompatibleInterface.sol";
import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol";
import "../interfaces/MigratableKeeperRegistryInterface.sol";
diff --git a/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol b/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol
index 6328b65167..c21f3a7391 100644
--- a/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol
+++ b/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol
@@ -8,7 +8,7 @@ import "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_
import "../ExecutionPrevention.sol";
import {Config, Upkeep} from "../interfaces/v1_3/AutomationRegistryInterface1_3.sol";
import "../../shared/access/ConfirmedOwner.sol";
-import "../../interfaces/AggregatorV3Interface.sol";
+import "../../shared/interfaces/AggregatorV3Interface.sol";
import "../../shared/interfaces/LinkTokenInterface.sol";
import "../interfaces/KeeperCompatibleInterface.sol";
import "../interfaces/UpkeepTranscoderInterface.sol";
diff --git a/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol b/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol
index 14e9b20447..9b78e5806f 100644
--- a/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol
+++ b/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol
@@ -7,7 +7,7 @@ import "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_
import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";
import "../ExecutionPrevention.sol";
import "../../shared/access/ConfirmedOwner.sol";
-import "../../interfaces/AggregatorV3Interface.sol";
+import "../../shared/interfaces/AggregatorV3Interface.sol";
import "../../shared/interfaces/LinkTokenInterface.sol";
import "../interfaces/KeeperCompatibleInterface.sol";
import "../interfaces/UpkeepTranscoderInterface.sol";
diff --git a/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol b/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol
index f5d89de546..f81fcef636 100644
--- a/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol
+++ b/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol
@@ -11,7 +11,7 @@ import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompa
import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol";
import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
-import {AggregatorV3Interface} from "../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol";
import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol";
import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol";
import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol";
diff --git a/contracts/src/v0.8/dev/shared/interfaces/OwnableInterface.sol b/contracts/src/v0.8/dev/shared/interfaces/OwnableInterface.sol
deleted file mode 100644
index a24cbee504..0000000000
--- a/contracts/src/v0.8/dev/shared/interfaces/OwnableInterface.sol
+++ /dev/null
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.0;
-
-interface OwnableInterface {
- function owner() external returns (address);
-
- function transferOwnership(address recipient) external;
-
- function acceptOwnership() external;
-}
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
index ed67d48543..adc6218733 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.19;
import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol";
-import {AggregatorV3Interface} from "../../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol";
import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol";
import {Routable} from "./Routable.sol";
diff --git a/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol b/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol
index 5168bdc01e..8de53dd9c0 100644
--- a/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.19;
import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol";
-import {AggregatorV3Interface} from "../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol";
import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol";
import {Routable} from "./Routable.sol";
diff --git a/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol b/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol
index 1d2367d82a..f3272174ae 100644
--- a/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol
+++ b/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
pragma abicoder v2;
-import {AggregatorV2V3Interface} from "./AggregatorV2V3Interface.sol";
+import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol";
interface FeedRegistryInterface {
struct Phase {
diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol
index 6d8d31a808..5250fbda27 100644
--- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol
+++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol
@@ -2,9 +2,9 @@
pragma solidity ^0.8.4;
import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol";
-import {AggregatorInterface} from "../../../interfaces/AggregatorInterface.sol";
-import {AggregatorV3Interface} from "../../../interfaces/AggregatorV3Interface.sol";
-import {AggregatorV2V3Interface} from "../../../interfaces/AggregatorV2V3Interface.sol";
+import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol";
+import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol";
+import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol";
import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol";
import {FlagsInterface} from "../interfaces/FlagsInterface.sol";
import {ArbitrumSequencerUptimeFeedInterface} from "../interfaces/ArbitrumSequencerUptimeFeedInterface.sol";
diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol
index 3b5fd277e5..2043ffa628 100644
--- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol
+++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {AggregatorValidatorInterface} from "../../../interfaces/AggregatorValidatorInterface.sol";
+import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol";
import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol";
import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol";
import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol";
diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol
index b522a600ba..fcf6093e3c 100644
--- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol
+++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
-import {AggregatorInterface} from "../../../interfaces/AggregatorInterface.sol";
-import {AggregatorV3Interface} from "../../../interfaces/AggregatorV3Interface.sol";
-import {AggregatorV2V3Interface} from "../../../interfaces/AggregatorV2V3Interface.sol";
+import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol";
+import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol";
+import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol";
import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol";
import {OptimismSequencerUptimeFeedInterface} from "./../interfaces/OptimismSequencerUptimeFeedInterface.sol";
import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol";
diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol
index a955b7e92c..e41c61a453 100644
--- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol
+++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {AggregatorValidatorInterface} from "../../../interfaces/AggregatorValidatorInterface.sol";
+import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol";
import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol";
import {OptimismSequencerUptimeFeedInterface} from "./../interfaces/OptimismSequencerUptimeFeedInterface.sol";
diff --git a/contracts/src/v0.8/llo-feeds/FeeManager.sol b/contracts/src/v0.8/llo-feeds/FeeManager.sol
index 397605d9b2..c9981045a4 100644
--- a/contracts/src/v0.8/llo-feeds/FeeManager.sol
+++ b/contracts/src/v0.8/llo-feeds/FeeManager.sol
@@ -5,7 +5,7 @@ import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {IFeeManager} from "./interfaces/IFeeManager.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../libraries/Common.sol";
+import {Common} from "./libraries/Common.sol";
import {IRewardManager} from "./interfaces/IRewardManager.sol";
import {IWERC20} from "../shared/interfaces/IWERC20.sol";
import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
diff --git a/contracts/src/v0.8/llo-feeds/RewardManager.sol b/contracts/src/v0.8/llo-feeds/RewardManager.sol
index 3777b432fc..596755142e 100644
--- a/contracts/src/v0.8/llo-feeds/RewardManager.sol
+++ b/contracts/src/v0.8/llo-feeds/RewardManager.sol
@@ -5,7 +5,7 @@ import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {IRewardManager} from "./interfaces/IRewardManager.sol";
import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
-import {Common} from "../libraries/Common.sol";
+import {Common} from "./libraries/Common.sol";
import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
/**
diff --git a/contracts/src/v0.8/llo-feeds/Verifier.sol b/contracts/src/v0.8/llo-feeds/Verifier.sol
index f7ce156a60..3e668c09ff 100644
--- a/contracts/src/v0.8/llo-feeds/Verifier.sol
+++ b/contracts/src/v0.8/llo-feeds/Verifier.sol
@@ -6,7 +6,7 @@ import {IVerifier} from "./interfaces/IVerifier.sol";
import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../libraries/Common.sol";
+import {Common} from "./libraries/Common.sol";
// OCR2 standard
uint256 constant MAX_NUM_ORACLES = 31;
diff --git a/contracts/src/v0.8/llo-feeds/VerifierProxy.sol b/contracts/src/v0.8/llo-feeds/VerifierProxy.sol
index 6abb2b78e9..a35c54573c 100644
--- a/contracts/src/v0.8/llo-feeds/VerifierProxy.sol
+++ b/contracts/src/v0.8/llo-feeds/VerifierProxy.sol
@@ -8,7 +8,7 @@ import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol
import {AccessControllerInterface} from "../shared/interfaces/AccessControllerInterface.sol";
import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol";
-import {Common} from "../libraries/Common.sol";
+import {Common} from "./libraries/Common.sol";
/**
* The verifier proxy contract is the gateway for all report verification requests
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol b/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol
index 08373a6a5b..e006f0254e 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IFeeManager.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../../libraries/Common.sol";
+import {Common} from "../libraries/Common.sol";
import {IVerifierFeeManager} from "./IVerifierFeeManager.sol";
interface IFeeManager is IERC165, IVerifierFeeManager {
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol b/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol
index a76366a3eb..7a4d421671 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IRewardManager.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../../libraries/Common.sol";
+import {Common} from "../libraries/Common.sol";
interface IRewardManager is IERC165 {
/**
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol b/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol
index 9b9ba2e657..9e1e6d314c 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IVerifier.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../../libraries/Common.sol";
+import {Common} from "../libraries/Common.sol";
interface IVerifier is IERC165 {
/**
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol b/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol
index e5a73e612c..323b8a2cf0 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IVerifierFeeManager.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../../libraries/Common.sol";
+import {Common} from "../libraries/Common.sol";
interface IVerifierFeeManager is IERC165 {
/**
diff --git a/contracts/src/v0.8/llo-feeds/interfaces/IVerifierProxy.sol b/contracts/src/v0.8/llo-feeds/interfaces/IVerifierProxy.sol
index c2665261e9..d86bb46dd9 100644
--- a/contracts/src/v0.8/llo-feeds/interfaces/IVerifierProxy.sol
+++ b/contracts/src/v0.8/llo-feeds/interfaces/IVerifierProxy.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
-import {Common} from "../../libraries/Common.sol";
+import {Common} from "../libraries/Common.sol";
import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol";
import {IVerifierFeeManager} from "./IVerifierFeeManager.sol";
diff --git a/contracts/src/v0.8/libraries/ByteUtil.sol b/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol
similarity index 100%
rename from contracts/src/v0.8/libraries/ByteUtil.sol
rename to contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol
diff --git a/contracts/src/v0.8/libraries/Common.sol b/contracts/src/v0.8/llo-feeds/libraries/Common.sol
similarity index 100%
rename from contracts/src/v0.8/libraries/Common.sol
rename to contracts/src/v0.8/llo-feeds/libraries/Common.sol
diff --git a/contracts/src/v0.8/libraries/test/ByteUtilTest.t.sol b/contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol
similarity index 99%
rename from contracts/src/v0.8/libraries/test/ByteUtilTest.t.sol
rename to contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol
index 0629d0235e..b4e87364ac 100644
--- a/contracts/src/v0.8/libraries/test/ByteUtilTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {Test} from "forge-std/Test.sol";
-import {ByteUtil} from "../ByteUtil.sol";
+import {ByteUtil} from "../libraries/ByteUtil.sol";
contract ByteUtilTest is Test {
using ByteUtil for bytes;
diff --git a/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol b/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol
index ec2611f9e4..db0b3d8b3d 100644
--- a/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/fee-manager/BaseFeeManager.t.sol
@@ -4,7 +4,7 @@ pragma solidity 0.8.16;
import {Test} from "forge-std/Test.sol";
import {FeeManager} from "../../FeeManager.sol";
import {RewardManager} from "../../RewardManager.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {WERC20Mock} from "../../../shared/mocks/WERC20Mock.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
diff --git a/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.getFeeAndReward.t.sol b/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.getFeeAndReward.t.sol
index 801a1e3992..6a24806353 100644
--- a/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.getFeeAndReward.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.getFeeAndReward.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
import "./BaseFeeManager.t.sol";
/**
diff --git a/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.processFee.t.sol b/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.processFee.t.sol
index 9c2bd711ed..e0093b88a4 100644
--- a/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.processFee.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/fee-manager/FeeManager.processFee.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
import "./BaseFeeManager.t.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
diff --git a/contracts/src/v0.8/llo-feeds/test/gas/Gas_VerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/test/gas/Gas_VerifierTest.t.sol
index 3198576e8a..6938437b01 100644
--- a/contracts/src/v0.8/llo-feeds/test/gas/Gas_VerifierTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/gas/Gas_VerifierTest.t.sol
@@ -3,7 +3,7 @@ pragma solidity 0.8.16;
import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "../verifier/BaseVerifierTest.t.sol";
import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
contract Verifier_setConfig is BaseTest {
diff --git a/contracts/src/v0.8/llo-feeds/test/mocks/ErroredVerifier.sol b/contracts/src/v0.8/llo-feeds/test/mocks/ErroredVerifier.sol
index a0a404d88d..770b7b809d 100644
--- a/contracts/src/v0.8/llo-feeds/test/mocks/ErroredVerifier.sol
+++ b/contracts/src/v0.8/llo-feeds/test/mocks/ErroredVerifier.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {IVerifier} from "../../interfaces/IVerifier.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
contract ErroredVerifier is IVerifier {
function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
diff --git a/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol b/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol
index 3e50adef95..a9953d73c7 100644
--- a/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/reward-manager/BaseRewardManager.t.sol
@@ -4,7 +4,7 @@ pragma solidity 0.8.16;
import {Test} from "forge-std/Test.sol";
import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {RewardManager} from "../../RewardManager.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
import {IRewardManager} from "../../interfaces/IRewardManager.sol";
/**
diff --git a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.claim.t.sol b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.claim.t.sol
index 9a3749d1dd..a6c98c0303 100644
--- a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.claim.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.claim.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
/**
* @title BaseRewardManagerTest
diff --git a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.setRecipients.t.sol b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.setRecipients.t.sol
index 0e45ba00da..a8cf6260f5 100644
--- a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.setRecipients.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.setRecipients.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
/**
* @title BaseRewardManagerTest
diff --git a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.updateRewardRecipients.t.sol b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.updateRewardRecipients.t.sol
index 4b3063ac01..b1836e0fb9 100644
--- a/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.updateRewardRecipients.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/reward-manager/RewardManager.updateRewardRecipients.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
/**
* @title BaseRewardManagerTest
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol
index 91e0f9da90..34e2090115 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/BaseVerifierTest.t.sol
@@ -10,7 +10,7 @@ import {Verifier} from "../../Verifier.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol";
import {FeeManager} from "../../FeeManager.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
import {WERC20Mock} from "../../../shared/mocks/WERC20Mock.sol";
import {FeeManager} from "../../FeeManager.sol";
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol
index a6b23d7e8b..17fc49979e 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierProxySetVerifierTest.t.sol
@@ -5,7 +5,7 @@ import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.
import {IVerifier} from "../../interfaces/IVerifier.sol";
import {VerifierProxy} from "../../VerifierProxy.sol";
import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
contract VerifierProxyInitializeVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager {
function test_revertsIfNotCorrectVerifier() public {
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigFromSourceTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigFromSourceTest.t.sol
index 6c5eac9b6d..ba3acce0ee 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigFromSourceTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigFromSourceTest.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.16;
import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
contract VerifierSetConfigFromSourceTest is BaseTest {
function setUp() public virtual override {
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigTest.t.sol
index f0b045e7f3..374a976786 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierSetConfigTest.t.sol
@@ -3,7 +3,7 @@ pragma solidity 0.8.16;
import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol";
import {Verifier} from "../../Verifier.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
contract VerifierSetConfigTest is BaseTest {
function setUp() public virtual override {
diff --git a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierVerifyTest.t.sol b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierVerifyTest.t.sol
index b4fcac75d3..34e02bcfb9 100644
--- a/contracts/src/v0.8/llo-feeds/test/verifier/VerifierVerifyTest.t.sol
+++ b/contracts/src/v0.8/llo-feeds/test/verifier/VerifierVerifyTest.t.sol
@@ -5,7 +5,7 @@ import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.
import {Verifier} from "../../Verifier.sol";
import {VerifierProxy} from "../../VerifierProxy.sol";
import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol";
-import {Common} from "../../../libraries/Common.sol";
+import {Common} from "../../libraries/Common.sol";
contract VerifierVerifyTest is BaseTestWithConfiguredVerifierAndFeeManager {
bytes32[3] internal s_reportContext;
diff --git a/contracts/src/v0.8/mocks/MockAggregatorValidator.sol b/contracts/src/v0.8/mocks/MockAggregatorValidator.sol
index a43236de9f..bdc935cd23 100644
--- a/contracts/src/v0.8/mocks/MockAggregatorValidator.sol
+++ b/contracts/src/v0.8/mocks/MockAggregatorValidator.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import "../interfaces/AggregatorValidatorInterface.sol";
+import "../shared/interfaces/AggregatorValidatorInterface.sol";
contract MockAggregatorValidator is AggregatorValidatorInterface {
uint8 immutable id;
diff --git a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol b/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol
index 04d2635d58..bc5f1c0e7e 100644
--- a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol
+++ b/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
-import {AuthorizedReceiverInterface} from "../../interfaces/AuthorizedReceiverInterface.sol";
+import {AuthorizedReceiverInterface} from "./interfaces/AuthorizedReceiverInterface.sol";
// solhint-disable custom-errors
abstract contract AuthorizedReceiver is AuthorizedReceiverInterface {
diff --git a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol b/contracts/src/v0.8/operatorforwarder/dev/Operator.sol
index b83996a9ed..c8451bf03c 100644
--- a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol
+++ b/contracts/src/v0.8/operatorforwarder/dev/Operator.sol
@@ -5,7 +5,7 @@ import {AuthorizedReceiver} from "./AuthorizedReceiver.sol";
import {LinkTokenReceiver} from "./LinkTokenReceiver.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol";
-import {AuthorizedReceiverInterface} from "../../interfaces/AuthorizedReceiverInterface.sol";
+import {AuthorizedReceiverInterface} from "./interfaces/AuthorizedReceiverInterface.sol";
import {OperatorInterface} from "../../interfaces/OperatorInterface.sol";
import {IOwnable} from "../../shared/interfaces/IOwnable.sol";
import {WithdrawalInterface} from "./interfaces/WithdrawalInterface.sol";
diff --git a/contracts/src/v0.8/interfaces/AuthorizedReceiverInterface.sol b/contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol
similarity index 100%
rename from contracts/src/v0.8/interfaces/AuthorizedReceiverInterface.sol
rename to contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol
diff --git a/contracts/src/v0.8/interfaces/AggregatorInterface.sol b/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol
similarity index 100%
rename from contracts/src/v0.8/interfaces/AggregatorInterface.sol
rename to contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol
diff --git a/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol b/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol
similarity index 100%
rename from contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol
rename to contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol
diff --git a/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol b/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
similarity index 100%
rename from contracts/src/v0.8/interfaces/AggregatorV3Interface.sol
rename to contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
diff --git a/contracts/src/v0.8/interfaces/AggregatorValidatorInterface.sol b/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol
similarity index 100%
rename from contracts/src/v0.8/interfaces/AggregatorValidatorInterface.sol
rename to contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol
diff --git a/contracts/src/v0.8/shared/token/ERC677/ERC677.sol b/contracts/src/v0.8/shared/token/ERC677/ERC677.sol
index 9a68bac3a1..aa75a1170c 100644
--- a/contracts/src/v0.8/shared/token/ERC677/ERC677.sol
+++ b/contracts/src/v0.8/shared/token/ERC677/ERC677.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
import {IERC677} from "./IERC677.sol";
-import {IERC677Receiver} from "./IERC677Receiver.sol";
+import {IERC677Receiver} from "../../interfaces/IERC677Receiver.sol";
import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol";
import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol";
diff --git a/contracts/src/v0.8/shared/token/ERC677/IERC677Receiver.sol b/contracts/src/v0.8/shared/token/ERC677/IERC677Receiver.sol
deleted file mode 100644
index 2e44d860a8..0000000000
--- a/contracts/src/v0.8/shared/token/ERC677/IERC677Receiver.sol
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.0;
-
-interface IERC677Receiver {
- function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external;
-}
diff --git a/contracts/src/v0.8/tests/FeedConsumer.sol b/contracts/src/v0.8/tests/FeedConsumer.sol
index 3c9462b0ac..c9fc62357a 100644
--- a/contracts/src/v0.8/tests/FeedConsumer.sol
+++ b/contracts/src/v0.8/tests/FeedConsumer.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {AggregatorV2V3Interface} from "../interfaces/AggregatorV2V3Interface.sol";
+import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol";
contract FeedConsumer {
AggregatorV2V3Interface public immutable AGGREGATOR;
diff --git a/contracts/src/v0.8/tests/MockETHLINKAggregator.sol b/contracts/src/v0.8/tests/MockETHLINKAggregator.sol
index 98dd775a11..d685aac731 100644
--- a/contracts/src/v0.8/tests/MockETHLINKAggregator.sol
+++ b/contracts/src/v0.8/tests/MockETHLINKAggregator.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import "../interfaces/AggregatorV3Interface.sol";
+import "../shared/interfaces/AggregatorV3Interface.sol";
contract MockETHLINKAggregator is AggregatorV3Interface {
int256 public answer;
diff --git a/contracts/src/v0.8/tests/MockV3Aggregator.sol b/contracts/src/v0.8/tests/MockV3Aggregator.sol
index d261b2c4b1..9822d23e85 100644
--- a/contracts/src/v0.8/tests/MockV3Aggregator.sol
+++ b/contracts/src/v0.8/tests/MockV3Aggregator.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import "../interfaces/AggregatorV2V3Interface.sol";
+import "../shared/interfaces/AggregatorV2V3Interface.sol";
/**
* @title MockV3Aggregator
diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol
index cd84bb6a0e..970ddf6b7e 100644
--- a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol
+++ b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol
@@ -4,7 +4,7 @@ pragma solidity ^0.8.15;
import {IPaymaster} from "../../../vendor/entrypoint/interfaces/IPaymaster.sol";
import {SCALibrary} from "./SCALibrary.sol";
import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol";
-import {AggregatorV3Interface} from "../../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol";
import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol";
import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol";
import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol";
diff --git a/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol b/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol
index 5150d263a8..5acd3e7435 100644
--- a/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol
+++ b/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol
@@ -3,7 +3,7 @@ pragma solidity ^0.8.4;
import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol";
import {BlockhashStoreInterface} from "./interfaces/BlockhashStoreInterface.sol";
-import {AggregatorV3Interface} from "../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol";
import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol";
diff --git a/contracts/src/v0.8/vrf/VRFV2Wrapper.sol b/contracts/src/v0.8/vrf/VRFV2Wrapper.sol
index 805c8d76cb..abe479cb20 100644
--- a/contracts/src/v0.8/vrf/VRFV2Wrapper.sol
+++ b/contracts/src/v0.8/vrf/VRFV2Wrapper.sol
@@ -6,7 +6,7 @@ import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol";
import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol";
import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol";
-import {AggregatorV3Interface} from "../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol";
import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol";
import {VRFV2WrapperInterface} from "./interfaces/VRFV2WrapperInterface.sol";
import {VRFV2WrapperConsumerBase} from "./VRFV2WrapperConsumerBase.sol";
diff --git a/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol b/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol
index e4708bb1fc..d7cc5b86c5 100644
--- a/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol
+++ b/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol
@@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol";
import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";
-import {AggregatorV3Interface} from "../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol";
import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol";
import {IVRFSubscriptionV2Plus} from "./interfaces/IVRFSubscriptionV2Plus.sol";
diff --git a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol
index 9c3b983e30..a724b70a3d 100644
--- a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol
+++ b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol
@@ -6,7 +6,7 @@ import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.
import {IVRFV2PlusMigrate} from "./interfaces/IVRFV2PlusMigrate.sol";
import {VRFConsumerBaseV2Plus} from "./VRFConsumerBaseV2Plus.sol";
import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol";
-import {AggregatorV3Interface} from "../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol";
import {VRFV2PlusClient} from "./libraries/VRFV2PlusClient.sol";
import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol";
import {VRFV2PlusWrapperConsumerBase} from "./VRFV2PlusWrapperConsumerBase.sol";
diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol b/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol
index f938532968..c5d1d90c12 100644
--- a/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol
+++ b/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {AggregatorV3Interface} from "../../interfaces/AggregatorV3Interface.sol";
+import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol";
// Ideally this contract should inherit from VRFCoordinatorV2 and delegate calls to VRFCoordinatorV2
// However, due to exceeding contract size limit, the logic from VRFCoordinatorV2 is ported over to this contract
diff --git a/contracts/test/v0.8/dev/ArbitrumValidator.test.ts b/contracts/test/v0.8/dev/ArbitrumValidator.test.ts
index 2f95a6f6fb..232eea9583 100644
--- a/contracts/test/v0.8/dev/ArbitrumValidator.test.ts
+++ b/contracts/test/v0.8/dev/ArbitrumValidator.test.ts
@@ -12,7 +12,7 @@ import { abi as arbitrumSequencerStatusRecorderAbi } from '../../../artifacts/sr
// @ts-ignore
import { abi as arbitrumInboxAbi } from '../../../artifacts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol/IInbox.json'
// @ts-ignore
-import { abi as aggregatorAbi } from '../../../artifacts/src/v0.8/interfaces/AggregatorV2V3Interface.sol/AggregatorV2V3Interface.json'
+import { abi as aggregatorAbi } from '../../../artifacts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol/AggregatorV2V3Interface.json'
const truncateBigNumToAddress = (num: BigNumberish) => {
// Pad, then slice off '0x' prefix
diff --git a/contracts/test/v0.8/dev/OptimismValidator.test.ts b/contracts/test/v0.8/dev/OptimismValidator.test.ts
index 120b1057d1..ee69211f56 100644
--- a/contracts/test/v0.8/dev/OptimismValidator.test.ts
+++ b/contracts/test/v0.8/dev/OptimismValidator.test.ts
@@ -8,7 +8,7 @@ import { abi as optimismSequencerStatusRecorderAbi } from '../../../artifacts/sr
// @ts-ignore
import { abi as optimismL1CrossDomainMessengerAbi } from '@eth-optimism/contracts/artifacts/contracts/L1/messaging/L1CrossDomainMessenger.sol'
// @ts-ignore
-import { abi as aggregatorAbi } from '../../../artifacts/src/v0.8/interfaces/AggregatorV2V3Interface.sol/AggregatorV2V3Interface.json'
+import { abi as aggregatorAbi } from '../../../artifacts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol/AggregatorV2V3Interface.json'
describe('OptimismValidator', () => {
const GAS_LIMIT = BigNumber.from(1_900_000)
From cc05bfd1cf693f57dd5d7075fbc571523212b596 Mon Sep 17 00:00:00 2001
From: Dimitris Grigoriou
Date: Thu, 9 Nov 2023 14:49:26 +0200
Subject: [PATCH 114/327] Remove core label dependency from common (#11241)
---
common/txmgr/broadcaster.go | 2 +-
common/txmgr/confirmer.go | 2 +-
common/txmgr/resender.go | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index 80c7adbfc1..d68b509101 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -14,12 +14,12 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-relay/pkg/chains/label"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go
index 1d92149094..1d7446d9d2 100644
--- a/common/txmgr/confirmer.go
+++ b/common/txmgr/confirmer.go
@@ -14,13 +14,13 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/chainlink-relay/pkg/chains/label"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/client"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go
index d788b82773..75781c0840 100644
--- a/common/txmgr/resender.go
+++ b/common/txmgr/resender.go
@@ -6,11 +6,11 @@ import (
"fmt"
"time"
+ "github.com/smartcontractkit/chainlink-relay/pkg/chains/label"
"github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
From b9bd82ade13007862b3820cdbc8f4a82ab8c1f1c Mon Sep 17 00:00:00 2001
From: Cedric
Date: Thu, 9 Nov 2023 13:05:31 +0000
Subject: [PATCH 115/327] [chore] Add run id to flakey test logs (#11243)
---
.github/workflows/ci-core.yml | 2 ++
tools/flakeytests/cmd/runner/main.go | 3 ++-
tools/flakeytests/reporter.go | 1 +
tools/flakeytests/utils.go | 10 ++++++----
tools/flakeytests/utils_test.go | 10 +++++-----
5 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml
index 4053585590..d0bae66480 100644
--- a/.github/workflows/ci-core.yml
+++ b/.github/workflows/ci-core.yml
@@ -166,6 +166,7 @@ jobs:
GITHUB_EVENT_PATH: ${{ github.event_path }}
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_REPO: ${{ github.repository }}
+ GITHUB_RUN_ID: ${{ github.run_id }}
run: |
./runner \
-grafana_auth=$GRAFANA_CLOUD_BASIC_AUTH \
@@ -173,6 +174,7 @@ jobs:
-gh_sha=$GITHUB_SHA \
-gh_event_path=$GITHUB_EVENT_PATH \
-gh_event_name=$GITHUB_EVENT_NAME \
+ -gh_run_id=$GITHUB_RUN_ID \
-gh_repo=$GITHUB_REPO \
-command=./tools/bin/go_core_tests \
`ls -R ./artifacts/go_core_tests*/output.txt`
diff --git a/tools/flakeytests/cmd/runner/main.go b/tools/flakeytests/cmd/runner/main.go
index 601832a837..f38179f502 100644
--- a/tools/flakeytests/cmd/runner/main.go
+++ b/tools/flakeytests/cmd/runner/main.go
@@ -20,6 +20,7 @@ func main() {
ghEventPath := flag.String("gh_event_path", "", "path to associated gh event")
ghEventName := flag.String("gh_event_name", "", "type of associated gh event")
ghRepo := flag.String("gh_repo", "", "name of gh repository")
+ ghRunID := flag.String("gh_run_id", "", "run id of the gh workflow")
flag.Parse()
if *grafanaHost == "" {
@@ -47,7 +48,7 @@ func main() {
readers = append(readers, r)
}
- ctx := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath)
+ ctx := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID)
rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *command, ctx)
r := flakeytests.NewRunner(readers, rep, numReruns)
err := r.Run()
diff --git a/tools/flakeytests/reporter.go b/tools/flakeytests/reporter.go
index db3890b5c7..6696ec29a4 100644
--- a/tools/flakeytests/reporter.go
+++ b/tools/flakeytests/reporter.go
@@ -37,6 +37,7 @@ type Context struct {
PullRequestURL string `json:"pull_request_url,omitempty"`
Repository string `json:"repository"`
Type string `json:"event_type"`
+ RunURL string `json:"run_url,omitempty"`
}
type LokiReporter struct {
diff --git a/tools/flakeytests/utils.go b/tools/flakeytests/utils.go
index 7ead45c858..698a9b49c9 100644
--- a/tools/flakeytests/utils.go
+++ b/tools/flakeytests/utils.go
@@ -2,6 +2,7 @@ package flakeytests
import (
"encoding/json"
+ "fmt"
"io"
"log"
"os"
@@ -29,7 +30,7 @@ func DigString(mp map[string]interface{}, path []string) (string, error) {
return vs, nil
}
-func getGithubMetadata(repo string, eventName string, sha string, e io.Reader) Context {
+func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, runID string) Context {
d, err := io.ReadAll(e)
if err != nil {
log.Fatal("Error reading gh event into string")
@@ -41,7 +42,8 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader) C
log.Fatalf("Error unmarshaling gh event at path")
}
- basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName}
+ runURL := fmt.Sprintf("%s/actions/%s", repo, runID)
+ basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: runURL}
switch eventName {
case "pull_request":
prURL := ""
@@ -68,10 +70,10 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader) C
}
}
-func GetGithubMetadata(repo string, eventName string, sha string, path string) Context {
+func GetGithubMetadata(repo string, eventName string, sha string, path string, runID string) Context {
event, err := os.Open(path)
if err != nil {
log.Fatalf("Error reading gh event at path: %s", path)
}
- return getGithubMetadata(repo, eventName, sha, event)
+ return getGithubMetadata(repo, eventName, sha, event, runID)
}
diff --git a/tools/flakeytests/utils_test.go b/tools/flakeytests/utils_test.go
index 17d597c3c0..761d9cd255 100644
--- a/tools/flakeytests/utils_test.go
+++ b/tools/flakeytests/utils_test.go
@@ -36,13 +36,13 @@ var prEventTemplate = `
`
func TestGetGithubMetadata(t *testing.T) {
- repo, eventName, sha, event := "chainlink", "merge_group", "a-sha", `{}`
- ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event))
- assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName}, ctx)
+ repo, eventName, sha, event, runID := "chainlink", "merge_group", "a-sha", `{}`, "1234"
+ ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID)
+ assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: fmt.Sprintf("%s/actions/%s", repo, runID)}, ctx)
anotherSha, eventName, url := "another-sha", "pull_request", "a-url"
event = fmt.Sprintf(prEventTemplate, anotherSha, url)
sha = "302eb05d592132309b264e316f443f1ceb81b6c3"
- ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event))
- assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url}, ctx)
+ ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID)
+ assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url, RunURL: fmt.Sprintf("%s/actions/%s", repo, runID)}, ctx)
}
From bc4ff537590279a124b96ef28002acfc5579179f Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Thu, 9 Nov 2023 15:31:27 +0100
Subject: [PATCH 116/327] bump solhint & prettier deps (#11228)
* bump solhint deps
* bump cl solhint chainlink-solidity/explicit-returns
* bump solhint
* bump prettier-plugin-solidity
---
contracts/.solhint.json | 3 +-
contracts/.solhintignore | 2 +-
contracts/package.json | 10 +-
contracts/pnpm-lock.yaml | 145 +++++++++++++++---
.../interfaces/IOwnableFunctionsRouter.sol | 4 +-
.../tests/v1_X/FunctionsRequest.t.sol | 24 +--
.../src/v0.8/functions/tests/v1_X/OCR2.t.sol | 36 ++---
.../interfaces/IOwnableFunctionsRouter.sol | 4 +-
.../l2ep/dev/CrossDomainDelegateForwarder.sol | 4 +-
.../v0.8/l2ep/dev/CrossDomainForwarder.sol | 4 +-
10 files changed, 148 insertions(+), 88 deletions(-)
diff --git a/contracts/.solhint.json b/contracts/.solhint.json
index 3b69ca6a7f..e66b915d67 100644
--- a/contracts/.solhint.json
+++ b/contracts/.solhint.json
@@ -37,6 +37,7 @@
"chainlink-solidity/prefix-immutable-variables-with-i": "warn",
"chainlink-solidity/all-caps-constant-storage-variables": "warn",
"chainlink-solidity/no-hardhat-imports": "warn",
- "chainlink-solidity/inherited-constructor-args-not-in-contract-definition": "warn"
+ "chainlink-solidity/inherited-constructor-args-not-in-contract-definition": "warn",
+ "chainlink-solidity/explicit-returns": "warn"
}
}
diff --git a/contracts/.solhintignore b/contracts/.solhintignore
index bc7be4fbfe..ba2aac1fb3 100644
--- a/contracts/.solhintignore
+++ b/contracts/.solhintignore
@@ -1,4 +1,4 @@
-# 377 warnings
+# 344 warnings
#./src/v0.8/automation
# Ignore Functions v1.0.0 code that was frozen after audit
diff --git a/contracts/package.json b/contracts/package.json
index 05a5293e48..6d0b7af6cc 100644
--- a/contracts/package.json
+++ b/contracts/package.json
@@ -18,7 +18,7 @@
"prepublishOnly": "pnpm compile && ./scripts/prepublish_generate_abi_folder",
"publish-beta": "pnpm publish --tag beta",
"publish-prod": "npm dist-tag add @chainlink/contracts@0.8.0 latest",
- "solhint": "solhint --max-warnings 350 \"./src/v0.8/**/*.sol\""
+ "solhint": "solhint --max-warnings 371 \"./src/v0.8/**/*.sol\""
},
"files": [
"src/v0.8",
@@ -72,11 +72,11 @@
"istanbul": "^0.4.5",
"moment": "^2.29.4",
"prettier": "^3.0.3",
- "prettier-plugin-solidity": "1.1.3",
+ "prettier-plugin-solidity": "1.1.4-dev",
"rlp": "^2.2.7",
- "solhint": "^3.6.2",
- "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git",
- "solhint-plugin-prettier": "^0.0.5",
+ "solhint": "^4.0.0",
+ "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.0",
+ "solhint-plugin-prettier": "^0.1.0",
"solidity-coverage": "^0.8.5",
"ts-node": "^10.9.1",
"tslib": "^2.6.2",
diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml
index 2b6082d656..ac4efd5f59 100644
--- a/contracts/pnpm-lock.yaml
+++ b/contracts/pnpm-lock.yaml
@@ -140,20 +140,20 @@ devDependencies:
specifier: ^3.0.3
version: 3.0.3
prettier-plugin-solidity:
- specifier: 1.1.3
- version: 1.1.3(prettier@3.0.3)
+ specifier: 1.1.4-dev
+ version: 1.1.4-dev(prettier@3.0.3)
rlp:
specifier: ^2.2.7
version: 2.2.7
solhint:
- specifier: ^3.6.2
- version: 3.6.2
+ specifier: ^4.0.0
+ version: 4.0.0
solhint-plugin-chainlink-solidity:
- specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git
- version: github.com/smartcontractkit/chainlink-solhint-rules/6229ce5d3cc3e4a2454411bebc887c5ca240dcf2
+ specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.0
+ version: github.com/smartcontractkit/chainlink-solhint-rules/cfc50b32f95b730304a50deb2e27e88d87115874
solhint-plugin-prettier:
- specifier: ^0.0.5
- version: 0.0.5(prettier-plugin-solidity@1.1.3)(prettier@3.0.3)
+ specifier: ^0.1.0
+ version: 0.1.0(prettier-plugin-solidity@1.1.4-dev)(prettier@3.0.3)
solidity-coverage:
specifier: ^0.8.5
version: 0.8.5(hardhat@2.18.1)
@@ -1317,6 +1317,35 @@ packages:
tslib: 2.6.2
dev: true
+ /@pnpm/config.env-replace@1.1.0:
+ resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
+ engines: {node: '>=12.22.0'}
+ dev: true
+
+ /@pnpm/network.ca-file@1.0.2:
+ resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==}
+ engines: {node: '>=12.22.0'}
+ dependencies:
+ graceful-fs: 4.2.10
+ dev: true
+
+ /@pnpm/npm-conf@2.2.2:
+ resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@pnpm/config.env-replace': 1.1.0
+ '@pnpm/network.ca-file': 1.0.2
+ config-chain: 1.1.13
+ dev: true
+
+ /@prettier/sync@0.3.0(prettier@3.0.3):
+ resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==}
+ peerDependencies:
+ prettier: ^3.0.0
+ dependencies:
+ prettier: 3.0.3
+ dev: true
+
/@resolver-engine/core@0.3.3:
resolution: {integrity: sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==}
dependencies:
@@ -1477,6 +1506,12 @@ packages:
antlr4ts: 0.5.0-alpha.4
dev: true
+ /@solidity-parser/parser@0.16.1:
+ resolution: {integrity: sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==}
+ dependencies:
+ antlr4ts: 0.5.0-alpha.4
+ dev: true
+
/@szmarczak/http-timer@1.1.2:
resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==}
engines: {node: '>=6'}
@@ -3833,6 +3868,13 @@ packages:
typedarray: 0.0.6
dev: true
+ /config-chain@1.1.13:
+ resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
+ dependencies:
+ ini: 1.3.8
+ proto-list: 1.2.4
+ dev: true
+
/constant-case@2.0.0:
resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==}
dependencies:
@@ -7326,6 +7368,13 @@ packages:
graceful-fs: 4.2.10
dev: true
+ /latest-version@7.0.0:
+ resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==}
+ engines: {node: '>=14.16'}
+ dependencies:
+ package-json: 8.1.1
+ dev: true
+
/lcid@1.0.0:
resolution: {integrity: sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==}
engines: {node: '>=0.10.0'}
@@ -8523,6 +8572,16 @@ packages:
engines: {node: '>=6'}
dev: true
+ /package-json@8.1.1:
+ resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
+ engines: {node: '>=14.16'}
+ dependencies:
+ got: 12.1.0
+ registry-auth-token: 5.0.2
+ registry-url: 6.0.1
+ semver: 7.5.4
+ dev: true
+
/param-case@2.1.1:
resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==}
dependencies:
@@ -8822,6 +8881,7 @@ packages:
/prettier-plugin-solidity@1.1.3(prettier@2.8.8):
resolution: {integrity: sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==}
engines: {node: '>=12'}
+ requiresBuild: true
peerDependencies:
prettier: '>=2.3.0 || >=3.0.0-alpha.0'
dependencies:
@@ -8832,15 +8892,15 @@ packages:
dev: true
optional: true
- /prettier-plugin-solidity@1.1.3(prettier@3.0.3):
- resolution: {integrity: sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==}
- engines: {node: '>=12'}
+ /prettier-plugin-solidity@1.1.4-dev(prettier@3.0.3):
+ resolution: {integrity: sha512-SIDnHIPLN/Pod/dZoyJL07ViEcDxrXoT47ROQshpA/WFgyq/rRzLIc3oWkKfWiicHOD493Y/L1n9ds1GbwPoKQ==}
+ engines: {node: '>=16'}
peerDependencies:
- prettier: '>=2.3.0 || >=3.0.0-alpha.0'
+ prettier: '>=2.3.0'
dependencies:
- '@solidity-parser/parser': 0.16.0
+ '@solidity-parser/parser': 0.16.1
prettier: 3.0.3
- semver: 7.5.0
+ semver: 7.5.4
solidity-comments-extractor: 0.0.7
dev: true
@@ -8892,6 +8952,10 @@ packages:
signal-exit: 3.0.7
dev: true
+ /proto-list@1.2.4:
+ resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
+ dev: true
+
/proxy-addr@2.0.5:
resolution: {integrity: sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==}
engines: {node: '>= 0.10'}
@@ -9080,6 +9144,16 @@ packages:
unpipe: 1.0.0
dev: true
+ /rc@1.2.8:
+ resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+ hasBin: true
+ dependencies:
+ deep-extend: 0.6.0
+ ini: 1.3.8
+ minimist: 1.2.8
+ strip-json-comments: 2.0.1
+ dev: true
+
/read-pkg-up@1.0.1:
resolution: {integrity: sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==}
engines: {node: '>=0.10.0'}
@@ -9216,6 +9290,20 @@ packages:
regjsparser: 0.1.5
dev: true
+ /registry-auth-token@5.0.2:
+ resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@pnpm/npm-conf': 2.2.2
+ dev: true
+
+ /registry-url@6.0.1:
+ resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==}
+ engines: {node: '>=12'}
+ dependencies:
+ rc: 1.2.8
+ dev: true
+
/regjsgen@0.2.0:
resolution: {integrity: sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==}
dev: true
@@ -9553,9 +9641,11 @@ packages:
resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==}
engines: {node: '>=10'}
hasBin: true
+ requiresBuild: true
dependencies:
lru-cache: 6.0.0
dev: true
+ optional: true
/semver@7.5.4:
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
@@ -9863,19 +9953,20 @@ packages:
- debug
dev: true
- /solhint-plugin-prettier@0.0.5(prettier-plugin-solidity@1.1.3)(prettier@3.0.3):
- resolution: {integrity: sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA==}
+ /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.1.4-dev)(prettier@3.0.3):
+ resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==}
peerDependencies:
- prettier: ^1.15.0 || ^2.0.0
- prettier-plugin-solidity: ^1.0.0-alpha.14
+ prettier: ^3.0.0
+ prettier-plugin-solidity: ^1.0.0
dependencies:
+ '@prettier/sync': 0.3.0(prettier@3.0.3)
prettier: 3.0.3
prettier-linter-helpers: 1.0.0
- prettier-plugin-solidity: 1.1.3(prettier@3.0.3)
+ prettier-plugin-solidity: 1.1.4-dev(prettier@3.0.3)
dev: true
- /solhint@3.6.2:
- resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==}
+ /solhint@4.0.0:
+ resolution: {integrity: sha512-bFViMcFvhqVd/HK3Roo7xZXX5nbujS7Bxeg5vnZc9QvH0yCWCrQ38Yrn1pbAY9tlKROc6wFr+rK1mxYgYrjZgA==}
hasBin: true
dependencies:
'@solidity-parser/parser': 0.16.0
@@ -9889,6 +9980,7 @@ packages:
glob: 8.1.0
ignore: 5.2.4
js-yaml: 4.1.0
+ latest-version: 7.0.0
lodash: 4.17.21
pluralize: 8.0.0
semver: 7.5.4
@@ -10321,6 +10413,11 @@ packages:
engines: {node: '>=4'}
dev: true
+ /strip-json-comments@2.0.1:
+ resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -12349,8 +12446,8 @@ packages:
ethereumjs-util: 6.2.1
dev: true
- github.com/smartcontractkit/chainlink-solhint-rules/6229ce5d3cc3e4a2454411bebc887c5ca240dcf2:
- resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/6229ce5d3cc3e4a2454411bebc887c5ca240dcf2}
+ github.com/smartcontractkit/chainlink-solhint-rules/cfc50b32f95b730304a50deb2e27e88d87115874:
+ resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/cfc50b32f95b730304a50deb2e27e88d87115874}
name: '@chainlink/solhint-plugin-chainlink-solidity'
- version: 1.0.1
+ version: 1.2.0
dev: true
diff --git a/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol b/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol
index 39b84a930a..f6d7880da3 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol
@@ -5,6 +5,4 @@ import {IFunctionsRouter} from "./IFunctionsRouter.sol";
import {IOwnable} from "../../../../shared/interfaces/IOwnable.sol";
/// @title Chainlink Functions Router interface with Ownability.
-interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {
-
-}
+interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol
index 5457a221b6..e9684d9f5b 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol
@@ -30,31 +30,19 @@ contract FunctionsRequest_EncodeCBOR is Test {
}
/// @notice #initializeRequest
-contract FunctionsRequest_InitializeRequest is Test {
-
-}
+contract FunctionsRequest_InitializeRequest is Test {}
/// @notice #initializeRequestForInlineJavaScript
-contract FunctionsRequest_InitializeRequestForInlineJavaScript is Test {
-
-}
+contract FunctionsRequest_InitializeRequestForInlineJavaScript is Test {}
/// @notice #addSecretsReference
-contract FunctionsRequest_AddSecretsReference is Test {
-
-}
+contract FunctionsRequest_AddSecretsReference is Test {}
/// @notice #addDONHostedSecrets
-contract FunctionsRequest_AddDONHostedSecrets is Test {
-
-}
+contract FunctionsRequest_AddDONHostedSecrets is Test {}
/// @notice #setArgs
-contract FunctionsRequest_SetArgs is Test {
-
-}
+contract FunctionsRequest_SetArgs is Test {}
/// @notice #setBytesArgs
-contract FunctionsRequest_SetBytesArgs is Test {
-
-}
+contract FunctionsRequest_SetBytesArgs is Test {}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol b/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol
index 745ad4f0ae..3dc0db85a4 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol
@@ -6,39 +6,25 @@ pragma solidity ^0.8.19;
// ================================================================
/// @notice #constructor
-contract OCR2Base_Constructor {
-
-}
+contract OCR2Base_Constructor {}
/// @notice #checkConfigValid
-contract OCR2Base_CheckConfigValid {
-
-}
+contract OCR2Base_CheckConfigValid {}
/// @notice #latestConfigDigestAndEpoch
-contract OCR2Base_LatestConfigDigestAndEpoch {
-
-}
+contract OCR2Base_LatestConfigDigestAndEpoch {}
/// @notice #setConfig
-contract OCR2Base_SetConfig {
-
-}
+contract OCR2Base_SetConfig {}
/// @notice #configDigestFromConfigData
-contract OCR2Base_ConfigDigestFromConfigData {
-
-}
+contract OCR2Base_ConfigDigestFromConfigData {}
/// @notice #latestConfigDetails
-contract OCR2Base_LatestConfigDetails {
-
-}
+contract OCR2Base_LatestConfigDetails {}
/// @notice #transmitters
-contract OCR2Base_Transmitters {
-
-}
+contract OCR2Base_Transmitters {}
/// @notice #_report
contract OCR2Base__Report {
@@ -46,11 +32,7 @@ contract OCR2Base__Report {
}
/// @notice #requireExpectedMsgDataLength
-contract OCR2Base_RequireExpectedMsgDataLength {
-
-}
+contract OCR2Base_RequireExpectedMsgDataLength {}
/// @notice #transmit
-contract OCR2Base_Transmit {
-
-}
+contract OCR2Base_Transmit {}
diff --git a/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol b/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol
index 89eb48022b..c5f3d82677 100644
--- a/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol
+++ b/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol
@@ -5,6 +5,4 @@ import {IFunctionsRouter} from "./IFunctionsRouter.sol";
import {IOwnable} from "../../../shared/interfaces/IOwnable.sol";
/// @title Chainlink Functions Router interface with Ownability.
-interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {
-
-}
+interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {}
diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol
index 1eb6cba932..5dc73619af 100644
--- a/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol
+++ b/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol
@@ -10,6 +10,4 @@ import {DelegateForwarderInterface} from "./interfaces/DelegateForwarderInterfac
* @dev Any other L2 contract which uses this contract's address as a privileged position,
* can consider that position to be held by the `l1Owner`
*/
-abstract contract CrossDomainDelegateForwarder is DelegateForwarderInterface, CrossDomainOwnable {
-
-}
+abstract contract CrossDomainDelegateForwarder is DelegateForwarderInterface, CrossDomainOwnable {}
diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol
index 1f9066c505..8f218f66b8 100644
--- a/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol
+++ b/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol
@@ -10,6 +10,4 @@ import {ForwarderInterface} from "./interfaces/ForwarderInterface.sol";
* @dev Any other L2 contract which uses this contract's address as a privileged position,
* can consider that position to be held by the `l1Owner`
*/
-abstract contract CrossDomainForwarder is ForwarderInterface, CrossDomainOwnable {
-
-}
+abstract contract CrossDomainForwarder is ForwarderInterface, CrossDomainOwnable {}
From 606e5f2b113bca494199a8385819132d6625403d Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Thu, 9 Nov 2023 09:24:14 -0600
Subject: [PATCH 117/327] switch sqlx from smartcontractkit to jmoiron (#11238)
---
core/bridges/orm.go | 2 +-
core/bridges/orm_test.go | 2 +-
core/chains/evm/chain.go | 2 +-
core/chains/evm/chain_test.go | 2 +-
core/chains/evm/evm_txm.go | 2 +-
.../evm/forwarders/forwarder_manager.go | 3 +-
core/chains/evm/forwarders/orm.go | 2 +-
core/chains/evm/forwarders/orm_test.go | 2 +-
.../evm/headtracker/head_tracker_test.go | 2 +-
core/chains/evm/headtracker/orm.go | 2 +-
core/chains/evm/log/helpers_test.go | 2 +-
core/chains/evm/log/orm.go | 2 +-
core/chains/evm/logpoller/observability.go | 2 +-
core/chains/evm/logpoller/orm.go | 2 +-
core/chains/evm/txmgr/builder.go | 2 +-
core/chains/evm/txmgr/evm_tx_store.go | 2 +-
core/chains/evm/txmgr/txmgr_test.go | 2 +-
core/cmd/ocr2vrf_configure_commands.go | 2 +-
core/cmd/shell.go | 2 +-
core/cmd/shell_local.go | 2 +-
core/internal/cltest/cltest.go | 2 +-
core/internal/cltest/factories.go | 2 +-
core/internal/cltest/heavyweight/orm.go | 2 +-
core/internal/cltest/job_factories.go | 2 +-
core/internal/cltest/mocks.go | 2 +-
core/internal/mocks/application.go | 2 +-
core/internal/testutils/evmtest/evmtest.go | 2 +-
core/internal/testutils/pgtest/pgtest.go | 2 +-
core/internal/testutils/pgtest/txdb.go | 2 +-
core/internal/testutils/pgtest/txdb_test.go | 2 +-
core/internal/testutils/testutils.go | 2 +-
core/scripts/go.mod | 5 ++--
core/scripts/go.sum | 6 ++--
core/scripts/vrfv2/testnet/main.go | 2 +-
core/scripts/vrfv2plus/testnet/main.go | 5 ++--
core/services/chainlink/application.go | 2 +-
core/services/chainlink/relayer_factory.go | 2 +-
core/services/feeds/orm.go | 2 +-
core/services/feeds/orm_test.go | 2 +-
core/services/feeds/service.go | 3 +-
core/services/fluxmonitorv2/delegate.go | 2 +-
core/services/fluxmonitorv2/flux_monitor.go | 3 +-
.../fluxmonitorv2/flux_monitor_test.go | 2 +-
.../fluxmonitorv2/integrations_test.go | 2 +-
core/services/fluxmonitorv2/orm.go | 2 +-
core/services/functions/orm.go | 2 +-
core/services/job/helpers_test.go | 2 +-
core/services/job/job_orm_test.go | 3 +-
.../job/job_pipeline_orm_integration_test.go | 2 +-
core/services/job/orm.go | 6 ++--
core/services/job/orm_test.go | 2 +-
core/services/job/spawner.go | 2 +-
core/services/job/spawner_test.go | 2 +-
core/services/keeper/delegate.go | 2 +-
core/services/keeper/orm.go | 2 +-
core/services/keeper/orm_test.go | 2 +-
.../registry_synchronizer_helper_test.go | 2 +-
core/services/keeper/upkeep_executer_test.go | 2 +-
core/services/keystore/helpers_test.go | 2 +-
core/services/keystore/keystoretest.go | 2 +-
core/services/keystore/master.go | 2 +-
core/services/keystore/orm.go | 2 +-
core/services/ocr/contract_tracker.go | 3 +-
core/services/ocr/database.go | 2 +-
core/services/ocr/delegate.go | 2 +-
core/services/ocr/helpers_internal_test.go | 2 +-
core/services/ocr2/database.go | 2 +-
core/services/ocr2/database_test.go | 2 +-
core/services/ocr2/delegate.go | 2 +-
.../ocr2/plugins/dkg/persistence/db.go | 2 +-
.../ocr2/plugins/dkg/persistence/db_test.go | 2 +-
core/services/ocr2/plugins/dkg/plugin.go | 2 +-
.../services/ocr2/plugins/functions/plugin.go | 2 +-
.../evm21/logprovider/integration_test.go | 2 +-
.../ocr2/plugins/ocr2keeper/evm21/services.go | 2 +-
.../ocr2keeper/evm21/upkeepstate/orm.go | 2 +-
core/services/ocr2/plugins/ocr2keeper/util.go | 2 +-
core/services/ocrbootstrap/database_test.go | 2 +-
core/services/ocrbootstrap/delegate.go | 2 +-
core/services/ocrcommon/peer_wrapper.go | 2 +-
core/services/ocrcommon/peerstore.go | 3 +-
core/services/pg/connection.go | 2 +-
core/services/pg/connection_test.go | 2 +-
core/services/pg/helpers_test.go | 2 +-
core/services/pg/lease_lock.go | 2 +-
core/services/pg/lease_lock_test.go | 2 +-
core/services/pg/locked_db.go | 2 +-
core/services/pg/q.go | 2 +-
core/services/pg/sqlx.go | 2 +-
core/services/pg/transaction.go | 2 +-
core/services/pipeline/orm.go | 2 +-
core/services/pipeline/orm_test.go | 2 +-
core/services/pipeline/runner_test.go | 2 +-
core/services/pipeline/test_helpers_test.go | 2 +-
core/services/relay/evm/evm.go | 2 +-
core/services/relay/evm/evm_test.go | 2 +-
core/services/relay/evm/median.go | 2 +-
core/services/relay/evm/mercury/orm.go | 2 +-
.../evm/mercury/persistence_manager_test.go | 2 +-
.../services/relay/evm/mercury/transmitter.go | 2 +-
core/services/relay/evm/ocr2keeper.go | 2 +-
core/services/relay/evm/ocr2vrf.go | 2 +-
.../relay/evm/request_round_tracker.go | 3 +-
core/services/s4/postgres_orm.go | 2 +-
core/services/versioning/orm.go | 2 +-
core/services/vrf/delegate.go | 2 +-
core/services/vrf/delegate_test.go | 2 +-
core/services/vrf/v2/integration_v2_test.go | 2 +-
core/services/webhook/authorizer_test.go | 2 +-
.../webhook/external_initiator_manager.go | 2 +-
core/sessions/ldapauth/helpers_test.go | 2 +-
core/sessions/ldapauth/ldap.go | 2 +-
core/sessions/ldapauth/ldap_test.go | 2 +-
core/sessions/ldapauth/sync.go | 2 +-
core/sessions/localauth/orm.go | 2 +-
core/sessions/localauth/orm_test.go | 2 +-
core/sessions/webauthn.go | 2 +-
core/sessions/webauthn_test.go | 2 +-
core/store/migrate/migrate.go | 2 +-
.../migrations/0036_external_job_id.go | 2 +-
core/web/jobs_controller_test.go | 2 +-
go.mod | 5 ++--
go.sum | 6 ++--
integration-tests/go.mod | 5 ++--
integration-tests/go.sum | 6 ++--
.../universal/log_poller/helpers.go | 28 +++++++++----------
126 files changed, 156 insertions(+), 157 deletions(-)
diff --git a/core/bridges/orm.go b/core/bridges/orm.go
index 96801f4484..cfad1da836 100644
--- a/core/bridges/orm.go
+++ b/core/bridges/orm.go
@@ -6,8 +6,8 @@ import (
"sync"
"time"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/bridges/orm_test.go b/core/bridges/orm_test.go
index b110b4f519..0b485764c8 100644
--- a/core/bridges/orm_test.go
+++ b/core/bridges/orm_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go
index 936abc6216..b5896393d3 100644
--- a/core/chains/evm/chain.go
+++ b/core/chains/evm/chain.go
@@ -11,7 +11,7 @@ import (
gotoml "github.com/pelletier/go-toml/v2"
"go.uber.org/multierr"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
relaychains "github.com/smartcontractkit/chainlink-relay/pkg/chains"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/chains/evm/chain_test.go b/core/chains/evm/chain_test.go
index ba24598ef7..f25af87a35 100644
--- a/core/chains/evm/chain_test.go
+++ b/core/chains/evm/chain_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/mocks"
diff --git a/core/chains/evm/evm_txm.go b/core/chains/evm/evm_txm.go
index a8673e954a..bfc0f6378b 100644
--- a/core/chains/evm/evm_txm.go
+++ b/core/chains/evm/evm_txm.go
@@ -3,7 +3,7 @@ package evm
import (
"fmt"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go
index 46bca95ba3..934da487fd 100644
--- a/core/chains/evm/forwarders/forwarder_manager.go
+++ b/core/chains/evm/forwarders/forwarder_manager.go
@@ -10,9 +10,10 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmlogpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/forwarders/orm.go b/core/chains/evm/forwarders/orm.go
index 287698d22f..df89dbe29e 100644
--- a/core/chains/evm/forwarders/orm.go
+++ b/core/chains/evm/forwarders/orm.go
@@ -4,8 +4,8 @@ import (
"database/sql"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/chains/evm/forwarders/orm_test.go b/core/chains/evm/forwarders/orm_test.go
index a3d5c2831f..f6d63dc574 100644
--- a/core/chains/evm/forwarders/orm_test.go
+++ b/core/chains/evm/forwarders/orm_test.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
)
type TestORM struct {
diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go
index 502aa4ae6d..8af344098f 100644
--- a/core/chains/evm/headtracker/head_tracker_test.go
+++ b/core/chains/evm/headtracker/head_tracker_test.go
@@ -18,7 +18,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/exp/maps"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/chains/evm/headtracker/orm.go b/core/chains/evm/headtracker/orm.go
index 426df68b30..34f46ce44d 100644
--- a/core/chains/evm/headtracker/orm.go
+++ b/core/chains/evm/headtracker/orm.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go
index 688757a3e9..f787002578 100644
--- a/core/chains/evm/log/helpers_test.go
+++ b/core/chains/evm/log/helpers_test.go
@@ -18,7 +18,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
diff --git a/core/chains/evm/log/orm.go b/core/chains/evm/log/orm.go
index 4e51940f34..d383419d72 100644
--- a/core/chains/evm/log/orm.go
+++ b/core/chains/evm/log/orm.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go
index 7f54fa9f09..c4b58b42a2 100644
--- a/core/chains/evm/logpoller/observability.go
+++ b/core/chains/evm/logpoller/observability.go
@@ -5,9 +5,9 @@ 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"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go
index 06f4acbb4f..e044be2e0c 100644
--- a/core/chains/evm/logpoller/orm.go
+++ b/core/chains/evm/logpoller/orm.go
@@ -8,8 +8,8 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go
index 9123d1dfc0..5e3d61301c 100644
--- a/core/chains/evm/txmgr/builder.go
+++ b/core/chains/evm/txmgr/builder.go
@@ -4,7 +4,7 @@ import (
"math/big"
"time"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 971103bdfd..4db7989b46 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -13,9 +13,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/jackc/pgconn"
+ "github.com/jmoiron/sqlx"
"github.com/lib/pq"
pkgerrors "github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
nullv4 "gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink/v2/common/txmgr"
diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go
index 4aa54bc52a..4e201b9c6f 100644
--- a/core/chains/evm/txmgr/txmgr_test.go
+++ b/core/chains/evm/txmgr/txmgr_test.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks"
diff --git a/core/cmd/ocr2vrf_configure_commands.go b/core/cmd/ocr2vrf_configure_commands.go
index a3feddd611..bb4cef4708 100644
--- a/core/cmd/ocr2vrf_configure_commands.go
+++ b/core/cmd/ocr2vrf_configure_commands.go
@@ -14,7 +14,7 @@ import (
"github.com/pkg/errors"
"github.com/urfave/cli"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder"
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 80ecd2590b..595c42b9fe 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -29,7 +29,7 @@ import (
"go.uber.org/zap/zapcore"
"golang.org/x/sync/errgroup"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go
index dea9a29359..954cead5c3 100644
--- a/core/cmd/shell_local.go
+++ b/core/cmd/shell_local.go
@@ -29,7 +29,7 @@ import (
"golang.org/x/sync/errgroup"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/build"
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index e5c2ca031a..778ccbdb15 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -39,8 +39,8 @@ import (
"github.com/tidwall/gjson"
"github.com/urfave/cli"
+ "github.com/jmoiron/sqlx"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go
index 82235baf6b..a52b9a5d06 100644
--- a/core/internal/cltest/factories.go
+++ b/core/internal/cltest/factories.go
@@ -21,7 +21,7 @@ import (
"github.com/urfave/cli"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
diff --git a/core/internal/cltest/heavyweight/orm.go b/core/internal/cltest/heavyweight/orm.go
index b46e7114cf..5df28a4977 100644
--- a/core/internal/cltest/heavyweight/orm.go
+++ b/core/internal/cltest/heavyweight/orm.go
@@ -18,7 +18,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go
index b76d6c7ec2..a9e403fb60 100644
--- a/core/internal/cltest/job_factories.go
+++ b/core/internal/cltest/job_factories.go
@@ -7,7 +7,7 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go
index 00f72199dd..540924d7f0 100644
--- a/core/internal/cltest/mocks.go
+++ b/core/internal/cltest/mocks.go
@@ -11,7 +11,7 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go
index 7853361db9..48f8e12dac 100644
--- a/core/internal/mocks/application.go
+++ b/core/internal/mocks/application.go
@@ -31,7 +31,7 @@ import (
sessions "github.com/smartcontractkit/chainlink/v2/core/sessions"
- sqlx "github.com/smartcontractkit/sqlx"
+ sqlx "github.com/jmoiron/sqlx"
txmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go
index 3a08c81516..80237d218d 100644
--- a/core/internal/testutils/evmtest/evmtest.go
+++ b/core/internal/testutils/evmtest/evmtest.go
@@ -9,8 +9,8 @@ import (
"testing"
"github.com/ethereum/go-ethereum"
+ "github.com/jmoiron/sqlx"
"github.com/pelletier/go-toml/v2"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go
index 283326de85..1900fcc62b 100644
--- a/core/internal/testutils/pgtest/pgtest.go
+++ b/core/internal/testutils/pgtest/pgtest.go
@@ -5,8 +5,8 @@ import (
"testing"
"github.com/google/uuid"
+ "github.com/jmoiron/sqlx"
"github.com/scylladb/go-reflectx"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go
index 598a5dddc5..da9fd6cb2d 100644
--- a/core/internal/testutils/pgtest/txdb.go
+++ b/core/internal/testutils/pgtest/txdb.go
@@ -12,7 +12,7 @@ import (
"sync"
"testing"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"go.uber.org/multierr"
"github.com/smartcontractkit/chainlink/v2/core/config/env"
diff --git a/core/internal/testutils/pgtest/txdb_test.go b/core/internal/testutils/pgtest/txdb_test.go
index 71960c6150..c1aeef4b8c 100644
--- a/core/internal/testutils/pgtest/txdb_test.go
+++ b/core/internal/testutils/pgtest/txdb_test.go
@@ -6,7 +6,7 @@ import (
"time"
"github.com/google/uuid"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
)
diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go
index 79c86f0c5f..6ffd873d09 100644
--- a/core/internal/testutils/testutils.go
+++ b/core/internal/testutils/testutils.go
@@ -27,7 +27,7 @@ import (
"github.com/tidwall/gjson"
"go.uber.org/zap/zaptest/observer"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index aada3850db..3adcc130bc 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -13,6 +13,7 @@ require (
github.com/ethereum/go-ethereum v1.12.0
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.1
+ github.com/jmoiron/sqlx v1.3.5
github.com/joho/godotenv v1.4.0
github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f
github.com/montanaflynn/stats v0.7.1
@@ -24,7 +25,6 @@ require (
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
- github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.4
@@ -199,7 +199,6 @@ require (
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
- github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.0 // indirect
@@ -304,7 +303,7 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 4f42c84d4e..7f5d0e227d 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1462,8 +1462,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
@@ -1480,8 +1480,6 @@ github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGuj
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
-github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A=
-github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb/go.mod h1:HNUu4cJekUdsJbwRBCiOybtkPJEfGRELQPe2tkoDEyk=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/core/scripts/vrfv2/testnet/main.go b/core/scripts/vrfv2/testnet/main.go
index 5b216776bd..677c0b105e 100644
--- a/core/scripts/vrfv2/testnet/main.go
+++ b/core/scripts/vrfv2/testnet/main.go
@@ -21,7 +21,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/shopspring/decimal"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
"github.com/smartcontractkit/chainlink/v2/core/assets"
diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go
index 0d1bf9a948..b7940d6fda 100644
--- a/core/scripts/vrfv2plus/testnet/main.go
+++ b/core/scripts/vrfv2plus/testnet/main.go
@@ -6,12 +6,13 @@ import (
"encoding/hex"
"flag"
"fmt"
- "github.com/smartcontractkit/chainlink/core/scripts/vrfv2plus/testnet/v2plusscripts"
"log"
"math/big"
"os"
"strings"
+ "github.com/smartcontractkit/chainlink/core/scripts/vrfv2plus/testnet/v2plusscripts"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_specific_util_helper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface"
@@ -25,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/shopspring/decimal"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
"github.com/smartcontractkit/chainlink/v2/core/assets"
diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go
index 3285acdc07..0d479b1f1a 100644
--- a/core/services/chainlink/application.go
+++ b/core/services/chainlink/application.go
@@ -16,7 +16,7 @@ import (
"go.uber.org/multierr"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
relayservices "github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go
index 76bfcd1641..d452decda1 100644
--- a/core/services/chainlink/relayer_factory.go
+++ b/core/services/chainlink/relayer_factory.go
@@ -7,7 +7,7 @@ import (
"github.com/pelletier/go-toml/v2"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
diff --git a/core/services/feeds/orm.go b/core/services/feeds/orm.go
index 30b6ad632a..24ed7b8b36 100644
--- a/core/services/feeds/orm.go
+++ b/core/services/feeds/orm.go
@@ -9,7 +9,7 @@ import (
"github.com/lib/pq"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go
index 3d51ad45ff..02b9e24739 100644
--- a/core/services/feeds/orm_test.go
+++ b/core/services/feeds/orm_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go
index 20919606fa..f6e8952d6b 100644
--- a/core/services/feeds/service.go
+++ b/core/services/feeds/service.go
@@ -15,9 +15,10 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto"
diff --git a/core/services/fluxmonitorv2/delegate.go b/core/services/fluxmonitorv2/delegate.go
index d380122f71..e63f355672 100644
--- a/core/services/fluxmonitorv2/delegate.go
+++ b/core/services/fluxmonitorv2/delegate.go
@@ -3,7 +3,7 @@ package fluxmonitorv2
import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go
index 99d33c4239..5dbeaeafc3 100644
--- a/core/services/fluxmonitorv2/flux_monitor.go
+++ b/core/services/fluxmonitorv2/flux_monitor.go
@@ -13,9 +13,10 @@ import (
"github.com/pkg/errors"
"github.com/shopspring/decimal"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/bridges"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go
index 26ec520e7c..e81e1ba9e6 100644
--- a/core/services/fluxmonitorv2/flux_monitor_test.go
+++ b/core/services/fluxmonitorv2/flux_monitor_test.go
@@ -18,7 +18,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/assets"
diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go
index b2f24e08d5..38c73d3ad7 100644
--- a/core/services/fluxmonitorv2/integrations_test.go
+++ b/core/services/fluxmonitorv2/integrations_test.go
@@ -24,7 +24,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
diff --git a/core/services/fluxmonitorv2/orm.go b/core/services/fluxmonitorv2/orm.go
index 61395e8708..f85ab146c7 100644
--- a/core/services/fluxmonitorv2/orm.go
+++ b/core/services/fluxmonitorv2/orm.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/services/functions/orm.go b/core/services/functions/orm.go
index b6f692019a..7838c70085 100644
--- a/core/services/functions/orm.go
+++ b/core/services/functions/orm.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go
index 167ed5297c..4151ed401c 100644
--- a/core/services/job/helpers_test.go
+++ b/core/services/job/helpers_test.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index 6306dedcef..f4471e75c6 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -16,8 +16,6 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay"
-
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
@@ -38,6 +36,7 @@ import (
ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap"
"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"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go
index a2b6cc4618..f1307753d2 100644
--- a/core/services/job/job_pipeline_orm_integration_test.go
+++ b/core/services/job/job_pipeline_orm_integration_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/services/job/orm.go b/core/services/job/orm.go
index c6ec4ed5c8..fb897bc928 100644
--- a/core/services/job/orm.go
+++ b/core/services/job/orm.go
@@ -16,7 +16,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
@@ -992,11 +992,13 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer)
// range minID <-> maxID.
for n := int64(1000); maxID > 0 && len(ids) < limit; n *= 2 {
+ var batch []int64
minID := maxID - n
- if err = tx.Select(&ids, stmt, offset, limit-len(ids), minID, maxID); err != nil {
+ if err = tx.Select(&batch, stmt, offset, limit-len(ids), minID, maxID); err != nil {
err = errors.Wrap(err, "error loading runs")
return
}
+ ids = append(ids, batch...)
if offset > 0 {
if len(ids) > 0 {
// If we're already receiving rows back, then we no longer need an offset
diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go
index 48805388a3..41d02dba06 100644
--- a/core/services/job/orm_test.go
+++ b/core/services/job/orm_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go
index b2a8dad68f..03ee8cee13 100644
--- a/core/services/job/spawner.go
+++ b/core/services/job/spawner.go
@@ -9,7 +9,7 @@ import (
pkgerrors "github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
relayservices "github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go
index 1f10a86e9c..cfe646d866 100644
--- a/core/services/job/spawner_test.go
+++ b/core/services/job/spawner_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/services/keeper/delegate.go b/core/services/keeper/delegate.go
index 6c68203f84..6d41362496 100644
--- a/core/services/keeper/delegate.go
+++ b/core/services/keeper/delegate.go
@@ -3,7 +3,7 @@ package keeper
import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/keeper/orm.go b/core/services/keeper/orm.go
index e281d61064..91883f8056 100644
--- a/core/services/keeper/orm.go
+++ b/core/services/keeper/orm.go
@@ -3,9 +3,9 @@ package keeper
import (
"math/rand"
+ "github.com/jmoiron/sqlx"
"github.com/lib/pq"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go
index d990effa10..d67baa09a0 100644
--- a/core/services/keeper/orm_test.go
+++ b/core/services/keeper/orm_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go
index 63dc634353..966366b106 100644
--- a/core/services/keeper/registry_synchronizer_helper_test.go
+++ b/core/services/keeper/registry_synchronizer_helper_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go
index 7f9698435f..32b1d2c191 100644
--- a/core/services/keeper/upkeep_executer_test.go
+++ b/core/services/keeper/upkeep_executer_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/services/keystore/helpers_test.go b/core/services/keystore/helpers_test.go
index 13627dd023..d0b2a21ab3 100644
--- a/core/services/keystore/helpers_test.go
+++ b/core/services/keystore/helpers_test.go
@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go
index 0b5ce4e005..6efc8e76bc 100644
--- a/core/services/keystore/keystoretest.go
+++ b/core/services/keystore/keystoretest.go
@@ -4,7 +4,7 @@ import (
"errors"
"sync"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/keystore/master.go b/core/services/keystore/master.go
index fb28202b52..05f19495f9 100644
--- a/core/services/keystore/master.go
+++ b/core/services/keystore/master.go
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
diff --git a/core/services/keystore/orm.go b/core/services/keystore/orm.go
index 6f612105ea..3d75d6f236 100644
--- a/core/services/keystore/orm.go
+++ b/core/services/keystore/orm.go
@@ -7,8 +7,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
)
func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) ksORM {
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index f49e556d4e..db19bdd4f0 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -14,13 +14,14 @@ import (
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
"github.com/smartcontractkit/libocr/offchainreporting/confighelper"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go
index cd8e584e39..524dfa0e7b 100644
--- a/core/services/ocr/database.go
+++ b/core/services/ocr/database.go
@@ -11,9 +11,9 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go
index 6eb6714a47..0559469abb 100644
--- a/core/services/ocr/delegate.go
+++ b/core/services/ocr/delegate.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
diff --git a/core/services/ocr/helpers_internal_test.go b/core/services/ocr/helpers_internal_test.go
index 9a1f887986..57b669ef40 100644
--- a/core/services/ocr/helpers_internal_test.go
+++ b/core/services/ocr/helpers_internal_test.go
@@ -3,7 +3,7 @@ package ocr
import (
"testing"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/database.go b/core/services/ocr2/database.go
index 7061ad0452..5591f33fd4 100644
--- a/core/services/ocr2/database.go
+++ b/core/services/ocr2/database.go
@@ -6,11 +6,11 @@ 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/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/ocr2/database_test.go b/core/services/ocr2/database_test.go
index aabb2b33a7..b70ac629da 100644
--- a/core/services/ocr2/database_test.go
+++ b/core/services/ocr2/database_test.go
@@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/jmoiron/sqlx"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 1e87915bd1..95ec146915 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -14,6 +14,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
@@ -27,7 +28,6 @@ import (
"github.com/smartcontractkit/ocr2vrf/altbn_128"
dkgpkg "github.com/smartcontractkit/ocr2vrf/dkg"
"github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- "github.com/smartcontractkit/sqlx"
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
diff --git a/core/services/ocr2/plugins/dkg/persistence/db.go b/core/services/ocr2/plugins/dkg/persistence/db.go
index 75fb3b391f..c020a68cbe 100644
--- a/core/services/ocr2/plugins/dkg/persistence/db.go
+++ b/core/services/ocr2/plugins/dkg/persistence/db.go
@@ -9,13 +9,13 @@ import (
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
"github.com/smartcontractkit/ocr2vrf/types/hash"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go
index b830a8db3b..4e029c1cb2 100644
--- a/core/services/ocr2/plugins/dkg/persistence/db_test.go
+++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go
@@ -7,9 +7,9 @@ import (
"testing"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/jmoiron/sqlx"
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
"github.com/smartcontractkit/ocr2vrf/types/hash"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
diff --git a/core/services/ocr2/plugins/dkg/plugin.go b/core/services/ocr2/plugins/dkg/plugin.go
index 540518b553..92910ff7bb 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/ocr2vrf/altbn_128"
"github.com/smartcontractkit/ocr2vrf/dkg"
- "github.com/smartcontractkit/sqlx"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go
index 10f780371b..26cffac5ab 100644
--- a/core/services/ocr2/plugins/functions/plugin.go
+++ b/core/services/ocr2/plugins/functions/plugin.go
@@ -7,8 +7,8 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index 63ed4114b8..9a1e99610c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -17,7 +17,7 @@ import (
"go.uber.org/zap/zapcore"
"golang.org/x/time/rate"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/services.go b/core/services/ocr2/plugins/ocr2keeper/evm21/services.go
index f9d3dd9259..d178a9af57 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/services.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/services.go
@@ -4,11 +4,11 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/orm.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/orm.go
index 5db2f8bd0f..c918ad595f 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/orm.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/orm.go
@@ -4,8 +4,8 @@ import (
"math/big"
"time"
+ "github.com/jmoiron/sqlx"
"github.com/lib/pq"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go
index 132afd0d29..fca98d8700 100644
--- a/core/services/ocr2/plugins/ocr2keeper/util.go
+++ b/core/services/ocr2/plugins/ocr2keeper/util.go
@@ -3,12 +3,12 @@ package ocr2keeper
import (
"fmt"
+ "github.com/jmoiron/sqlx"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
ocr2keepers20 "github.com/smartcontractkit/ocr2keepers/pkg/v2"
ocr2keepers20coordinator "github.com/smartcontractkit/ocr2keepers/pkg/v2/coordinator"
ocr2keepers20polling "github.com/smartcontractkit/ocr2keepers/pkg/v2/observer/polling"
ocr2keepers20runner "github.com/smartcontractkit/ocr2keepers/pkg/v2/runner"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
diff --git a/core/services/ocrbootstrap/database_test.go b/core/services/ocrbootstrap/database_test.go
index 2f160eff58..e00e318c69 100644
--- a/core/services/ocrbootstrap/database_test.go
+++ b/core/services/ocrbootstrap/database_test.go
@@ -3,7 +3,7 @@ package ocrbootstrap_test
import (
"testing"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/stretchr/testify/require"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go
index 3910ca05d3..34e3ee0a71 100644
--- a/core/services/ocrbootstrap/delegate.go
+++ b/core/services/ocrbootstrap/delegate.go
@@ -7,8 +7,8 @@ import (
"github.com/pkg/errors"
+ "github.com/jmoiron/sqlx"
ocr "github.com/smartcontractkit/libocr/offchainreporting2plus"
- "github.com/smartcontractkit/sqlx"
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
diff --git a/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go
index 0781303275..1daa84b721 100644
--- a/core/services/ocrcommon/peer_wrapper.go
+++ b/core/services/ocrcommon/peer_wrapper.go
@@ -11,11 +11,11 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
+ "github.com/jmoiron/sqlx"
ocrnetworking "github.com/smartcontractkit/libocr/networking"
ocrnetworkingtypes "github.com/smartcontractkit/libocr/networking/types"
ocr1types "github.com/smartcontractkit/libocr/offchainreporting/types"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/services/ocrcommon/peerstore.go b/core/services/ocrcommon/peerstore.go
index f1c318a3bf..02a4d90f57 100644
--- a/core/services/ocrcommon/peerstore.go
+++ b/core/services/ocrcommon/peerstore.go
@@ -12,9 +12,10 @@ import (
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/recovery"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go
index 19c48a118b..0bafd5dcd0 100644
--- a/core/services/pg/connection.go
+++ b/core/services/pg/connection.go
@@ -6,8 +6,8 @@ import (
"github.com/google/uuid"
_ "github.com/jackc/pgx/v4/stdlib" // need to make sure pgx driver is registered before opening connection
+ "github.com/jmoiron/sqlx"
"github.com/scylladb/go-reflectx"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/store/dialects"
)
diff --git a/core/services/pg/connection_test.go b/core/services/pg/connection_test.go
index 92781343c6..651bf9d2d9 100644
--- a/core/services/pg/connection_test.go
+++ b/core/services/pg/connection_test.go
@@ -5,7 +5,7 @@ import (
"github.com/google/uuid"
_ "github.com/jackc/pgx/v4/stdlib"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/services/pg/helpers_test.go b/core/services/pg/helpers_test.go
index c5ccda6bd9..52158535a2 100644
--- a/core/services/pg/helpers_test.go
+++ b/core/services/pg/helpers_test.go
@@ -1,6 +1,6 @@
package pg
-import "github.com/smartcontractkit/sqlx"
+import "github.com/jmoiron/sqlx"
func SetConn(lock interface{}, conn *sqlx.Conn) {
switch v := lock.(type) {
diff --git a/core/services/pg/lease_lock.go b/core/services/pg/lease_lock.go
index 656005016e..e21cec44bd 100644
--- a/core/services/pg/lease_lock.go
+++ b/core/services/pg/lease_lock.go
@@ -8,8 +8,8 @@ import (
"time"
"github.com/google/uuid"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"go.uber.org/multierr"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/pg/lease_lock_test.go b/core/services/pg/lease_lock_test.go
index 483e03e003..1b4116b5bf 100644
--- a/core/services/pg/lease_lock_test.go
+++ b/core/services/pg/lease_lock_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go
index af4481285c..a9157fe1ae 100644
--- a/core/services/pg/locked_db.go
+++ b/core/services/pg/locked_db.go
@@ -8,7 +8,7 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/pg/q.go b/core/services/pg/q.go
index 9c70d813ab..470d39c825 100644
--- a/core/services/pg/q.go
+++ b/core/services/pg/q.go
@@ -15,7 +15,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
)
diff --git a/core/services/pg/sqlx.go b/core/services/pg/sqlx.go
index cd5427463d..820cd51712 100644
--- a/core/services/pg/sqlx.go
+++ b/core/services/pg/sqlx.go
@@ -7,7 +7,7 @@ import (
"github.com/pkg/errors"
mapper "github.com/scylladb/go-reflectx"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
)
diff --git a/core/services/pg/transaction.go b/core/services/pg/transaction.go
index 932b112085..d237c20d4c 100644
--- a/core/services/pg/transaction.go
+++ b/core/services/pg/transaction.go
@@ -10,7 +10,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go
index 148901bb36..d60050700f 100644
--- a/core/services/pipeline/orm.go
+++ b/core/services/pipeline/orm.go
@@ -11,7 +11,7 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go
index 295ad20a00..dcbbfd9c97 100644
--- a/core/services/pipeline/orm_test.go
+++ b/core/services/pipeline/orm_test.go
@@ -10,7 +10,7 @@ import (
"go.uber.org/zap/zapcore"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go
index 3abcdbe0ab..695590e7bd 100644
--- a/core/services/pipeline/runner_test.go
+++ b/core/services/pipeline/runner_test.go
@@ -37,7 +37,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks"
"github.com/smartcontractkit/chainlink/v2/core/utils"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
)
func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) {
diff --git a/core/services/pipeline/test_helpers_test.go b/core/services/pipeline/test_helpers_test.go
index 8353f5fb5b..3b72a1625b 100644
--- a/core/services/pipeline/test_helpers_test.go
+++ b/core/services/pipeline/test_helpers_test.go
@@ -16,7 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
)
func fakeExternalAdapter(t *testing.T, expectedRequest, response interface{}) http.Handler {
diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go
index 3f45b41f46..111e3622b1 100644
--- a/core/services/relay/evm/evm.go
+++ b/core/services/relay/evm/evm.go
@@ -13,12 +13,12 @@ import (
pkgerrors "github.com/pkg/errors"
"go.uber.org/multierr"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median/evmreportcodec"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
diff --git a/core/services/relay/evm/evm_test.go b/core/services/relay/evm/evm_test.go
index 4e9c44a7b9..8f49128ff2 100644
--- a/core/services/relay/evm/evm_test.go
+++ b/core/services/relay/evm/evm_test.go
@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/relay/evm/median.go b/core/services/relay/evm/median.go
index b7d751e01e..5184326cf2 100644
--- a/core/services/relay/evm/median.go
+++ b/core/services/relay/evm/median.go
@@ -7,12 +7,12 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator"
diff --git a/core/services/relay/evm/mercury/orm.go b/core/services/relay/evm/mercury/orm.go
index 7273519f6b..f8d4c8cb1e 100644
--- a/core/services/relay/evm/mercury/orm.go
+++ b/core/services/relay/evm/mercury/orm.go
@@ -8,9 +8,9 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/lib/pq"
pkgerrors "github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
diff --git a/core/services/relay/evm/mercury/persistence_manager_test.go b/core/services/relay/evm/mercury/persistence_manager_test.go
index d185a64a8f..dbdb977725 100644
--- a/core/services/relay/evm/mercury/persistence_manager_test.go
+++ b/core/services/relay/evm/mercury/persistence_manager_test.go
@@ -6,8 +6,8 @@ import (
"time"
"github.com/cometbft/cometbft/libs/rand"
+ "github.com/jmoiron/sqlx"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go
index 557210e58a..269f28b122 100644
--- a/core/services/relay/evm/mercury/transmitter.go
+++ b/core/services/relay/evm/mercury/transmitter.go
@@ -16,9 +16,9 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go
index baf98b9b00..a284d677eb 100644
--- a/core/services/relay/evm/ocr2keeper.go
+++ b/core/services/relay/evm/ocr2keeper.go
@@ -8,12 +8,12 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
"github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
- "github.com/smartcontractkit/sqlx"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go
index 14004d0b1a..0c9414068e 100644
--- a/core/services/relay/evm/ocr2vrf.go
+++ b/core/services/relay/evm/ocr2vrf.go
@@ -7,11 +7,11 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
diff --git a/core/services/relay/evm/request_round_tracker.go b/core/services/relay/evm/request_round_tracker.go
index 4e065f2dfd..c1c3a49e0e 100644
--- a/core/services/relay/evm/request_round_tracker.go
+++ b/core/services/relay/evm/request_round_tracker.go
@@ -9,11 +9,12 @@ import (
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator"
diff --git a/core/services/s4/postgres_orm.go b/core/services/s4/postgres_orm.go
index d0a79dba95..1f91270fd0 100644
--- a/core/services/s4/postgres_orm.go
+++ b/core/services/s4/postgres_orm.go
@@ -9,8 +9,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
)
const (
diff --git a/core/services/versioning/orm.go b/core/services/versioning/orm.go
index 03bd64fdd2..8ed745955d 100644
--- a/core/services/versioning/orm.go
+++ b/core/services/versioning/orm.go
@@ -7,8 +7,8 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/jackc/pgconn"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go
index 558d48752d..e976d01b99 100644
--- a/core/services/vrf/delegate.go
+++ b/core/services/vrf/delegate.go
@@ -10,7 +10,7 @@ import (
"github.com/theodesp/go-heaps/pairing"
"go.uber.org/multierr"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go
index 927e2ae682..389e1159be 100644
--- a/core/services/vrf/delegate_test.go
+++ b/core/services/vrf/delegate_test.go
@@ -6,7 +6,7 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index e50ed91491..1f607da2f2 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -28,7 +28,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
diff --git a/core/services/webhook/authorizer_test.go b/core/services/webhook/authorizer_test.go
index 19dbf38140..b6eb2feacc 100644
--- a/core/services/webhook/authorizer_test.go
+++ b/core/services/webhook/authorizer_test.go
@@ -3,7 +3,7 @@ package webhook_test
import (
"testing"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/services/webhook/external_initiator_manager.go b/core/services/webhook/external_initiator_manager.go
index 2e881ec42d..01edf82b11 100644
--- a/core/services/webhook/external_initiator_manager.go
+++ b/core/services/webhook/external_initiator_manager.go
@@ -10,7 +10,7 @@ import (
"github.com/lib/pq"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/sessions/ldapauth/helpers_test.go b/core/sessions/ldapauth/helpers_test.go
index c554d5436e..3566ea8438 100644
--- a/core/sessions/ldapauth/helpers_test.go
+++ b/core/sessions/ldapauth/helpers_test.go
@@ -3,7 +3,7 @@ package ldapauth
import (
"time"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/sessions/ldapauth/ldap.go b/core/sessions/ldapauth/ldap.go
index 188f2684e7..04f6fbfbbb 100644
--- a/core/sessions/ldapauth/ldap.go
+++ b/core/sessions/ldapauth/ldap.go
@@ -32,7 +32,7 @@ import (
"time"
"github.com/go-ldap/ldap/v3"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
diff --git a/core/sessions/ldapauth/ldap_test.go b/core/sessions/ldapauth/ldap_test.go
index 261141d66e..c85e0db831 100644
--- a/core/sessions/ldapauth/ldap_test.go
+++ b/core/sessions/ldapauth/ldap_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
diff --git a/core/sessions/ldapauth/sync.go b/core/sessions/ldapauth/sync.go
index ce7a338f40..67f101b62a 100644
--- a/core/sessions/ldapauth/sync.go
+++ b/core/sessions/ldapauth/sync.go
@@ -6,8 +6,8 @@ import (
"time"
"github.com/go-ldap/ldap/v3"
+ "github.com/jmoiron/sqlx"
"github.com/lib/pq"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/sessions/localauth/orm.go b/core/sessions/localauth/orm.go
index d6fb8cd578..090dc468a6 100644
--- a/core/sessions/localauth/orm.go
+++ b/core/sessions/localauth/orm.go
@@ -6,8 +6,8 @@ import (
"strings"
"time"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
- "github.com/smartcontractkit/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
diff --git a/core/sessions/localauth/orm_test.go b/core/sessions/localauth/orm_test.go
index 7868937ad0..c2e155de28 100644
--- a/core/sessions/localauth/orm_test.go
+++ b/core/sessions/localauth/orm_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/sessions/webauthn.go b/core/sessions/webauthn.go
index 41e31d7aaa..89e7758bc5 100644
--- a/core/sessions/webauthn.go
+++ b/core/sessions/webauthn.go
@@ -9,8 +9,8 @@ import (
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
+ sqlxTypes "github.com/jmoiron/sqlx/types"
"github.com/pkg/errors"
- sqlxTypes "github.com/smartcontractkit/sqlx/types"
)
// WebAuthn holds the credentials for API user.
diff --git a/core/sessions/webauthn_test.go b/core/sessions/webauthn_test.go
index b3c1ecf789..9c055d9c79 100644
--- a/core/sessions/webauthn_test.go
+++ b/core/sessions/webauthn_test.go
@@ -7,7 +7,7 @@ import (
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
- sqlxTypes "github.com/smartcontractkit/sqlx/types"
+ sqlxTypes "github.com/jmoiron/sqlx/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
diff --git a/core/store/migrate/migrate.go b/core/store/migrate/migrate.go
index 69cf9a7824..1e58d7a0b0 100644
--- a/core/store/migrate/migrate.go
+++ b/core/store/migrate/migrate.go
@@ -9,9 +9,9 @@ import (
"strconv"
"strings"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"github.com/pressly/goose/v3"
- "github.com/smartcontractkit/sqlx"
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink/v2/core/config/env"
diff --git a/core/store/migrate/migrations/0036_external_job_id.go b/core/store/migrate/migrations/0036_external_job_id.go
index 8637bd38f5..fc9ec08ec6 100644
--- a/core/store/migrate/migrations/0036_external_job_id.go
+++ b/core/store/migrate/migrations/0036_external_job_id.go
@@ -6,8 +6,8 @@ import (
"fmt"
"github.com/google/uuid"
+ "github.com/jmoiron/sqlx"
"github.com/pressly/goose/v3"
- "github.com/smartcontractkit/sqlx"
)
func init() {
diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go
index 0bd947bbce..2e3f3a8369 100644
--- a/core/web/jobs_controller_test.go
+++ b/core/web/jobs_controller_test.go
@@ -23,7 +23,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/sqlx"
+ "github.com/jmoiron/sqlx"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/go.mod b/go.mod
index e6af9533dc..67896860e0 100644
--- a/go.mod
+++ b/go.mod
@@ -65,14 +65,13 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
- github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wsrpc v0.7.2
@@ -238,7 +237,7 @@ require (
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
- github.com/jmoiron/sqlx v1.3.5 // indirect
+ github.com/jmoiron/sqlx v1.3.5
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
diff --git a/go.sum b/go.sum
index 5c70c22a75..89e9aee85f 100644
--- a/go.sum
+++ b/go.sum
@@ -1463,8 +1463,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
@@ -1481,8 +1481,6 @@ github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGuj
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
-github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A=
-github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb/go.mod h1:HNUu4cJekUdsJbwRBCiOybtkPJEfGRELQPe2tkoDEyk=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 8fe63a46d2..c51bd3c4f6 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -12,6 +12,7 @@ require (
github.com/ethereum/go-ethereum v1.12.0
github.com/go-resty/resty/v2 v2.7.0
github.com/google/uuid v1.3.1
+ github.com/jmoiron/sqlx v1.3.5
github.com/kelseyhightower/envconfig v1.4.0
github.com/lib/pq v1.10.9
github.com/manifoldco/promptui v0.9.0
@@ -26,7 +27,6 @@ require (
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
- github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wasp v0.3.0
github.com/spf13/cobra v1.6.1
@@ -259,7 +259,6 @@ require (
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
- github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -387,7 +386,7 @@ require (
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index b8e8b205c8..4afa0de1d3 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2367,8 +2367,8 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353 h1:4iO3Ei1b/Lb0yprzclk93e1aQnYF92sIe+EJzMG87y4=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231101160906-7acebcc1b353/go.mod h1:hMhGr9ok3p4442keFtK6u6Ei9yWfG66fmDwsFi3aHcw=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
@@ -2387,8 +2387,6 @@ github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGuj
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
-github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A=
-github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb/go.mod h1:HNUu4cJekUdsJbwRBCiOybtkPJEfGRELQPe2tkoDEyk=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go
index aa488eb1be..ab7a221955 100644
--- a/integration-tests/universal/log_poller/helpers.go
+++ b/integration-tests/universal/log_poller/helpers.go
@@ -17,36 +17,36 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
geth_types "github.com/ethereum/go-ethereum/core/types"
+ "github.com/jmoiron/sqlx"
"github.com/rs/zerolog"
+ "github.com/scylladb/go-reflectx"
+ "github.com/stretchr/testify/require"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctf_blockchain "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/chainlink/integration-tests/actions"
- "github.com/smartcontractkit/chainlink/integration-tests/client"
- "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
- "github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
"github.com/smartcontractkit/wasp"
+ evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
+ lpEvm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
+ le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
+ core_logger "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/actions"
+ "github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/stretchr/testify/require"
-
- "github.com/scylladb/go-reflectx"
+ "github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
utils2 "github.com/smartcontractkit/chainlink/integration-tests/utils"
- evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
- lpEvm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
- le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
- core_logger "github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/sqlx"
)
var (
From c2a1b26ed24f50a30cac95bd25a8f517f3367c8c Mon Sep 17 00:00:00 2001
From: Sam
Date: Thu, 9 Nov 2023 11:42:44 -0500
Subject: [PATCH 118/327] Actually serialize the LatestBlocks part of the
observation (#11237)
* Actually serialize the LatestBlocks part of the observation
* Fix tests
* Regenerate mocks
---
.gitignore | 6 +-
common/headtracker/head_tracker.go | 3 +
common/headtracker/types/mocks/head.go | 20 +++-
common/types/head.go | 9 +-
common/types/mocks/head.go | 20 +++-
.../evm/client/simulated_backend_client.go | 2 +-
core/chains/evm/types/models.go | 4 +
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
.../relay/evm/mercury/v1/data_source.go | 3 +-
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
tools/flakeytests/coverage.txt | 93 -------------------
15 files changed, 68 insertions(+), 110 deletions(-)
delete mode 100644 tools/flakeytests/coverage.txt
diff --git a/.gitignore b/.gitignore
index 61ebfab0e9..48e228eb83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -79,7 +79,9 @@ MacOSX*
contracts/yarn.lock
-
# Ignore DevSpace cache and log folder
.devspace/
-go.work*
\ No newline at end of file
+go.work*
+
+# This sometimes shows up for some reason
+tools/flakeytests/coverage.txt
diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go
index c24dde595c..54262dd93f 100644
--- a/common/headtracker/head_tracker.go
+++ b/common/headtracker/head_tracker.go
@@ -197,6 +197,9 @@ func (ht *HeadTracker[HTH, S, ID, BLOCK_HASH]) handleNewHead(ctx context.Context
"blockHeight", head.BlockNumber(),
"blockHash", head.BlockHash(),
"parentHeadHash", head.GetParentHash(),
+ "blockTs", head.GetTimestamp(),
+ "blockTsUnix", head.GetTimestamp().Unix(),
+ "blockDifficulty", head.BlockDifficulty(),
)
err := ht.headSaver.Save(ctx, head)
diff --git a/common/headtracker/types/mocks/head.go b/common/headtracker/types/mocks/head.go
index a56590b6ef..1de1f78de8 100644
--- a/common/headtracker/types/mocks/head.go
+++ b/common/headtracker/types/mocks/head.go
@@ -3,9 +3,13 @@
package mocks
import (
+ time "time"
+
+ mock "github.com/stretchr/testify/mock"
+
types "github.com/smartcontractkit/chainlink/v2/common/types"
+
utils "github.com/smartcontractkit/chainlink/v2/core/utils"
- mock "github.com/stretchr/testify/mock"
)
// Head is an autogenerated mock type for the Head type
@@ -131,6 +135,20 @@ func (_m *Head[BLOCK_HASH, CHAIN_ID]) GetParentHash() BLOCK_HASH {
return r0
}
+// GetTimestamp provides a mock function with given fields:
+func (_m *Head[BLOCK_HASH, CHAIN_ID]) GetTimestamp() time.Time {
+ ret := _m.Called()
+
+ var r0 time.Time
+ if rf, ok := ret.Get(0).(func() time.Time); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(time.Time)
+ }
+
+ return r0
+}
+
// HasChainID provides a mock function with given fields:
func (_m *Head[BLOCK_HASH, CHAIN_ID]) HasChainID() bool {
ret := _m.Called()
diff --git a/common/types/head.go b/common/types/head.go
index bef9c30d9e..000bad2390 100644
--- a/common/types/head.go
+++ b/common/types/head.go
@@ -1,6 +1,10 @@
package types
-import "github.com/smartcontractkit/chainlink/v2/core/utils"
+import (
+ "time"
+
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
// Head provides access to a chain's head, as needed by the TxManager.
// This is a generic interface which ALL chains will implement.
@@ -10,6 +14,9 @@ type Head[BLOCK_HASH Hashable] interface {
// BlockNumber is the head's block number
BlockNumber() int64
+ // Timestamp the time of mining of the block
+ GetTimestamp() time.Time
+
// ChainLength returns the length of the chain followed by recursively looking up parents
ChainLength() uint32
diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go
index 816a9234a3..82fd910a08 100644
--- a/common/types/mocks/head.go
+++ b/common/types/mocks/head.go
@@ -3,9 +3,13 @@
package mocks
import (
+ time "time"
+
+ mock "github.com/stretchr/testify/mock"
+
types "github.com/smartcontractkit/chainlink/v2/common/types"
+
utils "github.com/smartcontractkit/chainlink/v2/core/utils"
- mock "github.com/stretchr/testify/mock"
)
// Head is an autogenerated mock type for the Head type
@@ -117,6 +121,20 @@ func (_m *Head[BLOCK_HASH]) GetParentHash() BLOCK_HASH {
return r0
}
+// GetTimestamp provides a mock function with given fields:
+func (_m *Head[BLOCK_HASH]) GetTimestamp() time.Time {
+ ret := _m.Called()
+
+ var r0 time.Time
+ if rf, ok := ret.Get(0).(func() time.Time); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(time.Time)
+ }
+
+ return r0
+}
+
// HashAtHeight provides a mock function with given fields: blockNum
func (_m *Head[BLOCK_HASH]) HashAtHeight(blockNum int64) BLOCK_HASH {
ret := _m.Called(blockNum)
diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go
index d542e98e6e..f4ad6a65a1 100644
--- a/core/chains/evm/client/simulated_backend_client.go
+++ b/core/chains/evm/client/simulated_backend_client.go
@@ -301,7 +301,7 @@ func (c *SimulatedBackendClient) SubscribeNewHead(
case h := <-ch:
var head *evmtypes.Head
if h != nil {
- head = &evmtypes.Head{Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: utils.NewBig(c.chainId)}
+ head = &evmtypes.Head{Difficulty: (*utils.Big)(h.Difficulty), Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: utils.NewBig(c.chainId)}
lastHead = head
}
select {
diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go
index 6db5d49575..c2d61e0070 100644
--- a/core/chains/evm/types/models.go
+++ b/core/chains/evm/types/models.go
@@ -76,6 +76,10 @@ func (h *Head) GetParent() commontypes.Head[common.Hash] {
return h.Parent
}
+func (h *Head) GetTimestamp() time.Time {
+ return h.Timestamp
+}
+
func (h *Head) BlockDifficulty() *utils.Big {
return h.Difficulty
}
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 3adcc130bc..5f881f354e 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -304,7 +304,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 7f5d0e227d..1d455305a9 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1464,8 +1464,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 h1:ZBsxdB/5iIpl/tWhXe/RHrOwBG7pbKOMeppy5Zt2BVc=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/relay/evm/mercury/v1/data_source.go b/core/services/relay/evm/mercury/v1/data_source.go
index 1b16dc76f9..0f8f56f46e 100644
--- a/core/services/relay/evm/mercury/v1/data_source.go
+++ b/core/services/relay/evm/mercury/v1/data_source.go
@@ -42,8 +42,7 @@ var (
)
)
-// nBlocksObservation controls how many blocks are included in the LatestBlocks observation
-const nBlocksObservation int = 5
+const nBlocksObservation int = relaymercuryv1.MaxAllowedBlocks
type Runner interface {
ExecuteRun(ctx context.Context, spec pipeline.Spec, vars pipeline.Vars, l logger.Logger) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error)
diff --git a/go.mod b/go.mod
index 67896860e0..f35077e923 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
diff --git a/go.sum b/go.sum
index 89e9aee85f..2c9d9e5371 100644
--- a/go.sum
+++ b/go.sum
@@ -1465,8 +1465,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 h1:ZBsxdB/5iIpl/tWhXe/RHrOwBG7pbKOMeppy5Zt2BVc=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index c51bd3c4f6..83657baa01 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -387,7 +387,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 4afa0de1d3..a873f9b7c1 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2369,8 +2369,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264 h1:64bH7MmWzcy5tB16x40266DzgKr2iIVcDPjOro6Q3Us=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231107132621-6de9cc4fb264/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 h1:ZBsxdB/5iIpl/tWhXe/RHrOwBG7pbKOMeppy5Zt2BVc=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/tools/flakeytests/coverage.txt b/tools/flakeytests/coverage.txt
deleted file mode 100644
index 91640016fe..0000000000
--- a/tools/flakeytests/coverage.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-mode: atomic
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:50.103,54.38 4 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:54.38,55.24 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:55.24,62.18 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:62.18,64.5 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:65.4,65.46 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:72.2,73.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:73.16,75.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:77.2,90.16 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:93.63,95.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:95.16,97.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:99.2,101.16 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:101.16,103.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:104.2,110.16 4 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:110.16,112.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:112.8,112.52 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:112.52,114.18 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:114.18,116.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:117.3,117.83 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:119.2,119.12 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:122.81,124.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:124.16,126.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:128.2,128.31 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/reporter.go:131.77,133.2 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:40.79,44.30 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:44.31,44.32 0 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:46.2,52.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:61.75,70.2 8 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:81.45,85.2 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:87.75,89.28 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:89.28,91.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:91.16,93.19 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:93.19,94.13 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:99.4,99.42 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:99.42,100.13 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:103.4,104.18 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:104.18,106.5 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:110.4,110.39 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:110.39,111.13 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:114.4,114.20 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:115.16,116.32 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:116.32,118.6 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:119.5,119.31 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:120.18,121.38 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:121.38,122.33 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:122.33,124.7 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:125.6,125.32 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:130.3,130.33 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:130.33,132.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:134.2,134.19 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:141.106,144.38 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:144.38,146.27 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:146.27,148.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:150.3,151.36 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:151.36,155.18 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:155.18,161.55 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:161.55,162.14 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:164.5,164.32 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:167.4,168.18 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:168.18,170.5 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:172.4,172.25 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:172.25,174.22 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:174.22,175.37 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:175.37,177.7 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:178.6,178.42 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:184.2,184.29 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:187.30,189.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:189.16,191.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:193.2,194.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:194.16,196.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:198.2,198.30 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:198.30,200.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:200.8,202.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/runner.go:204.2,204.43 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:12.74,15.25 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:15.25,17.10 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:17.10,19.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:21.3,21.10 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:24.2,25.9 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:25.9,27.3 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:29.2,29.16 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:32.88,34.16 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:34.16,36.17 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:36.17,38.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:40.3,41.17 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:41.17,43.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:45.3,46.17 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:46.17,48.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:51.2,52.19 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:53.22,56.17 3 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:56.17,58.4 1 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:60.3,61.19 2 0
-github.com/smartcontractkit/chainlink/v2/tools/flakeytests/utils.go:62.10,63.19 1 0
From 012865049d9a88057e25f2b928315ed12897a8b2 Mon Sep 17 00:00:00 2001
From: Andrei Smirnov
Date: Thu, 9 Nov 2023 20:23:30 +0300
Subject: [PATCH 119/327] Functions: ARB+OP cost estimation tweaks (#11102)
* Functions: ARB+OP gas tweaks
* make wrappers-all
* Updated gas snapshot
* Single line comments
* (refactor): rework ChainSpecificUtil usage to be an additional flat fee, rather than gas price
* (test): Add ChainSpecificUtil foundry tests
* Regenerate geth wrappers
* Regenerate gas snapshot
* Amend L1Fee as gas units, not in wei
* Prettier
* Revert "Amend L1Fee as gas units, not in wei"
This reverts commit 75e47cadbe4a7a58fc731bc57b9dfaa7eb8a7898.
* Denote that _getCurrentTxL1GasFees's return is in Wei
* (refactor) rework FunctionsBilling unit conversion helper to be juels from wei
* Changes from review
* Regenerate gas snapshot
---------
Co-authored-by: Justin Kaseman
---
.../gas-snapshots/functions.gas-snapshot | 73 +++---
.../functions/dev/v1_X/ChainSpecificUtil.sol | 78 +++++++
.../functions/dev/v1_X/FunctionsBilling.sol | 34 +--
.../dev/v1_X/FunctionsCoordinator.sol | 9 +-
.../tests/v1_X/ChainSpecificUtil.t.sol | 217 ++++++++++++++++++
.../tests/v1_X/FunctionsCoordinator.t.sol | 1 -
.../src/v0.8/functions/tests/v1_X/Gas.t.sol | 8 -
.../src/v0.8/functions/tests/v1_X/Setup.t.sol | 87 +++++--
.../FunctionsCoordinatorHarness.sol | 5 +-
.../functions_coordinator.go | 2 +-
...rapper-dependency-versions-do-not-edit.txt | 2 +-
11 files changed, 434 insertions(+), 82 deletions(-)
create mode 100644 contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol
create mode 100644 contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index e742be2754..4e891535b7 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,9 +1,18 @@
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14497117)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14497095)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14497111)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14508531)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14508508)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14508480)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14508431)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14508420)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14508464)
FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32458)
-FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 53227)
-FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 53330)
+FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 53807)
+FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 53910)
FunctionsBilling_GetAdminFee:test_GetAdminFee_Success() (gas: 18226)
FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 23671)
FunctionsBilling_GetDONFee:test_GetDONFee_Success() (gas: 15792)
@@ -18,39 +27,39 @@ FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 18974)
FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 38251)
FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8801)
FunctionsClient_Constructor:test_Constructor_Success() (gas: 7573)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 498114)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 199285)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 501740)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 202944)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14623)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22923)
FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55059)
-FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 11984)
+FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 12006)
FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15334)
-FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 106496)
+FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 106506)
FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15313)
-FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 656556)
+FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 656362)
FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20364)
-FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 101275)
+FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 101285)
FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13892)
-FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 651248)
+FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 651054)
FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22703)
-FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 107681)
+FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 108848)
FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 18957)
FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 19690)
FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 246)
FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 223)
FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 225)
FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12007)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 169900)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 160227)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 174021)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 164352)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38115)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35238)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 178373)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 182497)
FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 153924)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 296712)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 310327)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2484946)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 515433)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 158041)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 323262)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 336879)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2512144)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 542628)
FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 17983)
FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12904)
FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37159)
@@ -71,15 +80,15 @@ FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNe
FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23392)
FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (gas: 118479)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59347)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 192799)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 193436)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29426)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57925)
-FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 186299)
+FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 186932)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50947)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25082)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29132)
FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34291)
-FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 285026)
+FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 286243)
FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65843)
FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 36012)
FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29896)
@@ -87,8 +96,8 @@ FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalid
FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27503)
FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35717)
FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40810)
-FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 291595)
-FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 192791)
+FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 292812)
+FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 193424)
FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 30688)
FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13403)
FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13293)
@@ -101,7 +110,7 @@ FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOw
FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 60987)
FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 94677)
FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62693)
-FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 214560)
+FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 215197)
FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 137893)
FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164837)
FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12946)
@@ -113,7 +122,7 @@ FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubs
FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 57885)
FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89272)
FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20148)
-FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 193688)
+FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 194325)
FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 114506)
FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 125832)
FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 74973)
@@ -133,8 +142,8 @@ FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 1501
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43685, ~: 45548)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46197, ~: 48060)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14295, ~: 14295)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51089, ~: 53040)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 86057, ~: 89604)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51000, ~: 53040)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 85879, ~: 89604)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15638)
@@ -146,7 +155,7 @@ FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Reve
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 54867)
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49607)
FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessSubOwnerRefunded() (gas: 50896)
-FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 164303)
+FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 164812)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17924)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 210)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15555)
@@ -155,7 +164,7 @@ FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddres
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 54413)
FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 37790)
FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 14981)
-FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 175857)
+FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 176494)
FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27611)
FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57709)
FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15001)
@@ -171,7 +180,7 @@ FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription
FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 57800)
FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87208)
FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18049)
-FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 191221)
+FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 191858)
FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 41979)
FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12891)
FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15684)
@@ -209,5 +218,5 @@ Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84675)
Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79087)
Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73375)
Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38546)
-Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 964214)
-Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 156934)
\ No newline at end of file
+Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 979631)
+Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 157578)
\ No newline at end of file
diff --git a/contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol b/contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol
new file mode 100644
index 0000000000..f0eec19db2
--- /dev/null
+++ b/contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.19;
+
+import {ArbGasInfo} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
+import {OVM_GasPriceOracle} from "../../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
+
+/// @dev A library that abstracts out opcodes that behave differently across chains.
+/// @dev The methods below return values that are pertinent to the given chain.
+library ChainSpecificUtil {
+ // ------------ Start Arbitrum Constants ------------
+
+ /// @dev ARBGAS_ADDR is the address of the ArbGasInfo precompile on Arbitrum.
+ /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbGasInfo.sol#L10
+ address private constant ARBGAS_ADDR = address(0x000000000000000000000000000000000000006C);
+ ArbGasInfo private constant ARBGAS = ArbGasInfo(ARBGAS_ADDR);
+
+ uint256 private constant ARB_MAINNET_CHAIN_ID = 42161;
+ uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613;
+ uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614;
+
+ // ------------ End Arbitrum Constants ------------
+
+ // ------------ Start Optimism Constants ------------
+ /// @dev L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism
+ bytes internal constant L1_FEE_DATA_PADDING =
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_GasPriceOracle precompile on Optimism.
+ /// @dev reference: https://community.optimism.io/docs/developers/build/transaction-fees/#estimating-the-l1-data-fee
+ address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
+ OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR);
+
+ uint256 private constant OP_MAINNET_CHAIN_ID = 10;
+ uint256 private constant OP_GOERLI_CHAIN_ID = 420;
+ uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420;
+
+ /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism.
+ uint256 private constant BASE_MAINNET_CHAIN_ID = 8453;
+ uint256 private constant BASE_GOERLI_CHAIN_ID = 84531;
+ uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532;
+
+ // ------------ End Optimism Constants ------------
+
+ /// @notice Returns the L1 fees in wei that will be paid for the current transaction, given any calldata
+ /// @notice for the current transaction.
+ /// @notice When on a known Arbitrum chain, it uses ArbGas.getCurrentTxL1GasFees to get the fees.
+ /// @notice On Arbitrum, the provided calldata is not used to calculate the fees.
+ /// @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy
+ /// @notice and getL1Fee is called to get the fees.
+ function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256 l1FeeWei) {
+ uint256 chainid = block.chainid;
+ if (_isArbitrumChainId(chainid)) {
+ return ARBGAS.getCurrentTxL1GasFees();
+ } else if (_isOptimismChainId(chainid)) {
+ return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING));
+ }
+ return 0;
+ }
+
+ /// @notice Return true if and only if the provided chain ID is an Arbitrum chain ID.
+ function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) {
+ return
+ chainId == ARB_MAINNET_CHAIN_ID ||
+ chainId == ARB_GOERLI_TESTNET_CHAIN_ID ||
+ chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID;
+ }
+
+ /// @notice Return true if and only if the provided chain ID is an Optimism (or Base) chain ID.
+ /// @notice Note that optimism chain id's are also OP stack chain id's.
+ function _isOptimismChainId(uint256 chainId) internal pure returns (bool) {
+ return
+ chainId == OP_MAINNET_CHAIN_ID ||
+ chainId == OP_GOERLI_CHAIN_ID ||
+ chainId == OP_SEPOLIA_CHAIN_ID ||
+ chainId == BASE_MAINNET_CHAIN_ID ||
+ chainId == BASE_GOERLI_CHAIN_ID ||
+ chainId == BASE_SEPOLIA_CHAIN_ID;
+ }
+}
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
index adc6218733..bf43ead8d7 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
@@ -10,6 +10,8 @@ import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
+import {ChainSpecificUtil} from "./ChainSpecificUtil.sol";
+
/// @title Functions Billing contract
/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON).
abstract contract FunctionsBilling is Routable, IFunctionsBilling {
@@ -123,10 +125,10 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
return uint256(weiPerUnitLink);
}
- function _getJuelsPerGas(uint256 gasPriceWei) private view returns (uint96) {
- // (1e18 juels/link) * (wei/gas) / (wei/link) = juels per gas
+ function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) {
+ // (1e18 juels/link) * wei / (wei/link) = juels
// There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28)
- return SafeCast.toUint96((1e18 * gasPriceWei) / getWeiPerUnitLink());
+ return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink());
}
// ================================================================
@@ -159,8 +161,6 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
uint72 donFee,
uint72 adminFee
) internal view returns (uint96) {
- uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit;
-
// If gas price is less than the minimum fulfillment gas price, override to using the minimum
if (gasPriceWei < s_config.minimumEstimateGasPriceWei) {
gasPriceWei = s_config.minimumEstimateGasPriceWei;
@@ -170,11 +170,13 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
((gasPriceWei * s_config.fulfillmentGasPriceOverEstimationBP) / 10_000);
/// @NOTE: Basis Points are 1/100th of 1%, divide by 10_000 to bring back to original units
- uint96 juelsPerGas = _getJuelsPerGas(gasPriceWithOverestimation);
- uint256 estimatedGasReimbursement = juelsPerGas * executionGas;
- uint96 fees = uint96(donFee) + uint96(adminFee);
+ uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit;
+ uint256 l1FeeWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data);
+ uint96 estimatedGasReimbursementJuels = _getJuelsFromWei((gasPriceWithOverestimation * executionGas) + l1FeeWei);
+
+ uint96 feesJuels = uint96(donFee) + uint96(adminFee);
- return SafeCast.toUint96(estimatedGasReimbursement + fees);
+ return estimatedGasReimbursementJuels + feesJuels;
}
// ================================================================
@@ -248,6 +250,7 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
/// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment
/// @param response response data from DON consensus
/// @param err error from DON consensus
+ /// @param reportBatchSize the number of fulfillments in the transmitter's report
/// @return result fulfillment result
/// @dev Only callable by a node that has been approved on the Coordinator
/// @dev simulated offchain to determine if sufficient balance is present to fulfill the request
@@ -256,21 +259,22 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
bytes memory response,
bytes memory err,
bytes memory onchainMetadata,
- bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */
+ bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */,
+ uint8 reportBatchSize
) internal returns (FunctionsResponse.FulfillResult) {
FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment));
- uint96 juelsPerGas = _getJuelsPerGas(tx.gasprice);
+ uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice;
+ uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize;
// Gas overhead without callback
- uint96 gasOverheadJuels = juelsPerGas *
- (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback);
+ uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei);
// The Functions Router will perform the callback to the client contract
(FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill(
response,
err,
- juelsPerGas,
- gasOverheadJuels + commitment.donFee, // costWithoutFulfillment
+ _getJuelsFromWei(tx.gasprice), // Juels Per Gas conversion rate
+ gasOverheadJuels + commitment.donFee, // cost without callback or admin fee, those will be added by the Router
msg.sender,
commitment
);
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
index eb0d954ae0..2caab41c74 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
@@ -156,7 +156,14 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
// Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig
for (uint256 i = 0; i < requestIds.length; ++i) {
FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult(
- _fulfillAndBill(requestIds[i], results[i], errors[i], onchainMetadata[i], offchainMetadata[i])
+ _fulfillAndBill(
+ requestIds[i],
+ results[i],
+ errors[i],
+ onchainMetadata[i],
+ offchainMetadata[i],
+ uint8(requestIds.length) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig
+ )
);
// Emit on successfully processing the fulfillment
diff --git a/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol b/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol
new file mode 100644
index 0000000000..5384a66d91
--- /dev/null
+++ b/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.19;
+
+import {BaseTest} from "./BaseTest.t.sol";
+import {FunctionsClient} from "../../dev/v1_X/FunctionsClient.sol";
+import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol";
+import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol";
+import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol";
+import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol";
+
+import {FunctionsFulfillmentSetup} from "./Setup.t.sol";
+
+import {ArbGasInfo} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
+import {OVM_GasPriceOracle} from "../../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
+
+/// @notice #_getCurrentTxL1GasFees Arbitrum
+/// @dev Arbitrum gas formula = L2 Gas Price * (Gas used on L2 + Extra Buffer for L1 cost)
+/// @dev where Extra Buffer for L1 cost = (L1 Estimated Cost / L2 Gas Price)
+contract ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum is FunctionsFulfillmentSetup {
+ address private constant ARBGAS_ADDR = address(0x000000000000000000000000000000000000006C);
+ uint256 private constant L1_FEE_WEI = 15_818_209_764_247;
+
+ uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE));
+
+ function setUp() public virtual override {
+ vm.mockCall(ARBGAS_ADDR, abi.encodeWithSelector(ArbGasInfo.getCurrentTxL1GasFees.selector), abi.encode(L1_FEE_WEI));
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() public {
+ // Set the chainID
+ vm.chainId(42161);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() public {
+ // Set the chainID
+ vm.chainId(421613);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() public {
+ // Set the chainID
+ vm.chainId(421614);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+}
+
+/// @notice #_getCurrentTxL1GasFees Optimism
+/// @dev Optimism gas formula = ((l2_base_fee + l2_priority_fee) * l2_gas_used) + L1 data fee
+/// @dev where L1 data fee = l1_gas_price * ((count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16) + fixed_overhead + noncalldata_gas) * dynamic_overhead
+contract ChainSpecificUtil__getCurrentTxL1GasFees_Optimism is FunctionsFulfillmentSetup {
+ address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
+ uint256 private constant L1_FEE_WEI = 15_818_209_764_247;
+
+ uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE));
+
+ function setUp() public virtual override {
+ vm.mockCall(
+ OVM_GASPRICEORACLE_ADDR,
+ abi.encodeWithSelector(OVM_GasPriceOracle.getL1Fee.selector),
+ abi.encode(L1_FEE_WEI)
+ );
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() public {
+ // Set the chainID
+ vm.chainId(10);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() public {
+ // Set the chainID
+ vm.chainId(420);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() public {
+ // Set the chainID
+ vm.chainId(11155420);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+}
+
+/// @notice #_getCurrentTxL1GasFees Base
+/// @dev Base gas formula uses Optimism formula = ((l2_base_fee + l2_priority_fee) * l2_gas_used) + L1 data fee
+/// @dev where L1 data fee = l1_gas_price * ((count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16) + fixed_overhead + noncalldata_gas) * dynamic_overhead
+contract ChainSpecificUtil__getCurrentTxL1GasFees_Base is FunctionsFulfillmentSetup {
+ address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
+ uint256 private constant L1_FEE_WEI = 15_818_209_764_247;
+
+ uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE));
+
+ function setUp() public virtual override {
+ vm.mockCall(
+ OVM_GASPRICEORACLE_ADDR,
+ abi.encodeWithSelector(OVM_GasPriceOracle.getL1Fee.selector),
+ abi.encode(L1_FEE_WEI)
+ );
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() public {
+ // Set the chainID
+ vm.chainId(8453);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() public {
+ // Set the chainID
+ vm.chainId(84531);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+
+ function test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() public {
+ // Set the chainID
+ vm.chainId(84532);
+
+ // Setup sends and fulfills request #1
+ FunctionsFulfillmentSetup.setUp();
+
+ // Check request cost estimate
+ uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) +
+ l1FeeJuels;
+ assertEq(s_requests[1].commitment.estimatedTotalCostJuels, expectedEstimatedTotalCostJuels);
+
+ // Check response actual cost
+ uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels;
+ assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels);
+ }
+}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol
index 7166add19f..f6d3d41e63 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol
@@ -10,7 +10,6 @@ import {Routable} from "../../dev/v1_X/Routable.sol";
import {BaseTest} from "./BaseTest.t.sol";
import {FunctionsRouterSetup, FunctionsDONSetup, FunctionsSubscriptionSetup} from "./Setup.t.sol";
-import "forge-std/console.sol";
/// @notice #constructor
contract FunctionsCoordinator_Constructor is FunctionsRouterSetup {
diff --git a/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol b/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol
index 55ab3810b4..f2d7af54e4 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol
@@ -154,14 +154,6 @@ contract Gas_SendRequest is FunctionsSubscriptionSetup {
/// @notice #fulfillRequest
contract FunctionsClient_FulfillRequest is FunctionsClientRequestSetup {
- struct Report {
- bytes32[] rs;
- bytes32[] ss;
- bytes32 vs;
- bytes report;
- bytes32[3] reportContext;
- }
-
mapping(uint256 reportNumber => Report) s_reports;
FunctionsClientTestHelper s_functionsClientWithMaximumReturnData;
diff --git a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
index 0c08fd20cd..97418958bc 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
@@ -225,6 +225,14 @@ contract FunctionsSubscriptionSetup is FunctionsClientSetup {
/// @notice Set up to initate a minimal request and store it in s_requests[1]
contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
+ struct Report {
+ bytes32[] rs;
+ bytes32[] ss;
+ bytes32 vs;
+ bytes report;
+ bytes32[3] reportContext;
+ }
+
struct RequestData {
string sourceCode;
bytes secrets;
@@ -240,6 +248,12 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
mapping(uint256 requestNumber => Request) s_requests;
+ struct Response {
+ uint96 totalCostJuels;
+ }
+
+ mapping(uint256 requestNumber => Response) s_responses;
+
uint96 s_fulfillmentRouterOwnerBalance = 0;
uint96 s_fulfillmentCoordinatorBalance = 0;
@@ -255,7 +269,24 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
_sendAndStoreRequest(1, sourceCode, secrets, args, bytesArgs, callbackGasLimit);
}
- function _getExpectedCost(uint256 gasUsed) internal view returns (uint96 totalCostJuels) {
+ /// @notice Predicts the estimated cost (maximum cost) of a request
+ /// @dev Meant only for Ethereum, does not add L2 chains' L1 fee
+ function _getExpectedCostEstimate(uint256 callbackGas) internal view returns (uint96) {
+ uint256 gasPrice = TX_GASPRICE_START < getCoordinatorConfig().minimumEstimateGasPriceWei
+ ? getCoordinatorConfig().minimumEstimateGasPriceWei
+ : TX_GASPRICE_START;
+ uint256 gasPriceWithOverestimation = gasPrice +
+ ((gasPrice * getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP) / 10_000);
+ uint96 juelsPerGas = uint96((1e18 * gasPriceWithOverestimation) / uint256(LINK_ETH_RATE));
+ uint96 gasOverheadJuels = juelsPerGas *
+ ((getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback));
+ uint96 callbackGasCostJuels = uint96(juelsPerGas * callbackGas);
+ return gasOverheadJuels + s_donFee + s_adminFee + callbackGasCostJuels;
+ }
+
+ /// @notice Predicts the actual cost of a request
+ /// @dev Meant only for Ethereum, does not add L2 chains' L1 fee
+ function _getExpectedCost(uint256 gasUsed) internal view returns (uint96) {
uint96 juelsPerGas = uint96((1e18 * TX_GASPRICE_START) / uint256(LINK_ETH_RATE));
uint96 gasOverheadJuels = juelsPerGas *
(getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback);
@@ -400,7 +431,7 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
bytes memory report,
bytes32[3] memory reportContext,
uint256[] memory signerPrivateKeys
- ) internal pure returns (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) {
+ ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) {
bytes32[] memory rs = new bytes32[](signerPrivateKeys.length);
bytes32[] memory ss = new bytes32[](signerPrivateKeys.length);
bytes memory vs = new bytes(signerPrivateKeys.length);
@@ -417,13 +448,35 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
return (rs, ss, bytes32(vs));
}
+ function _buildAndSignReport(
+ uint256[] memory requestNumberKeys,
+ string[] memory results,
+ bytes[] memory errors
+ ) internal view returns (Report memory) {
+ (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors);
+
+ // Sign the report
+ // Need at least 3 signers to fulfill minimum number of: (configInfo.n + configInfo.f) / 2 + 1
+ uint256[] memory signerPrivateKeys = new uint256[](3);
+ signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1;
+ signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2;
+ signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3;
+ (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport(
+ report,
+ reportContext,
+ signerPrivateKeys
+ );
+
+ return Report({report: report, reportContext: reportContext, rs: rawRs, ss: rawSs, vs: rawVs});
+ }
+
/// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin
/// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report
/// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled.
/// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled.
/// @param transmitter - The address that will send the `.report` transaction
/// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log.
- /// @param requestProcessedIndex - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback)
+ /// @param requestProcessedStartIndex - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback)
/// @param transmitterGasToUse - Override the default amount of gas that the transmitter sends the `.report` transaction with
function _reportAndStore(
uint256[] memory requestNumberKeys,
@@ -431,7 +484,7 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
bytes[] memory errors,
address transmitter,
bool expectedToSucceed,
- uint8 requestProcessedIndex,
+ uint8 requestProcessedStartIndex,
uint256 transmitterGasToUse
) internal {
{
@@ -440,19 +493,7 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
}
}
- (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors);
-
- // Sign the report
- // Need at least 3 signers to fulfill minimum number of: (configInfo.n + configInfo.f) / 2 + 1
- uint256[] memory signerPrivateKeys = new uint256[](3);
- signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1;
- signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2;
- signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3;
- (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport(
- report,
- reportContext,
- signerPrivateKeys
- );
+ Report memory r = _buildAndSignReport(requestNumberKeys, results, errors);
// Send as transmitter
vm.stopPrank();
@@ -461,20 +502,24 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
// Send report
vm.recordLogs();
if (transmitterGasToUse > 0) {
- s_functionsCoordinator.transmit{gas: transmitterGasToUse}(reportContext, report, rawRs, rawSs, rawVs);
+ s_functionsCoordinator.transmit{gas: transmitterGasToUse}(r.reportContext, r.report, r.rs, r.ss, r.vs);
} else {
- s_functionsCoordinator.transmit(reportContext, report, rawRs, rawSs, rawVs);
+ s_functionsCoordinator.transmit(r.reportContext, r.report, r.rs, r.ss, r.vs);
}
if (expectedToSucceed) {
// Get actual cost from RequestProcessed event log
(uint96 totalCostJuels, , , , , ) = abi.decode(
- vm.getRecordedLogs()[requestProcessedIndex].data,
+ vm.getRecordedLogs()[requestProcessedStartIndex].data,
(uint96, address, FunctionsResponse.FulfillResult, bytes, bytes, bytes)
);
+ // Store response of first request
+ // TODO: handle multiple requests
+ s_responses[requestNumberKeys[0]] = Response({totalCostJuels: totalCostJuels});
// Store profit amounts
- s_fulfillmentRouterOwnerBalance += s_adminFee;
+ s_fulfillmentRouterOwnerBalance += s_adminFee * uint96(requestNumberKeys.length);
// totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels
+ // TODO: handle multiple requests
s_fulfillmentCoordinatorBalance += totalCostJuels - s_adminFee;
}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol
index bc103fc356..c1b6d5d0b1 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol
@@ -79,9 +79,10 @@ contract FunctionsCoordinatorHarness is FunctionsCoordinator {
bytes memory response,
bytes memory err,
bytes memory onchainMetadata,
- bytes memory offchainMetadata
+ bytes memory offchainMetadata,
+ uint8 reportBatchSize
) external returns (FunctionsResponse.FulfillResult) {
- return super._fulfillAndBill(requestId, response, err, onchainMetadata, offchainMetadata);
+ return super._fulfillAndBill(requestId, response, err, onchainMetadata, offchainMetadata, reportBatchSize);
}
function disperseFeePool_HARNESS() external {
diff --git a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
index ffe072fc65..b2e5ec4b09 100644
--- a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
+++ b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
@@ -72,7 +72,7 @@ type FunctionsResponseRequestMeta struct {
var FunctionsCoordinatorMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x60c06040523480156200001157600080fd5b506040516200529938038062005299833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614c166200068360003960008181610845015281816109d301528181610ca601528181610f3a0152818161104501528181611830015261332c0152600061126e0152614c166000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a036600461361f565b61059c565b005b6101a56101b53660046137c8565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b60405161020391906138e2565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c36600461398a565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613a19565b6108d7565b6101a5610a90565b6101a5610b92565b6101a561029336600461361f565b610d92565b6102a0610de2565b6040516102039190613aa3565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613ab6565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613acf565b610fd4565b6040516102039190613c24565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613c78565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b6040516102039190613d2f565b61053b610536366004613e1f565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004613f38565b6119e3565b61057b61240f565b604051908152602001610203565b6101a5610597366004614005565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec8284836140bb565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f518486290610836908390613d2f565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d291906141e1565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff1661422d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd2614252565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c31614252565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf5614252565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d8781614281565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec8284836140bb565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e6090614022565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea890614022565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed490614022565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a8836142b9565b6128b2565b90506110bf6060830160408401614005565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a088016143a6565b61111f61016088016101408901614005565b61112988806143c3565b61113b6101208b016101008c01614428565b60208b01356111516101008d0160e08e01614443565b8b60405161116799989796959493929190614460565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d50565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a89190614508565b6112b29190614550565b6112bd906001614508565b60ff1690506112dd565b60208201516112d7906001614508565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f2614572565b600281111561140357611403614572565b905250905060028160200151600281111561142057611420614572565b14801561146757506006816000015160ff168154811061144257611442614252565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da6135b7565b6000808a8a6040516114ed9291906145a1565b604051908190038120611504918e906020016145b1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d614252565b61157a91901a601b614508565b8e8e8681811061158c5761158c614252565b905060200201358d8d878181106115a5576115a5614252565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561168457611684614572565b600281111561169557611695614572565b90525092506001836020015160028111156116b2576116b2614572565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061173357611733614252565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf614252565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa600186614508565b9450508061180790614281565b905061154e565b50505061181f833383858e8e612e07565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd5565b98975050505050505050565b6060600c805461199b90614022565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea890614022565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b598160036145c5565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c10908861311d565b60055415611dc557600554600090611c2a906001906145dc565b9050600060058281548110611c4157611c41614252565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b614252565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb6145ef565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d646145ef565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee614252565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e38614572565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed0614252565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f71614572565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b614252565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe5614572565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f614252565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561212057612120614572565b02179055505082518051600592508390811061213e5761213e614252565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba614252565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061222481614281565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e49184917401000000000000000000000000000000000000000090041661461e565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a00151613136565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff1696909591949193919261463b565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c191906146eb565b5093505092505080426125d491906145dc565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b612679816131e1565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b90508051600003612768576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600b54600091612787916bffffffffffffffffffffffff1661473b565b905060005b82518110156128535781600a60008584815181106127ac576127ac614252565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128149190614766565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284c90614281565b905061278c565b508151612860908261478b565b600b80546000906128809084906bffffffffffffffffffffffff1661422d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6d576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aaa8560e001513a848860800151612fd5565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b06576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b1f91906147b3565b905060003087604001518860a001518960c001516001612b3f91906147c6565b8a5180516020918201206101008d015160e08e0151604051612bf398979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d029190613c24565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5d8260206145c5565b612d688560206145c5565b612d74886101446147b3565b612d7e91906147b3565b612d8891906147b3565b612d939060006147b3565b9050368114612dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e19868801886148c2565b8451949950929750909550935091501580612e3657508351855114155b80612e4357508251855114155b80612e5057508151855114155b80612e5d57508051855114155b15612e94576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8551811015612fc7576000612f2c878381518110612eb757612eb7614252565b6020026020010151878481518110612ed157612ed1614252565b6020026020010151878581518110612eeb57612eeb614252565b6020026020010151878681518110612f0557612f05614252565b6020026020010151878781518110612f1f57612f1f614252565b60200260200101516132d6565b90506000816006811115612f4257612f42614572565b1480612f5f57506001816006811115612f5d57612f5d614572565b145b15612fb657868281518110612f7657612f76614252565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc081614281565b9050612e97565b505050505050505050505050565b6008546000908190869061300d9063ffffffff6c0100000000000000000000000082048116916801000000000000000090041661461e565b613017919061461e565b60085463ffffffff919091169150790100000000000000000000000000000000000000000000000000900464ffffffffff1685101561307a57600854790100000000000000000000000000000000000000000000000000900464ffffffffff1694505b600854600090612710906130949063ffffffff16886145c5565b61309e9190614994565b6130a890876147b3565b905060006130b5826134e6565b905060006130d1846bffffffffffffffffffffffff84166145c5565b905060006130ed68ffffffffffffffffff808916908a16614766565b905061310f61310a6bffffffffffffffffffffffff8316846147b3565b613515565b9a9950505050505050505050565b6000613127610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161315a999897969594939291906149a8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080838060200190518101906132ed9190614a74565b905060006132fa3a6134e6565b905060008261012001518361010001516133149190614b3c565b6133259064ffffffffff168361478b565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298b8b878960e0015168ffffffffffffffffff16886133849190614766565b338b6040518763ffffffff1660e01b81526004016133a796959493929190614b5a565b60408051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190614bd6565b9092509050600082600681111561340257613402614572565b148061341f5750600182600681111561341d5761341d614572565b145b156134d85760008b81526007602052604081205561343d8184614766565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0870151600b805468ffffffffffffffffff909216939092916134a991859116614766565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b509998505050505050505050565b600061350f6134f361240f565b61350584670de0b6b3a76400006145c5565b61310a9190614994565b92915050565b60006bffffffffffffffffffffffff8211156135b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f8401126135e857600080fd5b50813567ffffffffffffffff81111561360057600080fd5b60208301915083602082850101111561361857600080fd5b9250929050565b6000806020838503121561363257600080fd5b823567ffffffffffffffff81111561364957600080fd5b613655858286016135d6565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156136b4576136b4613661565b60405290565b604051610160810167ffffffffffffffff811182821017156136b4576136b4613661565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561372557613725613661565b604052919050565b63ffffffff8116811461267957600080fd5b80356111708161372d565b68ffffffffffffffffff8116811461267957600080fd5b80356111708161374a565b64ffffffffff8116811461267957600080fd5b80356111708161376c565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b600061012082840312156137db57600080fd5b6137e3613690565b6137ec8361373f565b81526137fa6020840161373f565b602082015261380b6040840161373f565b604082015261381c6060840161373f565b606082015261382d60808401613761565b608082015261383e60a0840161377f565b60a082015261384f60c0840161378a565b60c082015261386060e0840161379c565b60e082015261010061387381850161373f565b908201529392505050565b6000815180845260005b818110156138a457602081850181015186830182015201613888565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006138f5602083018461387e565b9392505050565b600082601f83011261390d57600080fd5b813567ffffffffffffffff81111561392757613927613661565b61395860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016136de565b81815284602083860101111561396d57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561399c57600080fd5b813567ffffffffffffffff8111156139b357600080fd5b6139bf848285016138fc565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b8035611170816139c7565b6bffffffffffffffffffffffff8116811461267957600080fd5b8035611170816139f4565b60008060408385031215613a2c57600080fd5b8235613a37816139c7565b91506020830135613a47816139f4565b809150509250929050565b600081518084526020808501945080840160005b83811015613a9857815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613a66565b509495945050505050565b6020815260006138f56020830184613a52565b600060208284031215613ac857600080fd5b5035919050565b600060208284031215613ae157600080fd5b813567ffffffffffffffff811115613af857600080fd5b820161016081850312156138f557600080fd5b805182526020810151613b36602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613b5660408401826bffffffffffffffffffffffff169052565b506060810151613b7e606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613b9a608084018267ffffffffffffffff169052565b5060a0810151613bb260a084018263ffffffff169052565b5060c0810151613bcf60c084018268ffffffffffffffffff169052565b5060e0810151613bec60e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b610160810161350f8284613b0b565b60008083601f840112613c4557600080fd5b50813567ffffffffffffffff811115613c5d57600080fd5b6020830191508360208260051b850101111561361857600080fd5b60008060008060008060008060e0898b031215613c9457600080fd5b606089018a811115613ca557600080fd5b8998503567ffffffffffffffff80821115613cbf57600080fd5b613ccb8c838d016135d6565b909950975060808b0135915080821115613ce457600080fd5b613cf08c838d01613c33565b909750955060a08b0135915080821115613d0957600080fd5b50613d168b828c01613c33565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151613d83608084018268ffffffffffffffffff169052565b5060a0830151613d9c60a084018264ffffffffff169052565b5060c0830151613db260c084018261ffff169052565b5060e0830151613de260e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b803561117081613dfe565b600080600080600060808688031215613e3757600080fd5b8535613e4281613dfe565b9450602086013567ffffffffffffffff811115613e5e57600080fd5b613e6a888289016135d6565b9095509350506040860135613e7e8161372d565b949793965091946060013592915050565b600067ffffffffffffffff821115613ea957613ea9613661565b5060051b60200190565b600082601f830112613ec457600080fd5b81356020613ed9613ed483613e8f565b6136de565b82815260059290921b84018101918181019086841115613ef857600080fd5b8286015b84811015613f1c578035613f0f816139c7565b8352918301918301613efc565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c08789031215613f5157600080fd5b863567ffffffffffffffff80821115613f6957600080fd5b613f758a838b01613eb3565b97506020890135915080821115613f8b57600080fd5b613f978a838b01613eb3565b9650613fa560408a01613f27565b95506060890135915080821115613fbb57600080fd5b613fc78a838b016138fc565b9450613fd560808a01613e14565b935060a0890135915080821115613feb57600080fd5b50613ff889828a016138fc565b9150509295509295509295565b60006020828403121561401757600080fd5b81356138f5816139c7565b600181811c9082168061403657607f821691505b60208210810361406f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c8101602086101561409c5750805b601f850160051c820191505b81811015610a88578281556001016140a8565b67ffffffffffffffff8311156140d3576140d3613661565b6140e7836140e18354614022565b83614075565b6000601f84116001811461413957600085156141035750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556141cf565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156141885786850135825560209485019460019092019101614168565b50868210156141c3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b80516111708161374a565b6000602082840312156141f357600080fd5b81516138f58161374a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115612661576126616141fe565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036142b2576142b26141fe565b5060010190565b600061016082360312156142cc57600080fd5b6142d46136ba565b823567ffffffffffffffff8111156142eb57600080fd5b6142f7368286016138fc565b82525060208301356020820152614310604084016139e9565b604082015261432160608401613a0e565b606082015261433260808401613761565b608082015261434360a08401613e14565b60a082015261435460c08401613e14565b60c082015261436560e0840161373f565b60e082015261010061437881850161378a565b9082015261012061438a848201613e14565b9082015261014061439c8482016139e9565b9082015292915050565b6000602082840312156143b857600080fd5b81356138f581613dfe565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126143f857600080fd5b83018035915067ffffffffffffffff82111561441357600080fd5b60200191503681900382131561361857600080fd5b60006020828403121561443a57600080fd5b6138f58261378a565b60006020828403121561445557600080fd5b81356138f58161372d565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061310f60e0830184613b0b565b60ff818116838216019081111561350f5761350f6141fe565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061456357614563614521565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b808202811582820484141761350f5761350f6141fe565b8181038181111561350f5761350f6141fe565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115612661576126616141fe565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261466b8184018a613a52565b9050828103608084015261467f8189613a52565b905060ff871660a084015282810360c084015261469c818761387e565b905067ffffffffffffffff851660e08401528281036101008401526146c1818561387e565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a0868803121561470357600080fd5b61470c866146d1565b945060208601519350604086015192506060860151915061472f608087016146d1565b90509295509295909350565b60006bffffffffffffffffffffffff8084168061475a5761475a614521565b92169190910492915050565b6bffffffffffffffffffffffff818116838216019080821115612661576126616141fe565b6bffffffffffffffffffffffff818116838216028082169190828114613df657613df66141fe565b8082018082111561350f5761350f6141fe565b67ffffffffffffffff818116838216019080821115612661576126616141fe565b600082601f8301126147f857600080fd5b81356020614808613ed483613e8f565b82815260059290921b8401810191818101908684111561482757600080fd5b8286015b84811015613f1c578035835291830191830161482b565b600082601f83011261485357600080fd5b81356020614863613ed483613e8f565b82815260059290921b8401810191818101908684111561488257600080fd5b8286015b84811015613f1c57803567ffffffffffffffff8111156148a65760008081fd5b6148b48986838b01016138fc565b845250918301918301614886565b600080600080600060a086880312156148da57600080fd5b853567ffffffffffffffff808211156148f257600080fd5b6148fe89838a016147e7565b9650602088013591508082111561491457600080fd5b61492089838a01614842565b9550604088013591508082111561493657600080fd5b61494289838a01614842565b9450606088013591508082111561495857600080fd5b61496489838a01614842565b9350608088013591508082111561497a57600080fd5b5061498788828901614842565b9150509295509295909350565b6000826149a3576149a3614521565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526149ef8285018b613a52565b91508382036080850152614a03828a613a52565b915060ff881660a085015283820360c0850152614a20828861387e565b90861660e085015283810361010085015290506146c1818561387e565b8051611170816139c7565b8051611170816139f4565b805161117081613dfe565b80516111708161372d565b80516111708161376c565b60006101608284031215614a8757600080fd5b614a8f6136ba565b82518152614a9f60208401614a3d565b6020820152614ab060408401614a48565b6040820152614ac160608401614a3d565b6060820152614ad260808401614a53565b6080820152614ae360a08401614a5e565b60a0820152614af460c084016141d6565b60c0820152614b0560e084016141d6565b60e0820152610100614b18818501614a69565b90820152610120614b2a848201614a69565b90820152610140613873848201614a5e565b64ffffffffff818116838216019080821115612661576126616141fe565b6000610200808352614b6e8184018a61387e565b90508281036020840152614b82818961387e565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614bcb905060a0830184613b0b565b979650505050505050565b60008060408385031215614be957600080fd5b825160078110614bf857600080fd5b6020840151909250613a47816139f456fea164736f6c6343000813000a",
+ Bin: "0x60c06040523480156200001157600080fd5b506040516200556438038062005564833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614ee16200068360003960008181610845015281816109d301528181610ca601528181610f3a015281816110450152818161183001526133aa0152600061126e0152614ee16000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a0366004613857565b61059c565b005b6101a56101b5366004613a00565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613b24565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613bc5565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613c54565b6108d7565b6101a5610a90565b6101a5610b92565b6101a5610293366004613857565b610d92565b6102a0610de2565b6040516102039190613cde565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613cf1565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613d0a565b610fd4565b6040516102039190613e5f565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613eb3565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b6040516102039190613f6a565b61053b61053636600461405a565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004614173565b6119e3565b61057b61240f565b604051908152602001610203565b6101a5610597366004614240565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec8284836142f6565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f518486290610836908390613f6a565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d2919061441c565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff16614468565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd261448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c3161448d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf561448d565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d87816144bc565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec8284836142f6565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e609061425d565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea89061425d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed49061425d565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a8836144f4565b6128b2565b90506110bf6060830160408401614240565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a088016145e1565b61111f61016088016101408901614240565b61112988806145fe565b61113b6101208b016101008c01614663565b60208b01356111516101008d0160e08e0161467e565b8b6040516111679998979695949392919061469b565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d50565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a89190614743565b6112b2919061478b565b6112bd906001614743565b60ff1690506112dd565b60208201516112d7906001614743565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f26147ad565b6002811115611403576114036147ad565b9052509050600281602001516002811115611420576114206147ad565b14801561146757506006816000015160ff16815481106114425761144261448d565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da6137ef565b6000808a8a6040516114ed9291906147dc565b604051908190038120611504918e906020016147ec565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d61448d565b61157a91901a601b614743565b8e8e8681811061158c5761158c61448d565b905060200201358d8d878181106115a5576115a561448d565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff80821685529296509294508401916101009004166002811115611684576116846147ad565b6002811115611695576116956147ad565b90525092506001836020015160028111156116b2576116b26147ad565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f81106117335761173361448d565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf61448d565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa600186614743565b94505080611807906144bc565b905061154e565b50505061181f833383858e8e612e07565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd7565b98975050505050505050565b6060600c805461199b9061425d565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea89061425d565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b59816003614800565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c109088613144565b60055415611dc557600554600090611c2a90600190614817565b9050600060058281548110611c4157611c4161448d565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b61448d565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb61482a565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d6461482a565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee61448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e386147ad565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed061448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f716147ad565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b61448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe56147ad565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f61448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115612120576121206147ad565b02179055505082518051600592508390811061213e5761213e61448d565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba61448d565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905580612224816144bc565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e491849174010000000000000000000000000000000000000000900416614859565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a0015161315d565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff16969095919491939192614876565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c19190614926565b5093505092505080426125d49190614817565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b61267981613208565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b90508051600003612768576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600b54600091612787916bffffffffffffffffffffffff16614976565b905060005b82518110156128535781600a60008584815181106127ac576127ac61448d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff1661281491906149a1565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284c906144bc565b905061278c565b50815161286090826149c6565b600b80546000906128809084906bffffffffffffffffffffffff16614468565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6d576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aaa8560e001513a848860800151612fd7565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b06576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b1f91906149ee565b905060003087604001518860a001518960c001516001612b3f9190614a01565b8a5180516020918201206101008d015160e08e0151604051612bf398979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d029190613e5f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5d826020614800565b612d68856020614800565b612d74886101446149ee565b612d7e91906149ee565b612d8891906149ee565b612d939060006149ee565b9050368114612dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e1986880188614afd565b8451949950929750909550935091501580612e3657508351855114155b80612e4357508251855114155b80612e5057508151855114155b80612e5d57508051855114155b15612e94576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8551811015612fc9576000612f2e878381518110612eb757612eb761448d565b6020026020010151878481518110612ed157612ed161448d565b6020026020010151878581518110612eeb57612eeb61448d565b6020026020010151878681518110612f0557612f0561448d565b6020026020010151878781518110612f1f57612f1f61448d565b60200260200101518c516132fd565b90506000816006811115612f4457612f446147ad565b1480612f6157506001816006811115612f5f57612f5f6147ad565b145b15612fb857868281518110612f7857612f7861448d565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc2816144bc565b9050612e97565b505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561303257600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b6008546000906127109061304c9063ffffffff1687614800565b6130569190614bcf565b61306090866149ee565b60085490915060009087906130999063ffffffff6c01000000000000000000000000820481169168010000000000000000900416614859565b6130a39190614859565b63ffffffff16905060006130ed6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356d92505050565b9050600061310e826130ff8587614800565b61310991906149ee565b6136af565b9050600061312a68ffffffffffffffffff808916908a166149a1565b905061313681836149a1565b9a9950505050505050505050565b600061314e610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161318199989796959493929190614be3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133149190614caf565b905060003a82610120015183610100015161332f9190614d77565b64ffffffffff166133409190614800565b905060008460ff166133886000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356d92505050565b6133929190614bcf565b905060006133a361310983856149ee565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298d8d6133ef3a6136af565b60e08b01516134099068ffffffffffffffffff16896149a1565b338c6040518763ffffffff1660e01b815260040161342c96959493929190614d95565b60408051808303816000875af115801561344a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061346e9190614e11565b90925090506000826006811115613487576134876147ad565b14806134a4575060018260068111156134a2576134a26147ad565b145b1561355d5760008d8152600760205260408120556134c281846149a1565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0880151600b805468ffffffffffffffffff9092169390929161352e918591166149a1565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b509b9a5050505050505050505050565b600046613579816136e3565b156135f557606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ee9190614e44565b9392505050565b6135fe81613706565b156136a65773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e84604051806080016040528060488152602001614e8d6048913960405160200161365e929190614e5d565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016136899190613b24565b602060405180830381865afa1580156135ca573d6000803e3d6000fd5b50600092915050565b60006136dd6136bc61240f565b6136ce84670de0b6b3a7640000614800565b6136d89190614bcf565b61374d565b92915050565b600061a4b18214806136f7575062066eed82145b806136dd57505062066eee1490565b6000600a82148061371857506101a482145b80613725575062aa37dc82145b80613731575061210582145b8061373e575062014a3382145b806136dd57505062014a341490565b60006bffffffffffffffffffffffff8211156137eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f84011261382057600080fd5b50813567ffffffffffffffff81111561383857600080fd5b60208301915083602082850101111561385057600080fd5b9250929050565b6000806020838503121561386a57600080fd5b823567ffffffffffffffff81111561388157600080fd5b61388d8582860161380e565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156138ec576138ec613899565b60405290565b604051610160810167ffffffffffffffff811182821017156138ec576138ec613899565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561395d5761395d613899565b604052919050565b63ffffffff8116811461267957600080fd5b803561117081613965565b68ffffffffffffffffff8116811461267957600080fd5b803561117081613982565b64ffffffffff8116811461267957600080fd5b8035611170816139a4565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613a1357600080fd5b613a1b6138c8565b613a2483613977565b8152613a3260208401613977565b6020820152613a4360408401613977565b6040820152613a5460608401613977565b6060820152613a6560808401613999565b6080820152613a7660a084016139b7565b60a0820152613a8760c084016139c2565b60c0820152613a9860e084016139d4565b60e0820152610100613aab818501613977565b908201529392505050565b60005b83811015613ad1578181015183820152602001613ab9565b50506000910152565b60008151808452613af2816020860160208601613ab6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006135ee6020830184613ada565b600082601f830112613b4857600080fd5b813567ffffffffffffffff811115613b6257613b62613899565b613b9360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613916565b818152846020838601011115613ba857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613bd757600080fd5b813567ffffffffffffffff811115613bee57600080fd5b613bfa84828501613b37565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b803561117081613c02565b6bffffffffffffffffffffffff8116811461267957600080fd5b803561117081613c2f565b60008060408385031215613c6757600080fd5b8235613c7281613c02565b91506020830135613c8281613c2f565b809150509250929050565b600081518084526020808501945080840160005b83811015613cd357815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613ca1565b509495945050505050565b6020815260006135ee6020830184613c8d565b600060208284031215613d0357600080fd5b5035919050565b600060208284031215613d1c57600080fd5b813567ffffffffffffffff811115613d3357600080fd5b820161016081850312156135ee57600080fd5b805182526020810151613d71602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613d9160408401826bffffffffffffffffffffffff169052565b506060810151613db9606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613dd5608084018267ffffffffffffffff169052565b5060a0810151613ded60a084018263ffffffff169052565b5060c0810151613e0a60c084018268ffffffffffffffffff169052565b5060e0810151613e2760e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016136dd8284613d46565b60008083601f840112613e8057600080fd5b50813567ffffffffffffffff811115613e9857600080fd5b6020830191508360208260051b850101111561385057600080fd5b60008060008060008060008060e0898b031215613ecf57600080fd5b606089018a811115613ee057600080fd5b8998503567ffffffffffffffff80821115613efa57600080fd5b613f068c838d0161380e565b909950975060808b0135915080821115613f1f57600080fd5b613f2b8c838d01613e6e565b909750955060a08b0135915080821115613f4457600080fd5b50613f518b828c01613e6e565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151613fbe608084018268ffffffffffffffffff169052565b5060a0830151613fd760a084018264ffffffffff169052565b5060c0830151613fed60c084018261ffff169052565b5060e083015161401d60e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b803561117081614039565b60008060008060006080868803121561407257600080fd5b853561407d81614039565b9450602086013567ffffffffffffffff81111561409957600080fd5b6140a58882890161380e565b90955093505060408601356140b981613965565b949793965091946060013592915050565b600067ffffffffffffffff8211156140e4576140e4613899565b5060051b60200190565b600082601f8301126140ff57600080fd5b8135602061411461410f836140ca565b613916565b82815260059290921b8401810191818101908684111561413357600080fd5b8286015b8481101561415757803561414a81613c02565b8352918301918301614137565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561418c57600080fd5b863567ffffffffffffffff808211156141a457600080fd5b6141b08a838b016140ee565b975060208901359150808211156141c657600080fd5b6141d28a838b016140ee565b96506141e060408a01614162565b955060608901359150808211156141f657600080fd5b6142028a838b01613b37565b945061421060808a0161404f565b935060a089013591508082111561422657600080fd5b5061423389828a01613b37565b9150509295509295509295565b60006020828403121561425257600080fd5b81356135ee81613c02565b600181811c9082168061427157607f821691505b6020821081036142aa577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c810160208610156142d75750805b601f850160051c820191505b81811015610a88578281556001016142e3565b67ffffffffffffffff83111561430e5761430e613899565b6143228361431c835461425d565b836142b0565b6000601f841160018114614374576000851561433e5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561440a565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156143c357868501358255602094850194600190920191016143a3565b50868210156143fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613982565b60006020828403121561442e57600080fd5b81516135ee81613982565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff82811682821603908082111561266157612661614439565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036144ed576144ed614439565b5060010190565b6000610160823603121561450757600080fd5b61450f6138f2565b823567ffffffffffffffff81111561452657600080fd5b61453236828601613b37565b8252506020830135602082015261454b60408401613c24565b604082015261455c60608401613c49565b606082015261456d60808401613999565b608082015261457e60a0840161404f565b60a082015261458f60c0840161404f565b60c08201526145a060e08401613977565b60e08201526101006145b38185016139c2565b908201526101206145c584820161404f565b908201526101406145d7848201613c24565b9082015292915050565b6000602082840312156145f357600080fd5b81356135ee81614039565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261463357600080fd5b83018035915067ffffffffffffffff82111561464e57600080fd5b60200191503681900382131561385057600080fd5b60006020828403121561467557600080fd5b6135ee826139c2565b60006020828403121561469057600080fd5b81356135ee81613965565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061313660e0830184613d46565b60ff81811683821601908111156136dd576136dd614439565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061479e5761479e61475c565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b80820281158282048414176136dd576136dd614439565b818103818111156136dd576136dd614439565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff81811683821601908082111561266157612661614439565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526148a68184018a613c8d565b905082810360808401526148ba8189613c8d565b905060ff871660a084015282810360c08401526148d78187613ada565b905067ffffffffffffffff851660e08401528281036101008401526148fc8185613ada565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a0868803121561493e57600080fd5b6149478661490c565b945060208601519350604086015192506060860151915061496a6080870161490c565b90509295509295909350565b60006bffffffffffffffffffffffff808416806149955761499561475c565b92169190910492915050565b6bffffffffffffffffffffffff81811683821601908082111561266157612661614439565b6bffffffffffffffffffffffff81811683821602808216919082811461403157614031614439565b808201808211156136dd576136dd614439565b67ffffffffffffffff81811683821601908082111561266157612661614439565b600082601f830112614a3357600080fd5b81356020614a4361410f836140ca565b82815260059290921b84018101918181019086841115614a6257600080fd5b8286015b848110156141575780358352918301918301614a66565b600082601f830112614a8e57600080fd5b81356020614a9e61410f836140ca565b82815260059290921b84018101918181019086841115614abd57600080fd5b8286015b8481101561415757803567ffffffffffffffff811115614ae15760008081fd5b614aef8986838b0101613b37565b845250918301918301614ac1565b600080600080600060a08688031215614b1557600080fd5b853567ffffffffffffffff80821115614b2d57600080fd5b614b3989838a01614a22565b96506020880135915080821115614b4f57600080fd5b614b5b89838a01614a7d565b95506040880135915080821115614b7157600080fd5b614b7d89838a01614a7d565b94506060880135915080821115614b9357600080fd5b614b9f89838a01614a7d565b93506080880135915080821115614bb557600080fd5b50614bc288828901614a7d565b9150509295509295909350565b600082614bde57614bde61475c565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614c2a8285018b613c8d565b91508382036080850152614c3e828a613c8d565b915060ff881660a085015283820360c0850152614c5b8288613ada565b90861660e085015283810361010085015290506148fc8185613ada565b805161117081613c02565b805161117081613c2f565b805161117081614039565b805161117081613965565b8051611170816139a4565b60006101608284031215614cc257600080fd5b614cca6138f2565b82518152614cda60208401614c78565b6020820152614ceb60408401614c83565b6040820152614cfc60608401614c78565b6060820152614d0d60808401614c8e565b6080820152614d1e60a08401614c99565b60a0820152614d2f60c08401614411565b60c0820152614d4060e08401614411565b60e0820152610100614d53818501614ca4565b90820152610120614d65848201614ca4565b90820152610140613aab848201614c99565b64ffffffffff81811683821601908082111561266157612661614439565b6000610200808352614da98184018a613ada565b90508281036020840152614dbd8189613ada565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614e06905060a0830184613d46565b979650505050505050565b60008060408385031215614e2457600080fd5b825160078110614e3357600080fd5b6020840151909250613c8281613c2f565b600060208284031215614e5657600080fd5b5051919050565b60008351614e6f818460208801613ab6565b835190830190614e83818360208801613ab6565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
}
var FunctionsCoordinatorABI = FunctionsCoordinatorMetaData.ABI
diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index cff49cd07c..3543116d21 100644
--- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -4,7 +4,7 @@ functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServ
functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
functions_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca
functions_client_example: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.bin abf32e69f268f40e8530eb8d8e96bf310b798a4c0049a58022d9d2fb527b601b
-functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 9e11effc1922d258d3fc38564b87f4466c56162f33d553ec6d66edcfa55923af
+functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 948c04942910f308942fdde460317f9ec038b6b702b018471ce6157a14a09072
functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.bin c8dbbd5ebb34435800d6674700068837c3a252db60046a14b0e61e829db517de
functions_oracle_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
functions_router: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.bin 9dedd3a36043605fd9bedf821e7ec5b4281a5c7ae2e4a1955f37aff8ba13519f
From b811f0093a787754ad836049e58cc8cefec67d91 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Thu, 9 Nov 2023 17:43:09 +0000
Subject: [PATCH 120/327] [fix] Use correct format for GH run URL (#11246)
---
tools/flakeytests/utils.go | 2 +-
tools/flakeytests/utils_test.go | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/flakeytests/utils.go b/tools/flakeytests/utils.go
index 698a9b49c9..d2326c4726 100644
--- a/tools/flakeytests/utils.go
+++ b/tools/flakeytests/utils.go
@@ -42,7 +42,7 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, r
log.Fatalf("Error unmarshaling gh event at path")
}
- runURL := fmt.Sprintf("%s/actions/%s", repo, runID)
+ runURL := fmt.Sprintf("github.com/%s/actions/runs/%s", repo, runID)
basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: runURL}
switch eventName {
case "pull_request":
diff --git a/tools/flakeytests/utils_test.go b/tools/flakeytests/utils_test.go
index 761d9cd255..6ea912d11d 100644
--- a/tools/flakeytests/utils_test.go
+++ b/tools/flakeytests/utils_test.go
@@ -37,12 +37,13 @@ var prEventTemplate = `
func TestGetGithubMetadata(t *testing.T) {
repo, eventName, sha, event, runID := "chainlink", "merge_group", "a-sha", `{}`, "1234"
+ expectedRunURL := fmt.Sprintf("github.com/%s/actions/runs/%s", repo, runID)
ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID)
- assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: fmt.Sprintf("%s/actions/%s", repo, runID)}, ctx)
+ assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: expectedRunURL}, ctx)
anotherSha, eventName, url := "another-sha", "pull_request", "a-url"
event = fmt.Sprintf(prEventTemplate, anotherSha, url)
sha = "302eb05d592132309b264e316f443f1ceb81b6c3"
ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID)
- assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url, RunURL: fmt.Sprintf("%s/actions/%s", repo, runID)}, ctx)
+ assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url, RunURL: expectedRunURL}, ctx)
}
From 5dea552b46533c687b804a40fbed433868732f0b Mon Sep 17 00:00:00 2001
From: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com>
Date: Thu, 9 Nov 2023 21:04:30 +0100
Subject: [PATCH 121/327] Generalized Multinode unit tests BCI-2283 (#11066)
* POC for generalized multinode tests
* sendOnly node tests
* multi node tests
* node fsm test & node aliveLoop
* node lifecycle tests
* increase test coverage
* fixed flakey tests
* fixed rebase artifacts
* nit fixes
* regen mocks
* review fixes
* replace core/testutils with `chainlink-relay/pkg/utils/tests`
* Apply suggestions from code review
Co-authored-by: Jordan Krage
Co-authored-by: Dimitris Grigoriou
* update chainlink-relay
* make gomodtidy
* Update common/client/send_only_node_test.go
Co-authored-by: Dimitris Grigoriou
* simplify node state check
* sendOnly & node tests fixes
* make gomodtidy
* fix deps
* update relay
* fix silly cleanup issue
* Apply suggestions from code review
Co-authored-by: Dimitris Grigoriou
* review fixes
---------
Co-authored-by: Jordan Krage
Co-authored-by: Dimitris Grigoriou
---
common/client/mock_hashable_test.go | 18 +
common/client/mock_head_test.go | 57 +
common/client/mock_node_client_test.go | 168 +++
common/client/mock_node_selector_test.go | 57 +
common/client/mock_node_test.go | 195 +++
common/client/mock_rpc_test.go | 608 ++++++++++
common/client/mock_send_only_client_test.go | 72 ++
common/client/mock_send_only_node_test.go | 127 ++
common/client/multi_node.go | 44 +-
common/client/multi_node_test.go | 635 ++++++++++
common/client/node.go | 25 +-
common/client/node_fsm_test.go | 108 ++
common/client/node_lifecycle.go | 12 +-
common/client/node_lifecycle_test.go | 1070 +++++++++++++++++
common/client/node_selector.go | 46 +
.../client/node_selector_highest_head_test.go | 176 +++
.../node_selector_priority_level_test.go | 88 ++
.../client/node_selector_round_robin_test.go | 61 +
common/client/node_selector_test.go | 18 +
.../node_selector_total_difficulty_test.go | 178 +++
common/client/node_test.go | 80 ++
common/client/send_only_node.go | 4 +
common/client/send_only_node_test.go | 139 +++
common/client/types.go | 6 +
common/types/test_utils.go | 16 +
25 files changed, 3956 insertions(+), 52 deletions(-)
create mode 100644 common/client/mock_hashable_test.go
create mode 100644 common/client/mock_head_test.go
create mode 100644 common/client/mock_node_client_test.go
create mode 100644 common/client/mock_node_selector_test.go
create mode 100644 common/client/mock_node_test.go
create mode 100644 common/client/mock_rpc_test.go
create mode 100644 common/client/mock_send_only_client_test.go
create mode 100644 common/client/mock_send_only_node_test.go
create mode 100644 common/client/multi_node_test.go
create mode 100644 common/client/node_fsm_test.go
create mode 100644 common/client/node_lifecycle_test.go
create mode 100644 common/client/node_selector.go
create mode 100644 common/client/node_selector_highest_head_test.go
create mode 100644 common/client/node_selector_priority_level_test.go
create mode 100644 common/client/node_selector_round_robin_test.go
create mode 100644 common/client/node_selector_test.go
create mode 100644 common/client/node_selector_total_difficulty_test.go
create mode 100644 common/client/node_test.go
create mode 100644 common/client/send_only_node_test.go
create mode 100644 common/types/test_utils.go
diff --git a/common/client/mock_hashable_test.go b/common/client/mock_hashable_test.go
new file mode 100644
index 0000000000..d9f1670c07
--- /dev/null
+++ b/common/client/mock_hashable_test.go
@@ -0,0 +1,18 @@
+package client
+
+import "cmp"
+
+// Hashable - simple implementation of types.Hashable interface to be used as concrete type in tests
+type Hashable string
+
+func (h Hashable) Cmp(c Hashable) int {
+ return cmp.Compare(h, c)
+}
+
+func (h Hashable) String() string {
+ return string(h)
+}
+
+func (h Hashable) Bytes() []byte {
+ return []byte(h)
+}
diff --git a/common/client/mock_head_test.go b/common/client/mock_head_test.go
new file mode 100644
index 0000000000..b9cf0a5866
--- /dev/null
+++ b/common/client/mock_head_test.go
@@ -0,0 +1,57 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ utils "github.com/smartcontractkit/chainlink/v2/core/utils"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// mockHead is an autogenerated mock type for the Head type
+type mockHead struct {
+ mock.Mock
+}
+
+// BlockDifficulty provides a mock function with given fields:
+func (_m *mockHead) BlockDifficulty() *utils.Big {
+ ret := _m.Called()
+
+ var r0 *utils.Big
+ if rf, ok := ret.Get(0).(func() *utils.Big); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*utils.Big)
+ }
+ }
+
+ return r0
+}
+
+// BlockNumber provides a mock function with given fields:
+func (_m *mockHead) BlockNumber() int64 {
+ ret := _m.Called()
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func() int64); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ return r0
+}
+
+// newMockHead creates a new instance of mockHead. 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 newMockHead(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockHead {
+ mock := &mockHead{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/mock_node_client_test.go b/common/client/mock_node_client_test.go
new file mode 100644
index 0000000000..7c8eb69171
--- /dev/null
+++ b/common/client/mock_node_client_test.go
@@ -0,0 +1,168 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ context "context"
+
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// mockNodeClient is an autogenerated mock type for the NodeClient type
+type mockNodeClient[CHAIN_ID types.ID, HEAD Head] struct {
+ mock.Mock
+}
+
+// ChainID provides a mock function with given fields: ctx
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) ChainID(ctx context.Context) (CHAIN_ID, error) {
+ ret := _m.Called(ctx)
+
+ var r0 CHAIN_ID
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (CHAIN_ID, error)); ok {
+ return rf(ctx)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) CHAIN_ID); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(CHAIN_ID)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ClientVersion provides a mock function with given fields: _a0
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) ClientVersion(_a0 context.Context) (string, error) {
+ ret := _m.Called(_a0)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok {
+ return rf(_a0)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) string); ok {
+ r0 = rf(_a0)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(_a0)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Close provides a mock function with given fields:
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) Close() {
+ _m.Called()
+}
+
+// Dial provides a mock function with given fields: ctx
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) Dial(ctx context.Context) error {
+ ret := _m.Called(ctx)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DialHTTP provides a mock function with given fields:
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) DialHTTP() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DisconnectAll provides a mock function with given fields:
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) DisconnectAll() {
+ _m.Called()
+}
+
+// SetAliveLoopSub provides a mock function with given fields: _a0
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) SetAliveLoopSub(_a0 types.Subscription) {
+ _m.Called(_a0)
+}
+
+// Subscribe provides a mock function with given fields: ctx, channel, args
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (types.Subscription, error) {
+ var _ca []interface{}
+ _ca = append(_ca, ctx, channel)
+ _ca = append(_ca, args...)
+ ret := _m.Called(_ca...)
+
+ var r0 types.Subscription
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) (types.Subscription, error)); ok {
+ return rf(ctx, channel, args...)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) types.Subscription); ok {
+ r0 = rf(ctx, channel, args...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Subscription)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD, ...interface{}) error); ok {
+ r1 = rf(ctx, channel, args...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SubscribersCount provides a mock function with given fields:
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) SubscribersCount() int32 {
+ ret := _m.Called()
+
+ var r0 int32
+ if rf, ok := ret.Get(0).(func() int32); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(int32)
+ }
+
+ return r0
+}
+
+// UnsubscribeAllExceptAliveLoop provides a mock function with given fields:
+func (_m *mockNodeClient[CHAIN_ID, HEAD]) UnsubscribeAllExceptAliveLoop() {
+ _m.Called()
+}
+
+// newMockNodeClient creates a new instance of mockNodeClient. 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 newMockNodeClient[CHAIN_ID types.ID, HEAD Head](t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockNodeClient[CHAIN_ID, HEAD] {
+ mock := &mockNodeClient[CHAIN_ID, HEAD]{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/mock_node_selector_test.go b/common/client/mock_node_selector_test.go
new file mode 100644
index 0000000000..e7b8d9ecb8
--- /dev/null
+++ b/common/client/mock_node_selector_test.go
@@ -0,0 +1,57 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// mockNodeSelector is an autogenerated mock type for the NodeSelector type
+type mockNodeSelector[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct {
+ mock.Mock
+}
+
+// Name provides a mock function with given fields:
+func (_m *mockNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// Select provides a mock function with given fields:
+func (_m *mockNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] {
+ ret := _m.Called()
+
+ var r0 Node[CHAIN_ID, HEAD, RPC]
+ if rf, ok := ret.Get(0).(func() Node[CHAIN_ID, HEAD, RPC]); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(Node[CHAIN_ID, HEAD, RPC])
+ }
+ }
+
+ return r0
+}
+
+// newMockNodeSelector creates a new instance of mockNodeSelector. 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 newMockNodeSelector[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]](t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockNodeSelector[CHAIN_ID, HEAD, RPC] {
+ mock := &mockNodeSelector[CHAIN_ID, HEAD, RPC]{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/mock_node_test.go b/common/client/mock_node_test.go
new file mode 100644
index 0000000000..bd704cd2c6
--- /dev/null
+++ b/common/client/mock_node_test.go
@@ -0,0 +1,195 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ context "context"
+
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
+ mock "github.com/stretchr/testify/mock"
+
+ utils "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+// mockNode is an autogenerated mock type for the Node type
+type mockNode[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct {
+ mock.Mock
+}
+
+// Close provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Close() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// ConfiguredChainID provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() CHAIN_ID {
+ ret := _m.Called()
+
+ var r0 CHAIN_ID
+ if rf, ok := ret.Get(0).(func() CHAIN_ID); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(CHAIN_ID)
+ }
+
+ return r0
+}
+
+// Name provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Name() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// Order provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Order() int32 {
+ ret := _m.Called()
+
+ var r0 int32
+ if rf, ok := ret.Get(0).(func() int32); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(int32)
+ }
+
+ return r0
+}
+
+// RPC provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) RPC() RPC {
+ ret := _m.Called()
+
+ var r0 RPC
+ if rf, ok := ret.Get(0).(func() RPC); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(RPC)
+ }
+
+ return r0
+}
+
+// Start provides a mock function with given fields: _a0
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Start(_a0 context.Context) error {
+ ret := _m.Called(_a0)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+ r0 = rf(_a0)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// State provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) State() nodeState {
+ ret := _m.Called()
+
+ var r0 nodeState
+ if rf, ok := ret.Get(0).(func() nodeState); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(nodeState)
+ }
+
+ return r0
+}
+
+// StateAndLatest provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *utils.Big) {
+ ret := _m.Called()
+
+ var r0 nodeState
+ var r1 int64
+ var r2 *utils.Big
+ if rf, ok := ret.Get(0).(func() (nodeState, int64, *utils.Big)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() nodeState); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(nodeState)
+ }
+
+ if rf, ok := ret.Get(1).(func() int64); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Get(1).(int64)
+ }
+
+ if rf, ok := ret.Get(2).(func() *utils.Big); ok {
+ r2 = rf()
+ } else {
+ if ret.Get(2) != nil {
+ r2 = ret.Get(2).(*utils.Big)
+ }
+ }
+
+ return r0, r1, r2
+}
+
+// String provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) String() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// SubscribersCount provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) SubscribersCount() int32 {
+ ret := _m.Called()
+
+ var r0 int32
+ if rf, ok := ret.Get(0).(func() int32); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(int32)
+ }
+
+ return r0
+}
+
+// UnsubscribeAllExceptAliveLoop provides a mock function with given fields:
+func (_m *mockNode[CHAIN_ID, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() {
+ _m.Called()
+}
+
+// newMockNode creates a new instance of mockNode. 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 newMockNode[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]](t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockNode[CHAIN_ID, HEAD, RPC] {
+ mock := &mockNode[CHAIN_ID, HEAD, RPC]{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/mock_rpc_test.go b/common/client/mock_rpc_test.go
new file mode 100644
index 0000000000..c378b9384e
--- /dev/null
+++ b/common/client/mock_rpc_test.go
@@ -0,0 +1,608 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ big "math/big"
+
+ assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+
+ context "context"
+
+ feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
+
+ mock "github.com/stretchr/testify/mock"
+
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+// mockRPC is an autogenerated mock type for the RPC type
+type mockRPC[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH]] struct {
+ mock.Mock
+}
+
+// BalanceAt provides a mock function with given fields: ctx, accountAddress, blockNumber
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) BalanceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (*big.Int, error) {
+ ret := _m.Called(ctx, accountAddress, blockNumber)
+
+ var r0 *big.Int
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) (*big.Int, error)); ok {
+ return rf(ctx, accountAddress, blockNumber)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) *big.Int); ok {
+ r0 = rf(ctx, accountAddress, blockNumber)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*big.Int)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, ADDR, *big.Int) error); ok {
+ r1 = rf(ctx, accountAddress, blockNumber)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// BatchCallContext provides a mock function with given fields: ctx, b
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) BatchCallContext(ctx context.Context, b []interface{}) error {
+ ret := _m.Called(ctx, b)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, []interface{}) error); ok {
+ r0 = rf(ctx, b)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// BlockByHash provides a mock function with given fields: ctx, hash
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) BlockByHash(ctx context.Context, hash BLOCK_HASH) (HEAD, error) {
+ ret := _m.Called(ctx, hash)
+
+ var r0 HEAD
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, BLOCK_HASH) (HEAD, error)); ok {
+ return rf(ctx, hash)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, BLOCK_HASH) HEAD); ok {
+ r0 = rf(ctx, hash)
+ } else {
+ r0 = ret.Get(0).(HEAD)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, BLOCK_HASH) error); ok {
+ r1 = rf(ctx, hash)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// BlockByNumber provides a mock function with given fields: ctx, number
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) BlockByNumber(ctx context.Context, number *big.Int) (HEAD, error) {
+ ret := _m.Called(ctx, number)
+
+ var r0 HEAD
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (HEAD, error)); ok {
+ return rf(ctx, number)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *big.Int) HEAD); ok {
+ r0 = rf(ctx, number)
+ } else {
+ r0 = ret.Get(0).(HEAD)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok {
+ r1 = rf(ctx, number)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CallContext provides a mock function with given fields: ctx, result, method, args
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
+ var _ca []interface{}
+ _ca = append(_ca, ctx, result, method)
+ _ca = append(_ca, args...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, interface{}, string, ...interface{}) error); ok {
+ r0 = rf(ctx, result, method, args...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// CallContract provides a mock function with given fields: ctx, msg, blockNumber
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) ([]byte, error) {
+ ret := _m.Called(ctx, msg, blockNumber)
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, interface{}, *big.Int) ([]byte, error)); ok {
+ return rf(ctx, msg, blockNumber)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, interface{}, *big.Int) []byte); ok {
+ r0 = rf(ctx, msg, blockNumber)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, interface{}, *big.Int) error); ok {
+ r1 = rf(ctx, msg, blockNumber)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ChainID provides a mock function with given fields: ctx
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) ChainID(ctx context.Context) (CHAIN_ID, error) {
+ ret := _m.Called(ctx)
+
+ var r0 CHAIN_ID
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (CHAIN_ID, error)); ok {
+ return rf(ctx)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) CHAIN_ID); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(CHAIN_ID)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ClientVersion provides a mock function with given fields: _a0
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) ClientVersion(_a0 context.Context) (string, error) {
+ ret := _m.Called(_a0)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok {
+ return rf(_a0)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) string); ok {
+ r0 = rf(_a0)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(_a0)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Close provides a mock function with given fields:
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) Close() {
+ _m.Called()
+}
+
+// CodeAt provides a mock function with given fields: ctx, account, blockNumber
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) ([]byte, error) {
+ ret := _m.Called(ctx, account, blockNumber)
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) ([]byte, error)); ok {
+ return rf(ctx, account, blockNumber)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) []byte); ok {
+ r0 = rf(ctx, account, blockNumber)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, ADDR, *big.Int) error); ok {
+ r1 = rf(ctx, account, blockNumber)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Dial provides a mock function with given fields: ctx
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) Dial(ctx context.Context) error {
+ ret := _m.Called(ctx)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DialHTTP provides a mock function with given fields:
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) DialHTTP() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DisconnectAll provides a mock function with given fields:
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) DisconnectAll() {
+ _m.Called()
+}
+
+// EstimateGas provides a mock function with given fields: ctx, call
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) EstimateGas(ctx context.Context, call interface{}) (uint64, error) {
+ ret := _m.Called(ctx, call)
+
+ var r0 uint64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, interface{}) (uint64, error)); ok {
+ return rf(ctx, call)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, interface{}) uint64); ok {
+ r0 = rf(ctx, call)
+ } else {
+ r0 = ret.Get(0).(uint64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, interface{}) error); ok {
+ r1 = rf(ctx, call)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FilterEvents provides a mock function with given fields: ctx, query
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) FilterEvents(ctx context.Context, query EVENT_OPS) ([]EVENT, error) {
+ ret := _m.Called(ctx, query)
+
+ var r0 []EVENT
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, EVENT_OPS) ([]EVENT, error)); ok {
+ return rf(ctx, query)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, EVENT_OPS) []EVENT); ok {
+ r0 = rf(ctx, query)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]EVENT)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, EVENT_OPS) error); ok {
+ r1 = rf(ctx, query)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// LINKBalance provides a mock function with given fields: ctx, accountAddress, linkAddress
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) LINKBalance(ctx context.Context, accountAddress ADDR, linkAddress ADDR) (*assets.Link, error) {
+ ret := _m.Called(ctx, accountAddress, linkAddress)
+
+ var r0 *assets.Link
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) (*assets.Link, error)); ok {
+ return rf(ctx, accountAddress, linkAddress)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) *assets.Link); ok {
+ r0 = rf(ctx, accountAddress, linkAddress)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*assets.Link)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, ADDR, ADDR) error); ok {
+ r1 = rf(ctx, accountAddress, linkAddress)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// LatestBlockHeight provides a mock function with given fields: _a0
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) LatestBlockHeight(_a0 context.Context) (*big.Int, error) {
+ ret := _m.Called(_a0)
+
+ var r0 *big.Int
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok {
+ return rf(_a0)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok {
+ r0 = rf(_a0)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*big.Int)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(_a0)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// PendingSequenceAt provides a mock function with given fields: ctx, addr
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) PendingSequenceAt(ctx context.Context, addr ADDR) (SEQ, error) {
+ ret := _m.Called(ctx, addr)
+
+ var r0 SEQ
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR) (SEQ, error)); ok {
+ return rf(ctx, addr)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR) SEQ); ok {
+ r0 = rf(ctx, addr)
+ } else {
+ r0 = ret.Get(0).(SEQ)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, ADDR) error); ok {
+ r1 = rf(ctx, addr)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SendEmptyTransaction provides a mock function with given fields: ctx, newTxAttempt, seq, gasLimit, fee, fromAddress
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) SendEmptyTransaction(ctx context.Context, newTxAttempt func(SEQ, uint32, FEE, ADDR) (interface{}, error), seq SEQ, gasLimit uint32, fee FEE, fromAddress ADDR) (string, error) {
+ ret := _m.Called(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) (string, error)); ok {
+ return rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) string); ok {
+ r0 = rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) error); ok {
+ r1 = rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SendTransaction provides a mock function with given fields: ctx, tx
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) SendTransaction(ctx context.Context, tx TX) error {
+ ret := _m.Called(ctx, tx)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, TX) error); ok {
+ r0 = rf(ctx, tx)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// SequenceAt provides a mock function with given fields: ctx, accountAddress, blockNumber
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) SequenceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (SEQ, error) {
+ ret := _m.Called(ctx, accountAddress, blockNumber)
+
+ var r0 SEQ
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) (SEQ, error)); ok {
+ return rf(ctx, accountAddress, blockNumber)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) SEQ); ok {
+ r0 = rf(ctx, accountAddress, blockNumber)
+ } else {
+ r0 = ret.Get(0).(SEQ)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, ADDR, *big.Int) error); ok {
+ r1 = rf(ctx, accountAddress, blockNumber)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SetAliveLoopSub provides a mock function with given fields: _a0
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) SetAliveLoopSub(_a0 types.Subscription) {
+ _m.Called(_a0)
+}
+
+// SimulateTransaction provides a mock function with given fields: ctx, tx
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) SimulateTransaction(ctx context.Context, tx TX) error {
+ ret := _m.Called(ctx, tx)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, TX) error); ok {
+ r0 = rf(ctx, tx)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Subscribe provides a mock function with given fields: ctx, channel, args
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (types.Subscription, error) {
+ var _ca []interface{}
+ _ca = append(_ca, ctx, channel)
+ _ca = append(_ca, args...)
+ ret := _m.Called(_ca...)
+
+ var r0 types.Subscription
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) (types.Subscription, error)); ok {
+ return rf(ctx, channel, args...)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) types.Subscription); ok {
+ r0 = rf(ctx, channel, args...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Subscription)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD, ...interface{}) error); ok {
+ r1 = rf(ctx, channel, args...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SubscribersCount provides a mock function with given fields:
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) SubscribersCount() int32 {
+ ret := _m.Called()
+
+ var r0 int32
+ if rf, ok := ret.Get(0).(func() int32); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(int32)
+ }
+
+ return r0
+}
+
+// TokenBalance provides a mock function with given fields: ctx, accountAddress, tokenAddress
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) TokenBalance(ctx context.Context, accountAddress ADDR, tokenAddress ADDR) (*big.Int, error) {
+ ret := _m.Called(ctx, accountAddress, tokenAddress)
+
+ var r0 *big.Int
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) (*big.Int, error)); ok {
+ return rf(ctx, accountAddress, tokenAddress)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) *big.Int); ok {
+ r0 = rf(ctx, accountAddress, tokenAddress)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*big.Int)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, ADDR, ADDR) error); ok {
+ r1 = rf(ctx, accountAddress, tokenAddress)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// TransactionByHash provides a mock function with given fields: ctx, txHash
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) TransactionByHash(ctx context.Context, txHash TX_HASH) (TX, error) {
+ ret := _m.Called(ctx, txHash)
+
+ var r0 TX
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) (TX, error)); ok {
+ return rf(ctx, txHash)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) TX); ok {
+ r0 = rf(ctx, txHash)
+ } else {
+ r0 = ret.Get(0).(TX)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, TX_HASH) error); ok {
+ r1 = rf(ctx, txHash)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// TransactionReceipt provides a mock function with given fields: ctx, txHash
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) TransactionReceipt(ctx context.Context, txHash TX_HASH) (TX_RECEIPT, error) {
+ ret := _m.Called(ctx, txHash)
+
+ var r0 TX_RECEIPT
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) (TX_RECEIPT, error)); ok {
+ return rf(ctx, txHash)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) TX_RECEIPT); ok {
+ r0 = rf(ctx, txHash)
+ } else {
+ r0 = ret.Get(0).(TX_RECEIPT)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, TX_HASH) error); ok {
+ r1 = rf(ctx, txHash)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// UnsubscribeAllExceptAliveLoop provides a mock function with given fields:
+func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]) UnsubscribeAllExceptAliveLoop() {
+ _m.Called()
+}
+
+// newMockRPC creates a new instance of mockRPC. 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 newMockRPC[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH]](t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD] {
+ mock := &mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD]{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/mock_send_only_client_test.go b/common/client/mock_send_only_client_test.go
new file mode 100644
index 0000000000..481b2602ea
--- /dev/null
+++ b/common/client/mock_send_only_client_test.go
@@ -0,0 +1,72 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ context "context"
+
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// mockSendOnlyClient is an autogenerated mock type for the sendOnlyClient type
+type mockSendOnlyClient[CHAIN_ID types.ID] struct {
+ mock.Mock
+}
+
+// ChainID provides a mock function with given fields: _a0
+func (_m *mockSendOnlyClient[CHAIN_ID]) ChainID(_a0 context.Context) (CHAIN_ID, error) {
+ ret := _m.Called(_a0)
+
+ var r0 CHAIN_ID
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (CHAIN_ID, error)); ok {
+ return rf(_a0)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) CHAIN_ID); ok {
+ r0 = rf(_a0)
+ } else {
+ r0 = ret.Get(0).(CHAIN_ID)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(_a0)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Close provides a mock function with given fields:
+func (_m *mockSendOnlyClient[CHAIN_ID]) Close() {
+ _m.Called()
+}
+
+// DialHTTP provides a mock function with given fields:
+func (_m *mockSendOnlyClient[CHAIN_ID]) DialHTTP() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// newMockSendOnlyClient creates a new instance of mockSendOnlyClient. 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 newMockSendOnlyClient[CHAIN_ID types.ID](t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockSendOnlyClient[CHAIN_ID] {
+ mock := &mockSendOnlyClient[CHAIN_ID]{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/mock_send_only_node_test.go b/common/client/mock_send_only_node_test.go
new file mode 100644
index 0000000000..524d7d8a6c
--- /dev/null
+++ b/common/client/mock_send_only_node_test.go
@@ -0,0 +1,127 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package client
+
+import (
+ context "context"
+
+ types "github.com/smartcontractkit/chainlink/v2/common/types"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// mockSendOnlyNode is an autogenerated mock type for the SendOnlyNode type
+type mockSendOnlyNode[CHAIN_ID types.ID, RPC sendOnlyClient[CHAIN_ID]] struct {
+ mock.Mock
+}
+
+// Close provides a mock function with given fields:
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Close() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// ConfiguredChainID provides a mock function with given fields:
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID {
+ ret := _m.Called()
+
+ var r0 CHAIN_ID
+ if rf, ok := ret.Get(0).(func() CHAIN_ID); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(CHAIN_ID)
+ }
+
+ return r0
+}
+
+// Name provides a mock function with given fields:
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Name() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// RPC provides a mock function with given fields:
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) RPC() RPC {
+ ret := _m.Called()
+
+ var r0 RPC
+ if rf, ok := ret.Get(0).(func() RPC); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(RPC)
+ }
+
+ return r0
+}
+
+// Start provides a mock function with given fields: _a0
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Start(_a0 context.Context) error {
+ ret := _m.Called(_a0)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+ r0 = rf(_a0)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// State provides a mock function with given fields:
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) State() nodeState {
+ ret := _m.Called()
+
+ var r0 nodeState
+ if rf, ok := ret.Get(0).(func() nodeState); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(nodeState)
+ }
+
+ return r0
+}
+
+// String provides a mock function with given fields:
+func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) String() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// newMockSendOnlyNode creates a new instance of mockSendOnlyNode. 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 newMockSendOnlyNode[CHAIN_ID types.ID, RPC sendOnlyClient[CHAIN_ID]](t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *mockSendOnlyNode[CHAIN_ID, RPC] {
+ mock := &mockSendOnlyNode[CHAIN_ID, RPC]{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/common/client/multi_node.go b/common/client/multi_node.go
index f54e3115d9..c268cfb23c 100644
--- a/common/client/multi_node.go
+++ b/common/client/multi_node.go
@@ -30,25 +30,6 @@ var (
ErroringNodeError = fmt.Errorf("no live nodes available")
)
-const (
- NodeSelectionModeHighestHead = "HighestHead"
- NodeSelectionModeRoundRobin = "RoundRobin"
- NodeSelectionModeTotalDifficulty = "TotalDifficulty"
- NodeSelectionModePriorityLevel = "PriorityLevel"
-)
-
-type NodeSelector[
- CHAIN_ID types.ID,
- HEAD Head,
- RPC NodeClient[CHAIN_ID, HEAD],
-] interface {
- // Select returns a Node, or nil if none can be selected.
- // Implementation must be thread-safe.
- Select() Node[CHAIN_ID, HEAD, RPC]
- // Name returns the strategy name, e.g. "HighestHead" or "RoundRobin"
- Name() string
-}
-
// MultiNode is a generalized multi node client interface that includes methods to interact with different chains.
// It also handles multiple node RPC connections simultaneously.
type MultiNode[
@@ -113,6 +94,7 @@ type multiNode[
leaseDuration time.Duration
leaseTicker *time.Ticker
chainFamily string
+ reportInterval time.Duration
activeMu sync.RWMutex
activeNode Node[CHAIN_ID, HEAD, RPC_CLIENT]
@@ -148,23 +130,13 @@ func NewMultiNode[
chainFamily string,
sendOnlyErrorParser func(err error) SendTxReturnCode,
) MultiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT] {
- nodeSelector := func() NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] {
- switch selectionMode {
- case NodeSelectionModeHighestHead:
- return NewHighestHeadNodeSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
- case NodeSelectionModeRoundRobin:
- return NewRoundRobinSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
- case NodeSelectionModeTotalDifficulty:
- return NewTotalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
- case NodeSelectionModePriorityLevel:
- return NewPriorityLevelNodeSelector[CHAIN_ID, HEAD, RPC_CLIENT](nodes)
- default:
- panic(fmt.Sprintf("unsupported NodeSelectionMode: %s", selectionMode))
- }
- }()
+ nodeSelector := newNodeSelector(selectionMode, nodes)
lggr := logger.Named("MultiNode").With("chainID", chainID.String())
+ // Prometheus' default interval is 15s, set this to under 7.5s to avoid
+ // aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency)
+ const reportInterval = 6500 * time.Millisecond
c := &multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]{
nodes: nodes,
sendonlys: sendonlys,
@@ -178,6 +150,7 @@ func NewMultiNode[
leaseDuration: leaseDuration,
chainFamily: chainFamily,
sendOnlyErrorParser: sendOnlyErrorParser,
+ reportInterval: reportInterval,
}
c.logger.Debugf("The MultiNode is configured to use NodeSelectionMode: %s", selectionMode)
@@ -341,10 +314,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP
c.report()
- // Prometheus' default interval is 15s, set this to under 7.5s to avoid
- // aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency)
- reportInterval := 6500 * time.Millisecond
- monitor := time.NewTicker(utils.WithJitter(reportInterval))
+ monitor := time.NewTicker(utils.WithJitter(c.reportInterval))
defer monitor.Stop()
for {
diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go
new file mode 100644
index 0000000000..1fddbc3be3
--- /dev/null
+++ b/common/client/multi_node_test.go
@@ -0,0 +1,635 @@
+package client
+
+import (
+ "fmt"
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/zap"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type multiNodeRPCClient RPC[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any,
+ types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable]]
+
+type testMultiNode struct {
+ *multiNode[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any,
+ types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient]
+}
+
+type multiNodeOpts struct {
+ logger logger.Logger
+ selectionMode string
+ leaseDuration time.Duration
+ noNewHeadsThreshold time.Duration
+ nodes []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]
+ sendonlys []SendOnlyNode[types.ID, multiNodeRPCClient]
+ chainID types.ID
+ chainType config.ChainType
+ chainFamily string
+ sendOnlyErrorParser func(err error) SendTxReturnCode
+}
+
+func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode {
+ if opts.logger == nil {
+ opts.logger = logger.TestLogger(t)
+ }
+
+ result := NewMultiNode[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any,
+ types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient](opts.logger,
+ opts.selectionMode, opts.leaseDuration, opts.noNewHeadsThreshold, opts.nodes, opts.sendonlys,
+ opts.chainID, opts.chainType, opts.chainFamily, opts.sendOnlyErrorParser)
+ return testMultiNode{
+ result.(*multiNode[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any,
+ types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient]),
+ }
+}
+
+func newMultiNodeRPCClient(t *testing.T) *mockRPC[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any,
+ types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable]] {
+ return newMockRPC[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any,
+ types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable]](t)
+}
+
+func newHealthyNode(t *testing.T, chainID types.ID) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] {
+ return newNodeWithState(t, chainID, nodeStateAlive)
+}
+
+func newNodeWithState(t *testing.T, chainID types.ID, state nodeState) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] {
+ node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node.On("ConfiguredChainID").Return(chainID).Once()
+ node.On("Start", mock.Anything).Return(nil).Once()
+ node.On("Close").Return(nil).Once()
+ node.On("State").Return(state).Maybe()
+ node.On("String").Return(fmt.Sprintf("healthy_node_%d", rand.Int())).Maybe()
+ return node
+}
+func TestMultiNode_Dial(t *testing.T) {
+ t.Parallel()
+
+ newMockNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient]
+ newMockSendOnlyNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient]
+
+ t.Run("Fails without nodes", func(t *testing.T) {
+ t.Parallel()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: types.RandomID(),
+ })
+ err := mn.Dial(tests.Context(t))
+ assert.EqualError(t, err, fmt.Sprintf("no available nodes for chain %s", mn.chainID.String()))
+ })
+ t.Run("Fails with wrong node's chainID", func(t *testing.T) {
+ t.Parallel()
+ node := newMockNode(t)
+ multiNodeChainID := types.NewIDFromInt(10)
+ nodeChainID := types.NewIDFromInt(11)
+ node.On("ConfiguredChainID").Return(nodeChainID).Twice()
+ const nodeName = "nodeName"
+ node.On("String").Return(nodeName).Once()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: multiNodeChainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ })
+ err := mn.Dial(tests.Context(t))
+ assert.EqualError(t, err, fmt.Sprintf("node %s has configured chain ID %s which does not match multinode configured chain ID of %s", nodeName, nodeChainID, mn.chainID))
+ })
+ t.Run("Fails if node fails", func(t *testing.T) {
+ t.Parallel()
+ node := newMockNode(t)
+ chainID := types.RandomID()
+ node.On("ConfiguredChainID").Return(chainID).Once()
+ expectedError := errors.New("failed to start node")
+ node.On("Start", mock.Anything).Return(expectedError).Once()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ })
+ err := mn.Dial(tests.Context(t))
+ assert.EqualError(t, err, expectedError.Error())
+ })
+
+ t.Run("Closes started nodes on failure", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node1 := newHealthyNode(t, chainID)
+ node2 := newMockNode(t)
+ node2.On("ConfiguredChainID").Return(chainID).Once()
+ expectedError := errors.New("failed to start node")
+ node2.On("Start", mock.Anything).Return(expectedError).Once()
+
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node1, node2},
+ })
+ err := mn.Dial(tests.Context(t))
+ assert.EqualError(t, err, expectedError.Error())
+ })
+ t.Run("Fails with wrong send only node's chainID", func(t *testing.T) {
+ t.Parallel()
+ multiNodeChainID := types.NewIDFromInt(10)
+ node := newHealthyNode(t, multiNodeChainID)
+ sendOnly := newMockSendOnlyNode(t)
+ sendOnlyChainID := types.NewIDFromInt(11)
+ sendOnly.On("ConfiguredChainID").Return(sendOnlyChainID).Twice()
+ const sendOnlyName = "sendOnlyNodeName"
+ sendOnly.On("String").Return(sendOnlyName).Once()
+
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: multiNodeChainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{sendOnly},
+ })
+ err := mn.Dial(tests.Context(t))
+ assert.EqualError(t, err, fmt.Sprintf("sendonly node %s has configured chain ID %s which does not match multinode configured chain ID of %s", sendOnlyName, sendOnlyChainID, mn.chainID))
+ })
+
+ newHealthySendOnly := func(t *testing.T, chainID types.ID) *mockSendOnlyNode[types.ID, multiNodeRPCClient] {
+ node := newMockSendOnlyNode(t)
+ node.On("ConfiguredChainID").Return(chainID).Once()
+ node.On("Start", mock.Anything).Return(nil).Once()
+ node.On("Close").Return(nil).Once()
+ return node
+ }
+ t.Run("Fails on send only node failure", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.NewIDFromInt(10)
+ node := newHealthyNode(t, chainID)
+ sendOnly1 := newHealthySendOnly(t, chainID)
+ sendOnly2 := newMockSendOnlyNode(t)
+ sendOnly2.On("ConfiguredChainID").Return(chainID).Once()
+ expectedError := errors.New("failed to start send only node")
+ sendOnly2.On("Start", mock.Anything).Return(expectedError).Once()
+
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{sendOnly1, sendOnly2},
+ })
+ err := mn.Dial(tests.Context(t))
+ assert.EqualError(t, err, expectedError.Error())
+ })
+ t.Run("Starts successfully with healthy nodes", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.NewIDFromInt(10)
+ node := newHealthyNode(t, chainID)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newHealthySendOnly(t, chainID)},
+ })
+ defer func() { assert.NoError(t, mn.Close()) }()
+ err := mn.Dial(tests.Context(t))
+ require.NoError(t, err)
+ selectedNode, err := mn.selectNode()
+ require.NoError(t, err)
+ assert.Equal(t, node, selectedNode)
+ })
+}
+
+func TestMultiNode_Report(t *testing.T) {
+ t.Parallel()
+ t.Run("Dial starts periodical reporting", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node1 := newHealthyNode(t, chainID)
+ node2 := newNodeWithState(t, chainID, nodeStateOutOfSync)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node1, node2},
+ logger: lggr,
+ })
+ mn.reportInterval = tests.TestInterval
+ defer func() { assert.NoError(t, mn.Close()) }()
+ err := mn.Dial(tests.Context(t))
+ require.NoError(t, err)
+ tests.AssertLogCountEventually(t, observedLogs, "At least one primary node is dead: 1/2 nodes are alive", 2)
+ })
+ t.Run("Report critical error on all node failure", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node := newNodeWithState(t, chainID, nodeStateOutOfSync)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ logger: lggr,
+ })
+ mn.reportInterval = tests.TestInterval
+ defer func() { assert.NoError(t, mn.Close()) }()
+ err := mn.Dial(tests.Context(t))
+ require.NoError(t, err)
+ tests.AssertLogCountEventually(t, observedLogs, "no primary nodes available: 0/1 nodes are alive", 2)
+ err = mn.Healthy()
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "no primary nodes available: 0/1 nodes are alive")
+ })
+}
+
+func TestMultiNode_CheckLease(t *testing.T) {
+ t.Parallel()
+ t.Run("Round robin disables lease check", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node := newHealthyNode(t, chainID)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.InfoLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ logger: lggr,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ })
+ defer func() { assert.NoError(t, mn.Close()) }()
+ err := mn.Dial(tests.Context(t))
+ require.NoError(t, err)
+ tests.RequireLogMessage(t, observedLogs, "Best node switching is disabled")
+ })
+ t.Run("Misconfigured lease check period won't start", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node := newHealthyNode(t, chainID)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.InfoLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeHighestHead,
+ chainID: chainID,
+ logger: lggr,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node},
+ leaseDuration: 0,
+ })
+ defer func() { assert.NoError(t, mn.Close()) }()
+ err := mn.Dial(tests.Context(t))
+ require.NoError(t, err)
+ tests.RequireLogMessage(t, observedLogs, "Best node switching is disabled")
+ })
+ t.Run("Lease check updates active node", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node := newHealthyNode(t, chainID)
+ node.On("SubscribersCount").Return(int32(2))
+ node.On("UnsubscribeAllExceptAliveLoop")
+ bestNode := newHealthyNode(t, chainID)
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(bestNode)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.InfoLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeHighestHead,
+ chainID: chainID,
+ logger: lggr,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node, bestNode},
+ leaseDuration: tests.TestInterval,
+ })
+ defer func() { assert.NoError(t, mn.Close()) }()
+ mn.nodeSelector = nodeSelector
+ err := mn.Dial(tests.Context(t))
+ require.NoError(t, err)
+ tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("Switching to best node from %q to %q", node.String(), bestNode.String()))
+ tests.AssertEventually(t, func() bool {
+ mn.activeMu.RLock()
+ active := mn.activeNode
+ mn.activeMu.RUnlock()
+ return bestNode == active
+ })
+ })
+ t.Run("NodeStates returns proper states", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.NewIDFromInt(10)
+ nodes := map[string]nodeState{
+ "node_1": nodeStateAlive,
+ "node_2": nodeStateUnreachable,
+ "node_3": nodeStateDialed,
+ }
+
+ opts := multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ }
+
+ expectedResult := map[string]string{}
+ for name, state := range nodes {
+ node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node.On("Name").Return(name).Once()
+ node.On("State").Return(state).Once()
+ opts.nodes = append(opts.nodes, node)
+
+ sendOnly := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t)
+ sendOnlyName := "send_only_" + name
+ sendOnly.On("Name").Return(sendOnlyName).Once()
+ sendOnly.On("State").Return(state).Once()
+ opts.sendonlys = append(opts.sendonlys, sendOnly)
+
+ expectedResult[name] = state.String()
+ expectedResult[sendOnlyName] = state.String()
+ }
+
+ mn := newTestMultiNode(t, opts)
+ states := mn.NodeStates()
+ assert.Equal(t, expectedResult, states)
+ })
+}
+
+func TestMultiNode_selectNode(t *testing.T) {
+ t.Parallel()
+ t.Run("Returns same node, if it's still healthy", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ node1 := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node1.On("State").Return(nodeStateAlive).Once()
+ node1.On("String").Return("node1").Maybe()
+ node2 := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node2.On("String").Return("node2").Maybe()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node1, node2},
+ })
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(node1).Once()
+ mn.nodeSelector = nodeSelector
+ prevActiveNode, err := mn.selectNode()
+ require.NoError(t, err)
+ require.Equal(t, node1.String(), prevActiveNode.String())
+ newActiveNode, err := mn.selectNode()
+ require.NoError(t, err)
+ require.Equal(t, prevActiveNode.String(), newActiveNode.String())
+
+ })
+ t.Run("Updates node if active is not healthy", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ oldBest := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ oldBest.On("String").Return("oldBest").Maybe()
+ newBest := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ newBest.On("String").Return("newBest").Maybe()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{oldBest, newBest},
+ })
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(oldBest).Once()
+ mn.nodeSelector = nodeSelector
+ activeNode, err := mn.selectNode()
+ require.NoError(t, err)
+ require.Equal(t, oldBest.String(), activeNode.String())
+ // old best died, so we should replace it
+ oldBest.On("State").Return(nodeStateOutOfSync).Twice()
+ nodeSelector.On("Select").Return(newBest).Once()
+ newActiveNode, err := mn.selectNode()
+ require.NoError(t, err)
+ require.Equal(t, newBest.String(), newActiveNode.String())
+
+ })
+ t.Run("No active nodes - reports critical error", func(t *testing.T) {
+ t.Parallel()
+ chainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.InfoLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ logger: lggr,
+ })
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(nil).Once()
+ nodeSelector.On("Name").Return("MockedNodeSelector").Once()
+ mn.nodeSelector = nodeSelector
+ node, err := mn.selectNode()
+ require.EqualError(t, err, ErroringNodeError.Error())
+ require.Nil(t, node)
+ tests.RequireLogMessage(t, observedLogs, "No live RPC nodes available")
+
+ })
+}
+
+func TestMultiNode_nLiveNodes(t *testing.T) {
+ t.Parallel()
+ type nodeParams struct {
+ BlockNumber int64
+ TotalDifficulty *utils.Big
+ State nodeState
+ }
+ testCases := []struct {
+ Name string
+ ExpectedNLiveNodes int
+ ExpectedBlockNumber int64
+ ExpectedTotalDifficulty *utils.Big
+ NodeParams []nodeParams
+ }{
+ {
+ Name: "no nodes",
+ ExpectedTotalDifficulty: utils.NewBigI(0),
+ },
+ {
+ Name: "Best node is not healthy",
+ ExpectedTotalDifficulty: utils.NewBigI(10),
+ ExpectedBlockNumber: 20,
+ ExpectedNLiveNodes: 3,
+ NodeParams: []nodeParams{
+ {
+ State: nodeStateOutOfSync,
+ BlockNumber: 1000,
+ TotalDifficulty: utils.NewBigI(2000),
+ },
+ {
+ State: nodeStateAlive,
+ BlockNumber: 20,
+ TotalDifficulty: utils.NewBigI(9),
+ },
+ {
+ State: nodeStateAlive,
+ BlockNumber: 19,
+ TotalDifficulty: utils.NewBigI(10),
+ },
+ {
+ State: nodeStateAlive,
+ BlockNumber: 11,
+ TotalDifficulty: nil,
+ },
+ },
+ },
+ }
+
+ chainID := types.RandomID()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ })
+ for i := range testCases {
+ tc := testCases[i]
+ t.Run(tc.Name, func(t *testing.T) {
+ for _, params := range tc.NodeParams {
+ node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node.On("StateAndLatest").Return(params.State, params.BlockNumber, params.TotalDifficulty)
+ mn.nodes = append(mn.nodes, node)
+ }
+
+ nNodes, blockNum, td := mn.nLiveNodes()
+ assert.Equal(t, tc.ExpectedNLiveNodes, nNodes)
+ assert.Equal(t, tc.ExpectedTotalDifficulty, td)
+ assert.Equal(t, tc.ExpectedBlockNumber, blockNum)
+ })
+ }
+}
+
+func TestMultiNode_BatchCallContextAll(t *testing.T) {
+ t.Parallel()
+ t.Run("Fails if failed to select active node", func(t *testing.T) {
+ chainID := types.RandomID()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ })
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(nil).Once()
+ nodeSelector.On("Name").Return("MockedNodeSelector").Once()
+ mn.nodeSelector = nodeSelector
+ err := mn.BatchCallContextAll(tests.Context(t), nil)
+ require.EqualError(t, err, ErroringNodeError.Error())
+ })
+ t.Run("Returns error if RPC call fails for active node", func(t *testing.T) {
+ chainID := types.RandomID()
+ rpc := newMultiNodeRPCClient(t)
+ expectedError := errors.New("rpc failed to do the batch call")
+ rpc.On("BatchCallContext", mock.Anything, mock.Anything).Return(expectedError).Once()
+ node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node.On("RPC").Return(rpc)
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(node).Once()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ })
+ mn.nodeSelector = nodeSelector
+ err := mn.BatchCallContextAll(tests.Context(t), nil)
+ require.EqualError(t, err, expectedError.Error())
+ })
+ t.Run("Waits for all nodes to complete the call and logs results", func(t *testing.T) {
+ // setup RPCs
+ failedRPC := newMultiNodeRPCClient(t)
+ failedRPC.On("BatchCallContext", mock.Anything, mock.Anything).
+ Return(errors.New("rpc failed to do the batch call")).Once()
+ okRPC := newMultiNodeRPCClient(t)
+ okRPC.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Twice()
+
+ // setup ok and failed auxiliary nodes
+ okNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t)
+ okNode.On("RPC").Return(okRPC).Once()
+ failedNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ failedNode.On("RPC").Return(failedRPC).Once()
+
+ // setup main node
+ mainNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ mainNode.On("RPC").Return(okRPC)
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(mainNode).Once()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: types.RandomID(),
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{failedNode, mainNode},
+ sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{okNode},
+ logger: lggr,
+ })
+ mn.nodeSelector = nodeSelector
+
+ err := mn.BatchCallContextAll(tests.Context(t), nil)
+ require.NoError(t, err)
+ tests.RequireLogMessage(t, observedLogs, "Secondary node BatchCallContext failed")
+ })
+}
+
+func TestMultiNode_SendTransaction(t *testing.T) {
+ t.Parallel()
+ t.Run("Fails if failed to select active node", func(t *testing.T) {
+ chainID := types.RandomID()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ })
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(nil).Once()
+ nodeSelector.On("Name").Return("MockedNodeSelector").Once()
+ mn.nodeSelector = nodeSelector
+ err := mn.SendTransaction(tests.Context(t), nil)
+ require.EqualError(t, err, ErroringNodeError.Error())
+ })
+ t.Run("Returns error if RPC call fails for active node", func(t *testing.T) {
+ chainID := types.RandomID()
+ rpc := newMultiNodeRPCClient(t)
+ expectedError := errors.New("rpc failed to do the batch call")
+ rpc.On("SendTransaction", mock.Anything, mock.Anything).Return(expectedError).Once()
+ node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ node.On("RPC").Return(rpc)
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(node).Once()
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: chainID,
+ })
+ mn.nodeSelector = nodeSelector
+ err := mn.SendTransaction(tests.Context(t), nil)
+ require.EqualError(t, err, expectedError.Error())
+ })
+ t.Run("Returns result of main node and logs secondary nodes results", func(t *testing.T) {
+ // setup RPCs
+ failedRPC := newMultiNodeRPCClient(t)
+ failedRPC.On("SendTransaction", mock.Anything, mock.Anything).
+ Return(errors.New("rpc failed to do the batch call")).Once()
+ okRPC := newMultiNodeRPCClient(t)
+ okRPC.On("SendTransaction", mock.Anything, mock.Anything).Return(nil).Twice()
+
+ // setup ok and failed auxiliary nodes
+ okNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t)
+ okNode.On("RPC").Return(okRPC).Once()
+ okNode.On("String").Return("okNode")
+ failedNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ failedNode.On("RPC").Return(failedRPC).Once()
+ failedNode.On("String").Return("failedNode")
+
+ // setup main node
+ mainNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ mainNode.On("RPC").Return(okRPC)
+ nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t)
+ nodeSelector.On("Select").Return(mainNode).Once()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ mn := newTestMultiNode(t, multiNodeOpts{
+ selectionMode: NodeSelectionModeRoundRobin,
+ chainID: types.RandomID(),
+ nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{failedNode, mainNode},
+ sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{okNode},
+ logger: lggr,
+ sendOnlyErrorParser: func(err error) SendTxReturnCode {
+ if err != nil {
+ return Fatal
+ }
+
+ return Successful
+ },
+ })
+ mn.nodeSelector = nodeSelector
+
+ err := mn.SendTransaction(tests.Context(t), nil)
+ require.NoError(t, err)
+ tests.AssertLogEventually(t, observedLogs, "Sendonly node sent transaction")
+ tests.AssertLogEventually(t, observedLogs, "RPC returned error")
+ })
+}
diff --git a/common/client/node.go b/common/client/node.go
index 20d098e03f..f28a171a55 100644
--- a/common/client/node.go
+++ b/common/client/node.go
@@ -44,6 +44,7 @@ type NodeConfig interface {
SyncThreshold() uint32
}
+//go:generate mockery --quiet --name Node --structname mockNode --filename "mock_node_test.go" --inpackage --case=underscore
type Node[
CHAIN_ID types.ID,
HEAD Head,
@@ -177,19 +178,21 @@ func (n *node[CHAIN_ID, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() {
}
func (n *node[CHAIN_ID, HEAD, RPC]) Close() error {
- return n.StopOnce(n.name, func() error {
- defer func() {
- n.wg.Wait()
- n.rpc.Close()
- }()
+ return n.StopOnce(n.name, n.close)
+}
- n.stateMu.Lock()
- defer n.stateMu.Unlock()
+func (n *node[CHAIN_ID, HEAD, RPC]) close() error {
+ defer func() {
+ n.wg.Wait()
+ n.rpc.Close()
+ }()
- n.cancelNodeCtx()
- n.state = nodeStateClosed
- return nil
- })
+ n.stateMu.Lock()
+ defer n.stateMu.Unlock()
+
+ n.cancelNodeCtx()
+ n.state = nodeStateClosed
+ return nil
}
// Start dials and verifies the node
diff --git a/common/client/node_fsm_test.go b/common/client/node_fsm_test.go
new file mode 100644
index 0000000000..87e9084669
--- /dev/null
+++ b/common/client/node_fsm_test.go
@@ -0,0 +1,108 @@
+package client
+
+import (
+ "slices"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+type fnMock struct{ calls int }
+
+func (fm *fnMock) Fn() {
+ fm.calls++
+}
+
+func (fm *fnMock) AssertNotCalled(t *testing.T) {
+ assert.Equal(t, 0, fm.calls)
+}
+
+func (fm *fnMock) AssertCalled(t *testing.T) {
+ assert.Greater(t, fm.calls, 0)
+}
+
+func newTestTransitionNode(t *testing.T, rpc *mockNodeClient[types.ID, Head]) testNode {
+ return newTestNode(t, testNodeOpts{rpc: rpc})
+}
+
+func TestUnit_Node_StateTransitions(t *testing.T) {
+ t.Parallel()
+
+ t.Run("setState", func(t *testing.T) {
+ n := newTestTransitionNode(t, nil)
+ assert.Equal(t, nodeStateUndialed, n.State())
+ n.setState(nodeStateAlive)
+ assert.Equal(t, nodeStateAlive, n.State())
+ n.setState(nodeStateUndialed)
+ assert.Equal(t, nodeStateUndialed, n.State())
+ })
+
+ t.Run("transitionToAlive", func(t *testing.T) {
+ const destinationState = nodeStateAlive
+ allowedStates := []nodeState{nodeStateDialed, nodeStateInvalidChainID}
+ rpc := newMockNodeClient[types.ID, Head](t)
+ testTransition(t, rpc, testNode.transitionToAlive, destinationState, allowedStates...)
+ })
+
+ t.Run("transitionToInSync", func(t *testing.T) {
+ const destinationState = nodeStateAlive
+ allowedStates := []nodeState{nodeStateOutOfSync}
+ rpc := newMockNodeClient[types.ID, Head](t)
+ testTransition(t, rpc, testNode.transitionToInSync, destinationState, allowedStates...)
+ })
+ t.Run("transitionToOutOfSync", func(t *testing.T) {
+ const destinationState = nodeStateOutOfSync
+ allowedStates := []nodeState{nodeStateAlive}
+ rpc := newMockNodeClient[types.ID, Head](t)
+ rpc.On("DisconnectAll").Once()
+ testTransition(t, rpc, testNode.transitionToOutOfSync, destinationState, allowedStates...)
+ })
+ t.Run("transitionToUnreachable", func(t *testing.T) {
+ const destinationState = nodeStateUnreachable
+ allowedStates := []nodeState{nodeStateUndialed, nodeStateDialed, nodeStateAlive, nodeStateOutOfSync, nodeStateInvalidChainID}
+ rpc := newMockNodeClient[types.ID, Head](t)
+ rpc.On("DisconnectAll").Times(len(allowedStates))
+ testTransition(t, rpc, testNode.transitionToUnreachable, destinationState, allowedStates...)
+ })
+ t.Run("transitionToInvalidChain", func(t *testing.T) {
+ const destinationState = nodeStateInvalidChainID
+ allowedStates := []nodeState{nodeStateDialed, nodeStateOutOfSync}
+ rpc := newMockNodeClient[types.ID, Head](t)
+ rpc.On("DisconnectAll").Times(len(allowedStates))
+ testTransition(t, rpc, testNode.transitionToInvalidChainID, destinationState, allowedStates...)
+ })
+}
+
+func testTransition(t *testing.T, rpc *mockNodeClient[types.ID, Head], transition func(node testNode, fn func()), destinationState nodeState, allowedStates ...nodeState) {
+ node := newTestTransitionNode(t, rpc)
+ for _, allowedState := range allowedStates {
+ m := new(fnMock)
+ node.setState(allowedState)
+ transition(node, m.Fn)
+ assert.Equal(t, destinationState, node.State(), "Expected node to successfully transition from %s to %s state", allowedState, destinationState)
+ m.AssertCalled(t)
+ }
+ // noop on attempt to transition from Closed state
+ m := new(fnMock)
+ node.setState(nodeStateClosed)
+ transition(node, m.Fn)
+ m.AssertNotCalled(t)
+ assert.Equal(t, nodeStateClosed, node.State(), "Expected node to remain in closed state on transition attempt")
+
+ for _, nodeState := range allNodeStates {
+ if slices.Contains(allowedStates, nodeState) || nodeState == nodeStateClosed {
+ continue
+ }
+
+ m := new(fnMock)
+ node.setState(nodeState)
+ assert.Panics(t, func() {
+ transition(node, m.Fn)
+ }, "Expected transition from `%s` to `%s` to panic", nodeState, destinationState)
+ m.AssertNotCalled(t)
+ assert.Equal(t, nodeState, node.State(), "Expected node to remain in initial state on invalid transition")
+
+ }
+}
diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go
index 149c5f01a6..4193560e29 100644
--- a/common/client/node_lifecycle.go
+++ b/common/client/node_lifecycle.go
@@ -60,6 +60,8 @@ const (
msgDegradedState = "Chainlink is now operating in a degraded state and urgent action is required to resolve the issue"
)
+const rpcSubscriptionMethodNewHeads = "newHeads"
+
// Node is a FSM
// Each state has a loop that goes with it, which monitors the node and moves it into another state as necessary.
// Only one loop must run at a time.
@@ -90,12 +92,14 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() {
lggr.Tracew("Alive loop starting", "nodeState", n.State())
headsC := make(chan HEAD)
- sub, err := n.rpc.Subscribe(n.nodeCtx, headsC, "newHeads")
+ sub, err := n.rpc.Subscribe(n.nodeCtx, headsC, rpcSubscriptionMethodNewHeads)
if err != nil {
lggr.Errorw("Initial subscribe for heads failed", "nodeState", n.State())
n.declareUnreachable()
return
}
+ // TODO: nit fix. If multinode switches primary node before we set sub as AliveSub, sub will be closed and we'll
+ // falsely transition this node to unreachable state
n.rpc.SetAliveLoopSub(sub)
defer sub.Unsubscribe()
@@ -289,7 +293,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td
lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State())
ch := make(chan HEAD)
- sub, err := n.rpc.Subscribe(n.nodeCtx, ch, "newHeads")
+ sub, err := n.rpc.Subscribe(n.nodeCtx, ch, rpcSubscriptionMethodNewHeads)
if err != nil {
lggr.Errorw("Failed to subscribe heads on out-of-sync RPC node", "nodeState", n.State(), "err", err)
n.declareUnreachable()
@@ -310,11 +314,11 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td
n.setLatestReceived(head.BlockNumber(), head.BlockDifficulty())
if !isOutOfSync(head.BlockNumber(), head.BlockDifficulty()) {
// back in-sync! flip back into alive loop
- lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt)), "blockNumber", head.BlockNumber(), "totalDifficulty", "nodeState", n.State())
+ lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt)), "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.State())
n.declareInSync()
return
}
- lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "totalDifficulty", "nodeState", n.State())
+ lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.State())
case <-time.After(zombieNodeCheckInterval(n.noNewHeadsThreshold)):
if n.nLiveNodes != nil {
if l, _, _ := n.nLiveNodes(); l < 1 {
diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go
new file mode 100644
index 0000000000..564c08bbdc
--- /dev/null
+++ b/common/client/node_lifecycle_test.go
@@ -0,0 +1,1070 @@
+package client
+
+import (
+ "fmt"
+ "sync/atomic"
+ "testing"
+
+ "github.com/cometbft/cometbft/libs/rand"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "go.uber.org/zap"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) {
+ t.Parallel()
+
+ newDialedNode := func(t *testing.T, opts testNodeOpts) testNode {
+ node := newTestNode(t, opts)
+ opts.rpc.On("Close").Return(nil).Once()
+
+ node.setState(nodeStateDialed)
+ return node
+ }
+
+ t.Run("returns on closed", func(t *testing.T) {
+ node := newTestNode(t, testNodeOpts{})
+ node.setState(nodeStateClosed)
+ node.wg.Add(1)
+ node.aliveLoop()
+
+ })
+ t.Run("if initial subscribe fails, transitions to unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ node := newDialedNode(t, testNodeOpts{
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ expectedError := errors.New("failed to subscribe to rpc")
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(nil, expectedError).Once()
+ rpc.On("DisconnectAll").Once()
+ // might be called in unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareAlive()
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+
+ })
+ t.Run("if remote RPC connection is closed transitions to unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ node := newDialedNode(t, testNodeOpts{
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ sub := mocks.NewSubscription(t)
+ errChan := make(chan error)
+ close(errChan)
+ sub.On("Err").Return((<-chan error)(errChan)).Once()
+ sub.On("Unsubscribe").Once()
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once()
+ rpc.On("SetAliveLoopSub", sub).Once()
+ // disconnects all on transfer to unreachable
+ rpc.On("DisconnectAll").Once()
+ // might be called in unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, "Subscription was terminated")
+ assert.Equal(t, nodeStateUnreachable, node.State())
+ })
+
+ newSubscribedNode := func(t *testing.T, opts testNodeOpts) testNode {
+ sub := mocks.NewSubscription(t)
+ sub.On("Err").Return((<-chan error)(nil))
+ sub.On("Unsubscribe").Once()
+ opts.rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once()
+ opts.rpc.On("SetAliveLoopSub", sub).Once()
+ return newDialedNode(t, opts)
+ }
+ t.Run("Stays alive and waits for signal", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{},
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, "Head liveness checking disabled")
+ tests.AssertLogEventually(t, observedLogs, "Polling disabled")
+ assert.Equal(t, nodeStateAlive, node.State())
+ })
+ t.Run("stays alive while below pollFailureThreshold and resets counter on success", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ const pollFailureThreshold = 3
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{
+ pollFailureThreshold: pollFailureThreshold,
+ pollInterval: tests.TestInterval,
+ },
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ pollError := errors.New("failed to get ClientVersion")
+ // 1. Return error several times, but below threshold
+ rpc.On("ClientVersion", mock.Anything).Return("", pollError).Run(func(_ mock.Arguments) {
+ // stays healthy while below threshold
+ assert.Equal(t, nodeStateAlive, node.State())
+ }).Times(pollFailureThreshold - 1)
+ // 2. Successful call that is expected to reset counter
+ rpc.On("ClientVersion", mock.Anything).Return("client_version", nil).Once()
+ // 3. Return error. If we have not reset the timer, we'll transition to nonAliveState
+ rpc.On("ClientVersion", mock.Anything).Return("", pollError).Once()
+ // 4. Once during the call, check if node is alive
+ var ensuredAlive atomic.Bool
+ rpc.On("ClientVersion", mock.Anything).Return("client_version", nil).Run(func(_ mock.Arguments) {
+ if ensuredAlive.Load() {
+ return
+ }
+ ensuredAlive.Store(true)
+ assert.Equal(t, nodeStateAlive, node.State())
+ }).Once()
+ // redundant call to stay in alive state
+ rpc.On("ClientVersion", mock.Anything).Return("client_version", nil)
+ node.declareAlive()
+ tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", node.String()), pollFailureThreshold)
+ tests.AssertLogCountEventually(t, observedLogs, "Version poll successful", 2)
+ assert.True(t, ensuredAlive.Load(), "expected to ensure that node was alive")
+
+ })
+ t.Run("with threshold poll failures, transitions to unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ const pollFailureThreshold = 3
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{
+ pollFailureThreshold: pollFailureThreshold,
+ pollInterval: tests.TestInterval,
+ },
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ pollError := errors.New("failed to get ClientVersion")
+ rpc.On("ClientVersion", mock.Anything).Return("", pollError)
+ // disconnects all on transfer to unreachable
+ rpc.On("DisconnectAll").Once()
+ // might be called in unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareAlive()
+ tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", node.String()), pollFailureThreshold)
+ tests.AssertEventually(t, func() bool {
+ return nodeStateUnreachable == node.State()
+ })
+ })
+ t.Run("with threshold poll failures, but we are the last node alive, forcibly keeps it alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ const pollFailureThreshold = 3
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{
+ pollFailureThreshold: pollFailureThreshold,
+ pollInterval: tests.TestInterval,
+ },
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return 1, 20, utils.NewBigI(10)
+ }
+ pollError := errors.New("failed to get ClientVersion")
+ rpc.On("ClientVersion", mock.Anything).Return("", pollError)
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailureThreshold))
+ assert.Equal(t, nodeStateAlive, node.State())
+ })
+ t.Run("when behind more than SyncThreshold, transitions to out of sync", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ const syncThreshold = 10
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{
+ pollInterval: tests.TestInterval,
+ syncThreshold: syncThreshold,
+ selectionMode: NodeSelectionModeRoundRobin,
+ },
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.stateLatestBlockNumber = 20
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return 10, syncThreshold + node.stateLatestBlockNumber + 1, utils.NewBigI(10)
+ }
+ rpc.On("ClientVersion", mock.Anything).Return("", nil)
+ // tries to redial in outOfSync
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) {
+ assert.Equal(t, nodeStateOutOfSync, node.State())
+ }).Once()
+ // disconnects all on transfer to unreachable or outOfSync
+ rpc.On("DisconnectAll").Maybe()
+ // might be called in unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, "Failed to dial out-of-sync RPC node")
+ })
+ t.Run("when behind more than SyncThreshold but we are the last live node, forcibly stays alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ const syncThreshold = 10
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{
+ pollInterval: tests.TestInterval,
+ syncThreshold: syncThreshold,
+ selectionMode: NodeSelectionModeRoundRobin,
+ },
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.stateLatestBlockNumber = 20
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return 1, syncThreshold + node.stateLatestBlockNumber + 1, utils.NewBigI(10)
+ }
+ rpc.On("ClientVersion", mock.Anything).Return("", nil)
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState))
+ })
+ t.Run("when behind but SyncThreshold=0, stay alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{
+ pollInterval: tests.TestInterval,
+ syncThreshold: 0,
+ selectionMode: NodeSelectionModeRoundRobin,
+ },
+ rpc: rpc,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.stateLatestBlockNumber = 20
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return 1, node.stateLatestBlockNumber + 100, utils.NewBigI(10)
+ }
+ rpc.On("ClientVersion", mock.Anything).Return("", nil)
+ node.declareAlive()
+ tests.AssertLogCountEventually(t, observedLogs, "Version poll successful", 2)
+ assert.Equal(t, nodeStateAlive, node.State())
+ })
+
+ t.Run("when no new heads received for threshold, transitions to out of sync", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{},
+ noNewHeadsThreshold: tests.TestInterval,
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ // tries to redial in outOfSync
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) {
+ assert.Equal(t, nodeStateOutOfSync, node.State())
+ }).Once()
+ // disconnects all on transfer to unreachable or outOfSync
+ rpc.On("DisconnectAll").Maybe()
+ // might be called in unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareAlive()
+ tests.AssertEventually(t, func() bool {
+ // right after outOfSync we'll transfer to unreachable due to returned error on Dial
+ // we check that we were in out of sync state on first Dial call
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("when no new heads received for threshold but we are the last live node, forcibly stays alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newSubscribedNode(t, testNodeOpts{
+ config: testNodeConfig{},
+ lggr: lggr,
+ noNewHeadsThreshold: tests.TestInterval,
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return 1, 20, utils.NewBigI(10)
+ }
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState))
+ assert.Equal(t, nodeStateAlive, node.State())
+ })
+
+ t.Run("rpc closed head channel", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ sub := mocks.NewSubscription(t)
+ sub.On("Err").Return((<-chan error)(nil))
+ sub.On("Unsubscribe").Once()
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) {
+ ch := args.Get(1).(chan<- Head)
+ close(ch)
+ }).Return(sub, nil).Once()
+ rpc.On("SetAliveLoopSub", sub).Once()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.ErrorLevel)
+ node := newDialedNode(t, testNodeOpts{
+ lggr: lggr,
+ config: testNodeConfig{},
+ noNewHeadsThreshold: tests.TestInterval,
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ // disconnects all on transfer to unreachable or outOfSync
+ rpc.On("DisconnectAll").Once()
+ // might be called in unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareAlive()
+ tests.AssertLogEventually(t, observedLogs, "Subscription channel unexpectedly closed")
+ assert.Equal(t, nodeStateUnreachable, node.State())
+
+ })
+ t.Run("updates block number and difficulty on new head", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ sub := mocks.NewSubscription(t)
+ sub.On("Err").Return((<-chan error)(nil))
+ sub.On("Unsubscribe").Once()
+ expectedBlockNumber := rand.Int64()
+ expectedDiff := utils.NewBigI(rand.Int64())
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) {
+ ch := args.Get(1).(chan<- Head)
+ go writeHeads(t, ch, head{BlockNumber: expectedBlockNumber, BlockDifficulty: expectedDiff})
+ }).Return(sub, nil).Once()
+ rpc.On("SetAliveLoopSub", sub).Once()
+ node := newDialedNode(t, testNodeOpts{
+ config: testNodeConfig{},
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.declareAlive()
+ tests.AssertEventually(t, func() bool {
+ state, block, diff := node.StateAndLatest()
+ return state == nodeStateAlive && block == expectedBlockNumber == diff.Equal(expectedDiff)
+ })
+ })
+}
+
+type head struct {
+ BlockNumber int64
+ BlockDifficulty *utils.Big
+}
+
+func writeHeads(t *testing.T, ch chan<- Head, heads ...head) {
+ for _, head := range heads {
+ h := newMockHead(t)
+ h.On("BlockNumber").Return(head.BlockNumber)
+ h.On("BlockDifficulty").Return(head.BlockDifficulty)
+ select {
+ case ch <- h:
+ case <-tests.Context(t).Done():
+ return
+ }
+ }
+}
+
+func setupRPCForAliveLoop(t *testing.T, rpc *mockNodeClient[types.ID, Head]) {
+ rpc.On("Dial", mock.Anything).Return(nil).Maybe()
+ aliveSubscription := mocks.NewSubscription(t)
+ aliveSubscription.On("Err").Return((<-chan error)(nil)).Maybe()
+ aliveSubscription.On("Unsubscribe").Maybe()
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(aliveSubscription, nil).Maybe()
+ rpc.On("SetAliveLoopSub", mock.Anything).Maybe()
+}
+
+func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) {
+ t.Parallel()
+
+ newAliveNode := func(t *testing.T, opts testNodeOpts) testNode {
+ node := newTestNode(t, opts)
+ opts.rpc.On("Close").Return(nil).Once()
+ // disconnects all on transfer to unreachable or outOfSync
+ opts.rpc.On("DisconnectAll")
+ node.setState(nodeStateAlive)
+ return node
+ }
+
+ stubIsOutOfSync := func(num int64, td *utils.Big) bool {
+ return false
+ }
+
+ t.Run("returns on closed", func(t *testing.T) {
+ t.Parallel()
+ node := newTestNode(t, testNodeOpts{})
+ node.setState(nodeStateClosed)
+ node.wg.Add(1)
+ node.outOfSyncLoop(stubIsOutOfSync)
+ })
+ t.Run("on old blocks stays outOfSync and returns on close", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once()
+
+ outOfSyncSubscription := mocks.NewSubscription(t)
+ outOfSyncSubscription.On("Err").Return((<-chan error)(nil))
+ outOfSyncSubscription.On("Unsubscribe").Once()
+ heads := []head{{BlockNumber: 7}, {BlockNumber: 11}, {BlockNumber: 13}}
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) {
+ ch := args.Get(1).(chan<- Head)
+ go writeHeads(t, ch, heads...)
+ }).Return(outOfSyncSubscription, nil).Once()
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe()
+
+ node.declareOutOfSync(func(num int64, td *utils.Big) bool {
+ return true
+ })
+ tests.AssertLogCountEventually(t, observedLogs, msgReceivedBlock, len(heads))
+ assert.Equal(t, nodeStateOutOfSync, node.State())
+ })
+ t.Run("if initial dial fails, transitions to unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ expectedError := errors.New("failed to dial rpc")
+ // might be called again in unreachable loop, so no need to set once
+ rpc.On("Dial", mock.Anything).Return(expectedError)
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("if fail to get chainID, transitions to invalidChainID", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ expectedError := errors.New("failed to get chain ID")
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(types.NewIDFromInt(0), expectedError)
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateInvalidChainID
+ })
+ })
+ t.Run("if chainID does not match, transitions to invalidChainID", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.NewIDFromInt(10)
+ rpcChainID := types.NewIDFromInt(11)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil)
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateInvalidChainID
+ })
+ })
+ t.Run("if fails to subscribe, becomes unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once()
+ expectedError := errors.New("failed to subscribe")
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(nil, expectedError)
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe()
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("on subscription termination becomes unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.ErrorLevel)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once()
+
+ sub := mocks.NewSubscription(t)
+ errChan := make(chan error, 1)
+ errChan <- errors.New("subscription was terminate")
+ sub.On("Err").Return((<-chan error)(errChan))
+ sub.On("Unsubscribe").Once()
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once()
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe()
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertLogEventually(t, observedLogs, "Subscription was terminated")
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("becomes unreachable if head channel is closed", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.ErrorLevel)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once()
+
+ sub := mocks.NewSubscription(t)
+ sub.On("Err").Return((<-chan error)(nil))
+ sub.On("Unsubscribe").Once()
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) {
+ ch := args.Get(1).(chan<- Head)
+ close(ch)
+ }).Return(sub, nil).Once()
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe()
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertLogEventually(t, observedLogs, "Subscription channel unexpectedly closed")
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+
+ t.Run("becomes alive if it receives a newer head", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once()
+
+ outOfSyncSubscription := mocks.NewSubscription(t)
+ outOfSyncSubscription.On("Err").Return((<-chan error)(nil))
+ outOfSyncSubscription.On("Unsubscribe").Once()
+ const highestBlock = 1000
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) {
+ ch := args.Get(1).(chan<- Head)
+ go writeHeads(t, ch, head{BlockNumber: highestBlock - 1}, head{BlockNumber: highestBlock})
+ }).Return(outOfSyncSubscription, nil).Once()
+
+ setupRPCForAliveLoop(t, rpc)
+
+ node.declareOutOfSync(func(num int64, td *utils.Big) bool {
+ return num < highestBlock
+ })
+ tests.AssertLogEventually(t, observedLogs, msgReceivedBlock)
+ tests.AssertLogEventually(t, observedLogs, msgInSync)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateAlive
+ })
+ })
+ t.Run("becomes alive if there is no other nodes", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newAliveNode(t, testNodeOpts{
+ noNewHeadsThreshold: tests.TestInterval,
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return 0, 100, utils.NewBigI(200)
+ }
+
+ rpc.On("Dial", mock.Anything).Return(nil).Once()
+ // might be called multiple times
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once()
+
+ outOfSyncSubscription := mocks.NewSubscription(t)
+ outOfSyncSubscription.On("Err").Return((<-chan error)(nil))
+ outOfSyncSubscription.On("Unsubscribe").Once()
+ rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(outOfSyncSubscription, nil).Once()
+
+ setupRPCForAliveLoop(t, rpc)
+
+ node.declareOutOfSync(stubIsOutOfSync)
+ tests.AssertLogEventually(t, observedLogs, "RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state")
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateAlive
+ })
+ })
+}
+
+func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) {
+ t.Parallel()
+
+ newAliveNode := func(t *testing.T, opts testNodeOpts) testNode {
+ node := newTestNode(t, opts)
+ opts.rpc.On("Close").Return(nil).Once()
+ // disconnects all on transfer to unreachable
+ opts.rpc.On("DisconnectAll")
+
+ node.setState(nodeStateAlive)
+ return node
+ }
+ t.Run("returns on closed", func(t *testing.T) {
+ t.Parallel()
+ node := newTestNode(t, testNodeOpts{})
+ node.setState(nodeStateClosed)
+ node.wg.Add(1)
+ node.unreachableLoop()
+
+ })
+ t.Run("on failed redial, keeps trying", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial"))
+ node.declareUnreachable()
+ tests.AssertLogCountEventually(t, observedLogs, "Failed to redial RPC node; still unreachable", 2)
+ })
+ t.Run("on failed chainID verification, keep trying", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil)
+ rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) {
+ assert.Equal(t, nodeStateDialed, node.State())
+ }).Return(nodeChainID, errors.New("failed to get chain id"))
+ node.declareUnreachable()
+ tests.AssertLogCountEventually(t, observedLogs, "Failed to redial RPC node; verify failed", 2)
+ })
+ t.Run("on chain ID mismatch transitions to invalidChainID", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.NewIDFromInt(10)
+ rpcChainID := types.NewIDFromInt(11)
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil)
+ rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil)
+ node.declareUnreachable()
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateInvalidChainID
+ })
+ })
+ t.Run("on valid chain ID becomes alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ node := newAliveNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil)
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil)
+
+ setupRPCForAliveLoop(t, rpc)
+
+ node.declareUnreachable()
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateAlive
+ })
+ })
+}
+
+func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) {
+ t.Parallel()
+ newDialedNode := func(t *testing.T, opts testNodeOpts) testNode {
+ node := newTestNode(t, opts)
+ opts.rpc.On("Close").Return(nil).Once()
+ opts.rpc.On("DisconnectAll")
+
+ node.setState(nodeStateDialed)
+ return node
+ }
+ t.Run("returns on closed", func(t *testing.T) {
+ t.Parallel()
+ node := newTestNode(t, testNodeOpts{})
+ node.setState(nodeStateClosed)
+ node.wg.Add(1)
+ node.invalidChainIDLoop()
+
+ })
+ t.Run("on failed chainID call becomes unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newDialedNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, errors.New("failed to get chain id"))
+ // for unreachable loop
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe()
+ node.declareInvalidChainID()
+ tests.AssertLogEventually(t, observedLogs, "Unexpected error while verifying RPC node chain ID")
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("on chainID mismatch keeps trying", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.NewIDFromInt(10)
+ rpcChainID := types.NewIDFromInt(11)
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newDialedNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil)
+ node.declareInvalidChainID()
+ tests.AssertLogCountEventually(t, observedLogs, "Failed to verify RPC node; remote endpoint returned the wrong chain ID", 2)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateInvalidChainID
+ })
+ })
+ t.Run("on valid chainID becomes alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ node := newDialedNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil)
+
+ setupRPCForAliveLoop(t, rpc)
+
+ node.declareInvalidChainID()
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateAlive
+ })
+ })
+}
+
+func TestUnit_NodeLifecycle_start(t *testing.T) {
+ t.Parallel()
+
+ newNode := func(t *testing.T, opts testNodeOpts) testNode {
+ node := newTestNode(t, opts)
+ opts.rpc.On("Close").Return(nil).Once()
+
+ return node
+ }
+ t.Run("if fails on initial dial, becomes unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial"))
+ // disconnects all on transfer to unreachable
+ rpc.On("DisconnectAll")
+ err := node.Start(tests.Context(t))
+ assert.NoError(t, err)
+ tests.AssertLogEventually(t, observedLogs, "Dial failed: Node is unreachable")
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("if chainID verification fails, becomes unreachable", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.DebugLevel)
+ node := newNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ lggr: lggr,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil)
+ rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) {
+ assert.Equal(t, nodeStateDialed, node.State())
+ }).Return(nodeChainID, errors.New("failed to get chain id"))
+ // disconnects all on transfer to unreachable
+ rpc.On("DisconnectAll")
+ err := node.Start(tests.Context(t))
+ assert.NoError(t, err)
+ tests.AssertLogEventually(t, observedLogs, "Verify failed")
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateUnreachable
+ })
+ })
+ t.Run("on chain ID mismatch transitions to invalidChainID", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.NewIDFromInt(10)
+ rpcChainID := types.NewIDFromInt(11)
+ node := newNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil)
+ rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil)
+ // disconnects all on transfer to unreachable
+ rpc.On("DisconnectAll")
+ err := node.Start(tests.Context(t))
+ assert.NoError(t, err)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateInvalidChainID
+ })
+ })
+ t.Run("on valid chain ID becomes alive", func(t *testing.T) {
+ t.Parallel()
+ rpc := newMockNodeClient[types.ID, Head](t)
+ nodeChainID := types.RandomID()
+ node := newNode(t, testNodeOpts{
+ rpc: rpc,
+ chainID: nodeChainID,
+ })
+ defer func() { assert.NoError(t, node.close()) }()
+
+ rpc.On("Dial", mock.Anything).Return(nil)
+ rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil)
+
+ setupRPCForAliveLoop(t, rpc)
+
+ err := node.Start(tests.Context(t))
+ assert.NoError(t, err)
+ tests.AssertEventually(t, func() bool {
+ return node.State() == nodeStateAlive
+ })
+ })
+}
+
+func TestUnit_NodeLifecycle_syncStatus(t *testing.T) {
+ t.Parallel()
+ t.Run("skip if nLiveNodes is not configured", func(t *testing.T) {
+ node := newTestNode(t, testNodeOpts{})
+ outOfSync, liveNodes := node.syncStatus(0, nil)
+ assert.Equal(t, false, outOfSync)
+ assert.Equal(t, 0, liveNodes)
+ })
+ t.Run("skip if syncThreshold is not configured", func(t *testing.T) {
+ node := newTestNode(t, testNodeOpts{})
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return
+ }
+ outOfSync, liveNodes := node.syncStatus(0, nil)
+ assert.Equal(t, false, outOfSync)
+ assert.Equal(t, 0, liveNodes)
+ })
+ t.Run("panics on invalid selection mode", func(t *testing.T) {
+ node := newTestNode(t, testNodeOpts{
+ config: testNodeConfig{syncThreshold: 1},
+ })
+ node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) {
+ return
+ }
+ assert.Panics(t, func() {
+ _, _ = node.syncStatus(0, nil)
+ })
+ })
+ t.Run("block height selection mode", func(t *testing.T) {
+ const syncThreshold = 10
+ const highestBlock = 1000
+ const nodesNum = 20
+ const totalDifficulty = 3000
+ testCases := []struct {
+ name string
+ blockNumber int64
+ outOfSync bool
+ }{
+ {
+ name: "below threshold",
+ blockNumber: highestBlock - syncThreshold - 1,
+ outOfSync: true,
+ },
+ {
+ name: "equal to threshold",
+ blockNumber: highestBlock - syncThreshold,
+ outOfSync: false,
+ },
+ {
+ name: "equal to highest block",
+ blockNumber: highestBlock,
+ outOfSync: false,
+ },
+ {
+ name: "higher than highest block",
+ blockNumber: highestBlock,
+ outOfSync: false,
+ },
+ }
+
+ for _, selectionMode := range []string{NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel} {
+ node := newTestNode(t, testNodeOpts{
+ config: testNodeConfig{
+ syncThreshold: syncThreshold,
+ selectionMode: selectionMode,
+ },
+ })
+ node.nLiveNodes = func() (int, int64, *utils.Big) {
+ return nodesNum, highestBlock, utils.NewBigI(totalDifficulty)
+ }
+ for _, td := range []int64{totalDifficulty - syncThreshold - 1, totalDifficulty - syncThreshold, totalDifficulty, totalDifficulty + 1} {
+ for _, testCase := range testCases {
+ t.Run(fmt.Sprintf("%s: selectionMode: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) {
+ outOfSync, liveNodes := node.syncStatus(testCase.blockNumber, utils.NewBigI(td))
+ assert.Equal(t, nodesNum, liveNodes)
+ assert.Equal(t, testCase.outOfSync, outOfSync)
+ })
+ }
+ }
+ }
+
+ })
+ t.Run("total difficulty selection mode", func(t *testing.T) {
+ const syncThreshold = 10
+ const highestBlock = 1000
+ const nodesNum = 20
+ const totalDifficulty = 3000
+ testCases := []struct {
+ name string
+ totalDifficulty int64
+ outOfSync bool
+ }{
+ {
+ name: "below threshold",
+ totalDifficulty: totalDifficulty - syncThreshold - 1,
+ outOfSync: true,
+ },
+ {
+ name: "equal to threshold",
+ totalDifficulty: totalDifficulty - syncThreshold,
+ outOfSync: false,
+ },
+ {
+ name: "equal to highest block",
+ totalDifficulty: totalDifficulty,
+ outOfSync: false,
+ },
+ {
+ name: "higher than highest block",
+ totalDifficulty: totalDifficulty,
+ outOfSync: false,
+ },
+ }
+
+ node := newTestNode(t, testNodeOpts{
+ config: testNodeConfig{
+ syncThreshold: syncThreshold,
+ selectionMode: NodeSelectionModeTotalDifficulty,
+ },
+ })
+ node.nLiveNodes = func() (int, int64, *utils.Big) {
+ return nodesNum, highestBlock, utils.NewBigI(totalDifficulty)
+ }
+ for _, hb := range []int64{highestBlock - syncThreshold - 1, highestBlock - syncThreshold, highestBlock, highestBlock + 1} {
+ for _, testCase := range testCases {
+ t.Run(fmt.Sprintf("%s: selectionMode: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) {
+ outOfSync, liveNodes := node.syncStatus(hb, utils.NewBigI(testCase.totalDifficulty))
+ assert.Equal(t, nodesNum, liveNodes)
+ assert.Equal(t, testCase.outOfSync, outOfSync)
+ })
+ }
+ }
+
+ })
+}
diff --git a/common/client/node_selector.go b/common/client/node_selector.go
new file mode 100644
index 0000000000..45604ebe8d
--- /dev/null
+++ b/common/client/node_selector.go
@@ -0,0 +1,46 @@
+package client
+
+import (
+ "fmt"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+const (
+ NodeSelectionModeHighestHead = "HighestHead"
+ NodeSelectionModeRoundRobin = "RoundRobin"
+ NodeSelectionModeTotalDifficulty = "TotalDifficulty"
+ NodeSelectionModePriorityLevel = "PriorityLevel"
+)
+
+//go:generate mockery --quiet --name NodeSelector --structname mockNodeSelector --filename "mock_node_selector_test.go" --inpackage --case=underscore
+type NodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+] interface {
+ // Select returns a Node, or nil if none can be selected.
+ // Implementation must be thread-safe.
+ Select() Node[CHAIN_ID, HEAD, RPC]
+ // Name returns the strategy name, e.g. "HighestHead" or "RoundRobin"
+ Name() string
+}
+
+func newNodeSelector[
+ CHAIN_ID types.ID,
+ HEAD Head,
+ RPC NodeClient[CHAIN_ID, HEAD],
+](selectionMode string, nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] {
+ switch selectionMode {
+ case NodeSelectionModeHighestHead:
+ return NewHighestHeadNodeSelector[CHAIN_ID, HEAD, RPC](nodes)
+ case NodeSelectionModeRoundRobin:
+ return NewRoundRobinSelector[CHAIN_ID, HEAD, RPC](nodes)
+ case NodeSelectionModeTotalDifficulty:
+ return NewTotalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC](nodes)
+ case NodeSelectionModePriorityLevel:
+ return NewPriorityLevelNodeSelector[CHAIN_ID, HEAD, RPC](nodes)
+ default:
+ panic(fmt.Sprintf("unsupported NodeSelectionMode: %s", selectionMode))
+ }
+}
diff --git a/common/client/node_selector_highest_head_test.go b/common/client/node_selector_highest_head_test.go
new file mode 100644
index 0000000000..6e47bbedca
--- /dev/null
+++ b/common/client/node_selector_highest_head_test.go
@@ -0,0 +1,176 @@
+package client
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+func TestHighestHeadNodeSelectorName(t *testing.T) {
+ selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModeHighestHead, nil)
+ assert.Equal(t, selector.Name(), NodeSelectionModeHighestHead)
+}
+
+func TestHighestHeadNodeSelector(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil)
+ } else if i == 1 {
+ // second node is alive, LatestReceivedBlockNumber = 1
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(1), nil)
+ } else {
+ // third node is alive, LatestReceivedBlockNumber = 2 (best node)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(2), nil)
+ }
+ node.On("Order").Maybe().Return(int32(1))
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector[types.ID, Head, nodeClient](NodeSelectionModeHighestHead, nodes)
+ assert.Same(t, nodes[2], selector.Select())
+
+ t.Run("stick to the same node", func(t *testing.T) {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ // fourth node is alive, LatestReceivedBlockNumber = 2 (same as 3rd)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(2), nil)
+ node.On("Order").Return(int32(1))
+ nodes = append(nodes, node)
+
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ assert.Same(t, nodes[2], selector.Select())
+ })
+
+ t.Run("another best node", func(t *testing.T) {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ // fifth node is alive, LatestReceivedBlockNumber = 3 (better than 3rd and 4th)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil)
+ node.On("Order").Return(int32(1))
+ nodes = append(nodes, node)
+
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ assert.Same(t, nodes[4], selector.Select())
+ })
+
+ t.Run("nodes never update latest block number", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil)
+ node1.On("Order").Return(int32(1))
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil)
+ node2.On("Order").Return(int32(1))
+ selector := newNodeSelector(NodeSelectionModeHighestHead, []Node[types.ID, Head, nodeClient]{node1, node2})
+ assert.Same(t, node1, selector.Select())
+ })
+}
+
+func TestHighestHeadNodeSelector_None(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil)
+ } else {
+ // others are unreachable
+ node.On("StateAndLatest").Return(nodeStateUnreachable, int64(1), nil)
+ }
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ assert.Nil(t, selector.Select())
+}
+
+func TestHighestHeadNodeSelectorWithOrder(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ t.Run("same head and order", func(t *testing.T) {
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(1), nil)
+ node.On("Order").Return(int32(2))
+ nodes = append(nodes, node)
+ }
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ //Should select the first node because all things are equal
+ assert.Same(t, nodes[0], selector.Select())
+ })
+
+ t.Run("same head but different order", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil)
+ node1.On("Order").Return(int32(3))
+
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil)
+ node2.On("Order").Return(int32(1))
+
+ node3 := newMockNode[types.ID, Head, nodeClient](t)
+ node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil)
+ node3.On("Order").Return(int32(2))
+
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3}
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ //Should select the second node as it has the highest priority
+ assert.Same(t, nodes[1], selector.Select())
+ })
+
+ t.Run("different head but same order", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), nil)
+ node1.On("Order").Maybe().Return(int32(3))
+
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(2), nil)
+ node2.On("Order").Maybe().Return(int32(3))
+
+ node3 := newMockNode[types.ID, Head, nodeClient](t)
+ node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil)
+ node3.On("Order").Return(int32(3))
+
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3}
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ //Should select the third node as it has the highest head
+ assert.Same(t, nodes[2], selector.Select())
+ })
+
+ t.Run("different head and different order", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(10), nil)
+ node1.On("Order").Maybe().Return(int32(3))
+
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(11), nil)
+ node2.On("Order").Maybe().Return(int32(4))
+
+ node3 := newMockNode[types.ID, Head, nodeClient](t)
+ node3.On("StateAndLatest").Return(nodeStateAlive, int64(11), nil)
+ node3.On("Order").Maybe().Return(int32(3))
+
+ node4 := newMockNode[types.ID, Head, nodeClient](t)
+ node4.On("StateAndLatest").Return(nodeStateAlive, int64(10), nil)
+ node4.On("Order").Maybe().Return(int32(1))
+
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3, node4}
+ selector := newNodeSelector(NodeSelectionModeHighestHead, nodes)
+ //Should select the third node as it has the highest head and will win the priority tie-breaker
+ assert.Same(t, nodes[2], selector.Select())
+ })
+}
diff --git a/common/client/node_selector_priority_level_test.go b/common/client/node_selector_priority_level_test.go
new file mode 100644
index 0000000000..ac84645e91
--- /dev/null
+++ b/common/client/node_selector_priority_level_test.go
@@ -0,0 +1,88 @@
+package client
+
+import (
+ "testing"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPriorityLevelNodeSelectorName(t *testing.T) {
+ selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModePriorityLevel, nil)
+ assert.Equal(t, selector.Name(), NodeSelectionModePriorityLevel)
+}
+
+func TestPriorityLevelNodeSelector(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+ n1 := newMockNode[types.ID, Head, nodeClient](t)
+ n1.On("State").Return(nodeStateAlive)
+ n1.On("Order").Return(int32(1))
+
+ n2 := newMockNode[types.ID, Head, nodeClient](t)
+ n2.On("State").Return(nodeStateAlive)
+ n2.On("Order").Return(int32(1))
+
+ n3 := newMockNode[types.ID, Head, nodeClient](t)
+ n3.On("State").Return(nodeStateAlive)
+ n3.On("Order").Return(int32(1))
+
+ nodes = append(nodes, n1, n2, n3)
+ selector := newNodeSelector(NodeSelectionModePriorityLevel, nodes)
+ assert.Same(t, nodes[0], selector.Select())
+ assert.Same(t, nodes[1], selector.Select())
+ assert.Same(t, nodes[2], selector.Select())
+ assert.Same(t, nodes[0], selector.Select())
+ assert.Same(t, nodes[1], selector.Select())
+ assert.Same(t, nodes[2], selector.Select())
+}
+
+func TestPriorityLevelNodeSelector_None(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("State").Return(nodeStateOutOfSync)
+ node.On("Order").Return(int32(1))
+ } else {
+ // others are unreachable
+ node.On("State").Return(nodeStateUnreachable)
+ node.On("Order").Return(int32(1))
+ }
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector(NodeSelectionModePriorityLevel, nodes)
+ assert.Nil(t, selector.Select())
+}
+
+func TestPriorityLevelNodeSelector_DifferentOrder(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+ n1 := newMockNode[types.ID, Head, nodeClient](t)
+ n1.On("State").Return(nodeStateAlive)
+ n1.On("Order").Return(int32(1))
+
+ n2 := newMockNode[types.ID, Head, nodeClient](t)
+ n2.On("State").Return(nodeStateAlive)
+ n2.On("Order").Return(int32(2))
+
+ n3 := newMockNode[types.ID, Head, nodeClient](t)
+ n3.On("State").Return(nodeStateAlive)
+ n3.On("Order").Return(int32(3))
+
+ nodes = append(nodes, n1, n2, n3)
+ selector := newNodeSelector(NodeSelectionModePriorityLevel, nodes)
+ assert.Same(t, nodes[0], selector.Select())
+ assert.Same(t, nodes[0], selector.Select())
+}
diff --git a/common/client/node_selector_round_robin_test.go b/common/client/node_selector_round_robin_test.go
new file mode 100644
index 0000000000..e5078d858f
--- /dev/null
+++ b/common/client/node_selector_round_robin_test.go
@@ -0,0 +1,61 @@
+package client
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+func TestRoundRobinNodeSelectorName(t *testing.T) {
+ selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModeRoundRobin, nil)
+ assert.Equal(t, selector.Name(), NodeSelectionModeRoundRobin)
+}
+
+func TestRoundRobinNodeSelector(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("State").Return(nodeStateOutOfSync)
+ } else {
+ // second & third nodes are alive
+ node.On("State").Return(nodeStateAlive)
+ }
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector(NodeSelectionModeRoundRobin, nodes)
+ assert.Same(t, nodes[1], selector.Select())
+ assert.Same(t, nodes[2], selector.Select())
+ assert.Same(t, nodes[1], selector.Select())
+ assert.Same(t, nodes[2], selector.Select())
+}
+
+func TestRoundRobinNodeSelector_None(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("State").Return(nodeStateOutOfSync)
+ } else {
+ // others are unreachable
+ node.On("State").Return(nodeStateUnreachable)
+ }
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector(NodeSelectionModeRoundRobin, nodes)
+ assert.Nil(t, selector.Select())
+}
diff --git a/common/client/node_selector_test.go b/common/client/node_selector_test.go
new file mode 100644
index 0000000000..226cb67168
--- /dev/null
+++ b/common/client/node_selector_test.go
@@ -0,0 +1,18 @@
+package client
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+)
+
+func TestNodeSelector(t *testing.T) {
+ // rest of the tests are located in specific node selectors tests
+ t.Run("panics on unknown type", func(t *testing.T) {
+ assert.Panics(t, func() {
+ _ = newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]]("unknown", nil)
+ })
+ })
+}
diff --git a/common/client/node_selector_total_difficulty_test.go b/common/client/node_selector_total_difficulty_test.go
new file mode 100644
index 0000000000..4eecb859db
--- /dev/null
+++ b/common/client/node_selector_total_difficulty_test.go
@@ -0,0 +1,178 @@
+package client
+
+import (
+ "testing"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestTotalDifficultyNodeSelectorName(t *testing.T) {
+ selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModeTotalDifficulty, nil)
+ assert.Equal(t, selector.Name(), NodeSelectionModeTotalDifficulty)
+}
+
+func TestTotalDifficultyNodeSelector(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil)
+ } else if i == 1 {
+ // second node is alive
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(7))
+ } else {
+ // third node is alive and best
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(2), utils.NewBigI(8))
+ }
+ node.On("Order").Maybe().Return(int32(1))
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ assert.Same(t, nodes[2], selector.Select())
+
+ t.Run("stick to the same node", func(t *testing.T) {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ // fourth node is alive (same as 3rd)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(2), utils.NewBigI(8))
+ node.On("Order").Maybe().Return(int32(1))
+ nodes = append(nodes, node)
+
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ assert.Same(t, nodes[2], selector.Select())
+ })
+
+ t.Run("another best node", func(t *testing.T) {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ // fifth node is alive (better than 3rd and 4th)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(11))
+ node.On("Order").Maybe().Return(int32(1))
+ nodes = append(nodes, node)
+
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ assert.Same(t, nodes[4], selector.Select())
+ })
+
+ t.Run("nodes never update latest block number", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil)
+ node1.On("Order").Maybe().Return(int32(1))
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil)
+ node2.On("Order").Maybe().Return(int32(1))
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2}
+
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ assert.Same(t, node1, selector.Select())
+ })
+}
+
+func TestTotalDifficultyNodeSelector_None(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ if i == 0 {
+ // first node is out of sync
+ node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil)
+ } else {
+ // others are unreachable
+ node.On("StateAndLatest").Return(nodeStateUnreachable, int64(1), utils.NewBigI(7))
+ }
+ nodes = append(nodes, node)
+ }
+
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ assert.Nil(t, selector.Select())
+}
+
+func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) {
+ t.Parallel()
+
+ type nodeClient NodeClient[types.ID, Head]
+ var nodes []Node[types.ID, Head, nodeClient]
+
+ t.Run("same td and order", func(t *testing.T) {
+ for i := 0; i < 3; i++ {
+ node := newMockNode[types.ID, Head, nodeClient](t)
+ node.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(10))
+ node.On("Order").Return(int32(2))
+ nodes = append(nodes, node)
+ }
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ //Should select the first node because all things are equal
+ assert.Same(t, nodes[0], selector.Select())
+ })
+
+ t.Run("same td but different order", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(10))
+ node1.On("Order").Return(int32(3))
+
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(10))
+ node2.On("Order").Return(int32(1))
+
+ node3 := newMockNode[types.ID, Head, nodeClient](t)
+ node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(10))
+ node3.On("Order").Return(int32(2))
+
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3}
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ //Should select the second node as it has the highest priority
+ assert.Same(t, nodes[1], selector.Select())
+ })
+
+ t.Run("different td but same order", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(10))
+ node1.On("Order").Maybe().Return(int32(3))
+
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(11))
+ node2.On("Order").Maybe().Return(int32(3))
+
+ node3 := newMockNode[types.ID, Head, nodeClient](t)
+ node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(12))
+ node3.On("Order").Return(int32(3))
+
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3}
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ //Should select the third node as it has the highest td
+ assert.Same(t, nodes[2], selector.Select())
+ })
+
+ t.Run("different head and different order", func(t *testing.T) {
+ node1 := newMockNode[types.ID, Head, nodeClient](t)
+ node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(100))
+ node1.On("Order").Maybe().Return(int32(4))
+
+ node2 := newMockNode[types.ID, Head, nodeClient](t)
+ node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(110))
+ node2.On("Order").Maybe().Return(int32(5))
+
+ node3 := newMockNode[types.ID, Head, nodeClient](t)
+ node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(110))
+ node3.On("Order").Maybe().Return(int32(1))
+
+ node4 := newMockNode[types.ID, Head, nodeClient](t)
+ node4.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(105))
+ node4.On("Order").Maybe().Return(int32(2))
+
+ nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3, node4}
+ selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes)
+ //Should select the third node as it has the highest td and will win the priority tie-breaker
+ assert.Same(t, nodes[2], selector.Select())
+ })
+}
diff --git a/common/client/node_test.go b/common/client/node_test.go
new file mode 100644
index 0000000000..0438e11e61
--- /dev/null
+++ b/common/client/node_test.go
@@ -0,0 +1,80 @@
+package client
+
+import (
+ "net/url"
+ "testing"
+ "time"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+type testNodeConfig struct {
+ pollFailureThreshold uint32
+ pollInterval time.Duration
+ selectionMode string
+ syncThreshold uint32
+}
+
+func (n testNodeConfig) PollFailureThreshold() uint32 {
+ return n.pollFailureThreshold
+}
+
+func (n testNodeConfig) PollInterval() time.Duration {
+ return n.pollInterval
+}
+
+func (n testNodeConfig) SelectionMode() string {
+ return n.selectionMode
+}
+
+func (n testNodeConfig) SyncThreshold() uint32 {
+ return n.syncThreshold
+}
+
+type testNode struct {
+ *node[types.ID, Head, NodeClient[types.ID, Head]]
+}
+
+type testNodeOpts struct {
+ config testNodeConfig
+ noNewHeadsThreshold time.Duration
+ lggr logger.Logger
+ wsuri url.URL
+ httpuri *url.URL
+ name string
+ id int32
+ chainID types.ID
+ nodeOrder int32
+ rpc *mockNodeClient[types.ID, Head]
+ chainFamily string
+}
+
+func newTestNode(t *testing.T, opts testNodeOpts) testNode {
+ if opts.lggr == nil {
+ opts.lggr = logger.TestLogger(t)
+ }
+
+ if opts.name == "" {
+ opts.name = "tes node"
+ }
+
+ if opts.chainFamily == "" {
+ opts.chainFamily = "test node chain family"
+ }
+
+ if opts.chainID == nil {
+ opts.chainID = types.RandomID()
+ }
+
+ if opts.id == 0 {
+ opts.id = 42
+ }
+
+ nodeI := NewNode[types.ID, Head, NodeClient[types.ID, Head]](opts.config, opts.noNewHeadsThreshold, opts.lggr,
+ opts.wsuri, opts.httpuri, opts.name, opts.id, opts.chainID, opts.nodeOrder, opts.rpc, opts.chainFamily)
+
+ return testNode{
+ nodeI.(*node[types.ID, Head, NodeClient[types.ID, Head]]),
+ }
+}
diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go
index 0051fb014d..fa793a826a 100644
--- a/common/client/send_only_node.go
+++ b/common/client/send_only_node.go
@@ -13,6 +13,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
+//go:generate mockery --quiet --name sendOnlyClient --structname mockSendOnlyClient --filename "mock_send_only_client_test.go" --inpackage --case=underscore
type sendOnlyClient[
CHAIN_ID types.ID,
] interface {
@@ -22,6 +23,8 @@ type sendOnlyClient[
}
// SendOnlyNode represents one node used as a sendonly
+//
+//go:generate mockery --quiet --name SendOnlyNode --structname mockSendOnlyNode --filename "mock_send_only_node_test.go" --inpackage --case=underscore
type SendOnlyNode[
CHAIN_ID types.ID,
RPC sendOnlyClient[CHAIN_ID],
@@ -143,6 +146,7 @@ func (s *sendOnlyNode[CHAIN_ID, RPC]) start(startCtx context.Context) {
func (s *sendOnlyNode[CHAIN_ID, RPC]) Close() error {
return s.StopOnce(s.name, func() error {
s.rpc.Close()
+ close(s.chStop)
s.wg.Wait()
s.setState(nodeStateClosed)
return nil
diff --git a/common/client/send_only_node_test.go b/common/client/send_only_node_test.go
new file mode 100644
index 0000000000..bfe5515365
--- /dev/null
+++ b/common/client/send_only_node_test.go
@@ -0,0 +1,139 @@
+package client
+
+import (
+ "fmt"
+ "net/url"
+ "testing"
+
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/zap"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+
+ "github.com/smartcontractkit/chainlink/v2/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+func TestNewSendOnlyNode(t *testing.T) {
+ t.Parallel()
+
+ urlFormat := "http://user:%s@testurl.com"
+ password := "pass"
+ u, err := url.Parse(fmt.Sprintf(urlFormat, password))
+ require.NoError(t, err)
+ redacted := fmt.Sprintf(urlFormat, "xxxxx")
+ lggr := logger.TestLogger(t)
+ name := "TestNewSendOnlyNode"
+ chainID := types.RandomID()
+ client := newMockSendOnlyClient[types.ID](t)
+
+ node := NewSendOnlyNode(lggr, *u, name, chainID, client)
+ assert.NotNil(t, node)
+
+ // Must contain name & url with redacted password
+ assert.Contains(t, node.String(), fmt.Sprintf("%s:%s", name, redacted))
+ assert.Equal(t, node.ConfiguredChainID(), chainID)
+}
+
+func TestStartSendOnlyNode(t *testing.T) {
+ t.Parallel()
+ t.Run("becomes unusable if initial dial fails", func(t *testing.T) {
+ t.Parallel()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ client := newMockSendOnlyClient[types.ID](t)
+ client.On("Close").Once()
+ expectedError := errors.New("some http error")
+ client.On("DialHTTP").Return(expectedError).Once()
+ s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), types.RandomID(), client)
+
+ defer func() { assert.NoError(t, s.Close()) }()
+ err := s.Start(tests.Context(t))
+ require.NoError(t, err)
+
+ assert.Equal(t, nodeStateUnusable, s.State())
+ tests.RequireLogMessage(t, observedLogs, "Dial failed: SendOnly Node is unusable")
+ })
+ t.Run("Default ChainID(0) produces warn and skips checks", func(t *testing.T) {
+ t.Parallel()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ client := newMockSendOnlyClient[types.ID](t)
+ client.On("Close").Once()
+ client.On("DialHTTP").Return(nil).Once()
+ s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), types.NewIDFromInt(0), client)
+
+ defer func() { assert.NoError(t, s.Close()) }()
+ err := s.Start(tests.Context(t))
+ require.NoError(t, err)
+
+ assert.Equal(t, nodeStateAlive, s.State())
+ tests.RequireLogMessage(t, observedLogs, "sendonly rpc ChainID verification skipped")
+ })
+ t.Run("Can recover from chainID verification failure", func(t *testing.T) {
+ t.Parallel()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ client := newMockSendOnlyClient[types.ID](t)
+ client.On("Close").Once()
+ client.On("DialHTTP").Return(nil)
+ expectedError := errors.New("failed to get chain ID")
+ chainID := types.RandomID()
+ const failuresCount = 2
+ client.On("ChainID", mock.Anything).Return(types.RandomID(), expectedError).Times(failuresCount)
+ client.On("ChainID", mock.Anything).Return(chainID, nil)
+
+ s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), chainID, client)
+
+ defer func() { assert.NoError(t, s.Close()) }()
+ err := s.Start(tests.Context(t))
+ require.NoError(t, err)
+
+ assert.Equal(t, nodeStateUnreachable, s.State())
+ tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Verify failed: %v", expectedError), failuresCount)
+ tests.AssertEventually(t, func() bool {
+ return s.State() == nodeStateAlive
+ })
+ })
+ t.Run("Can recover from chainID mismatch", func(t *testing.T) {
+ t.Parallel()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ client := newMockSendOnlyClient[types.ID](t)
+ client.On("Close").Once()
+ client.On("DialHTTP").Return(nil).Once()
+ configuredChainID := types.NewIDFromInt(11)
+ rpcChainID := types.NewIDFromInt(20)
+ const failuresCount = 2
+ client.On("ChainID", mock.Anything).Return(rpcChainID, nil).Times(failuresCount)
+ client.On("ChainID", mock.Anything).Return(configuredChainID, nil)
+ s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), configuredChainID, client)
+
+ defer func() { assert.NoError(t, s.Close()) }()
+ err := s.Start(tests.Context(t))
+ require.NoError(t, err)
+
+ assert.Equal(t, nodeStateInvalidChainID, s.State())
+ tests.AssertLogCountEventually(t, observedLogs, "sendonly rpc ChainID doesn't match local chain ID", failuresCount)
+ tests.AssertEventually(t, func() bool {
+ return s.State() == nodeStateAlive
+ })
+ })
+ t.Run("Start with Random ChainID", func(t *testing.T) {
+ t.Parallel()
+ lggr, observedLogs := logger.TestLoggerObserved(t, zap.WarnLevel)
+ client := newMockSendOnlyClient[types.ID](t)
+ client.On("Close").Once()
+ client.On("DialHTTP").Return(nil).Once()
+ configuredChainID := types.RandomID()
+ client.On("ChainID", mock.Anything).Return(configuredChainID, nil)
+ s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), configuredChainID, client)
+
+ defer func() { assert.NoError(t, s.Close()) }()
+ err := s.Start(tests.Context(t))
+ assert.NoError(t, err)
+ tests.AssertEventually(t, func() bool {
+ return s.State() == nodeStateAlive
+ })
+ assert.Equal(t, 0, observedLogs.Len()) // No warnings expected
+ })
+}
diff --git a/common/client/types.go b/common/client/types.go
index f3a6029a9e..0e52f1db72 100644
--- a/common/client/types.go
+++ b/common/client/types.go
@@ -11,6 +11,8 @@ import (
)
// RPC includes all the necessary methods for a multi-node client to interact directly with any RPC endpoint.
+//
+//go:generate mockery --quiet --name RPC --structname mockRPC --inpackage --filename "mock_rpc_test.go" --case=underscore
type RPC[
CHAIN_ID types.ID,
SEQ types.Sequence,
@@ -45,12 +47,16 @@ type RPC[
}
// Head is the interface required by the NodeClient
+//
+//go:generate mockery --quiet --name Head --structname mockHead --filename "mock_head_test.go" --inpackage --case=underscore
type Head interface {
BlockNumber() int64
BlockDifficulty() *utils.Big
}
// NodeClient includes all the necessary RPC methods required by a node.
+//
+//go:generate mockery --quiet --name NodeClient --structname mockNodeClient --filename "mock_node_client_test.go" --inpackage --case=underscore
type NodeClient[
CHAIN_ID types.ID,
HEAD Head,
diff --git a/common/types/test_utils.go b/common/types/test_utils.go
new file mode 100644
index 0000000000..40560f7866
--- /dev/null
+++ b/common/types/test_utils.go
@@ -0,0 +1,16 @@
+package types
+
+import (
+ "math"
+ "math/big"
+ "math/rand"
+)
+
+func RandomID() ID {
+ id := rand.Int63n(math.MaxInt32) + 10000
+ return big.NewInt(id)
+}
+
+func NewIDFromInt(id int64) ID {
+ return big.NewInt(id)
+}
From d8dc7abe3c9bd9bedd036cf69c742e883832fc9e Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Thu, 9 Nov 2023 16:09:14 -0500
Subject: [PATCH 122/327] [Functions] Add Billing event (#11185)
* FUN-974 - Add Billing event
* Add L1 fee share to billing event
* Update gas snapshot
---
.../gas-snapshots/functions.gas-snapshot | 44 +++---
.../functions/dev/v1_X/FunctionsBilling.sol | 19 ++-
.../tests/v1_X/FunctionsBilling.t.sol | 52 ++++++-
.../functions_coordinator.go | 147 +++++++++++++++++-
...rapper-dependency-versions-do-not-edit.txt | 2 +-
5 files changed, 237 insertions(+), 27 deletions(-)
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index 4e891535b7..af95b75df1 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,12 +1,12 @@
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14497117)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14497095)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14497111)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14508531)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14508508)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14508480)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14508431)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14508420)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14508464)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14534216)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14534194)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14534210)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14545630)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14545607)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14545579)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14545530)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14545519)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14545563)
FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
@@ -26,9 +26,11 @@ FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmitter
FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 18974)
FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 38251)
FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8801)
+FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13302)
+FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 180763)
FunctionsClient_Constructor:test_Constructor_Success() (gas: 7573)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 501740)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 202944)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 504364)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 205568)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14623)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22923)
FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55059)
@@ -49,17 +51,17 @@ FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 246)
FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 223)
FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 225)
FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12007)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 174021)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 164352)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 174037)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 164368)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38115)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35238)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 182497)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 182513)
FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 158041)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 323262)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 336879)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2512144)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 542628)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 158055)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 327615)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 341236)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2516517)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 546996)
FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 17983)
FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12904)
FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37159)
@@ -142,8 +144,8 @@ FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 1501
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43685, ~: 45548)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46197, ~: 48060)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14295, ~: 14295)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51000, ~: 53040)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 85879, ~: 89604)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51089, ~: 53040)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 86057, ~: 89604)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15638)
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
index bf43ead8d7..bd13a3a5a1 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
@@ -20,6 +20,15 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
using FunctionsResponse for FunctionsResponse.FulfillResult;
uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei
+
+ event RequestBilled(
+ bytes32 indexed requestId,
+ uint96 juelsPerGas,
+ uint256 l1FeeShareWei,
+ uint96 callbackCostJuels,
+ uint96 totalCostJuels
+ );
+
// ================================================================
// | Request Commitment state |
// ================================================================
@@ -268,12 +277,13 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize;
// Gas overhead without callback
uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei);
+ uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice);
// The Functions Router will perform the callback to the client contract
(FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill(
response,
err,
- _getJuelsFromWei(tx.gasprice), // Juels Per Gas conversion rate
+ juelsPerGas,
gasOverheadJuels + commitment.donFee, // cost without callback or admin fee, those will be added by the Router
msg.sender,
commitment
@@ -292,6 +302,13 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
// Put donFee into the pool of fees, to be split later
// Saves on storage writes that would otherwise be charged to the user
s_feePool += commitment.donFee;
+ emit RequestBilled({
+ requestId: requestId,
+ juelsPerGas: juelsPerGas,
+ l1FeeShareWei: l1FeeShareWei,
+ callbackCostJuels: callbackCostJuels,
+ totalCostJuels: gasOverheadJuels + callbackCostJuels + commitment.donFee + commitment.adminFee
+ });
}
return resultCode;
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
index 82dea8672c..6e94e4fc5f 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
@@ -4,6 +4,7 @@ pragma solidity ^0.8.19;
import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol";
import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol";
import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol";
+import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol";
import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol";
import {Routable} from "../../dev/v1_X/Routable.sol";
@@ -221,8 +222,55 @@ contract FunctionsBilling__StartBilling {
}
/// @notice #_fulfillAndBill
-contract FunctionsBilling__FulfillAndBill {
- // TODO: make contract internal function helper
+contract FunctionsBilling__FulfillAndBill is FunctionsClientRequestSetup {
+ function test__FulfillAndBill_RevertIfInvalidCommitment() public {
+ vm.expectRevert();
+ s_functionsCoordinator.fulfillAndBill_HARNESS(
+ s_requests[1].requestId,
+ new bytes(0),
+ new bytes(0),
+ new bytes(0), // malformed commitment data
+ new bytes(0),
+ 1
+ );
+ }
+
+ event RequestBilled(
+ bytes32 indexed requestId,
+ uint96 juelsPerGas,
+ uint256 l1FeeShareWei,
+ uint96 callbackCostJuels,
+ uint96 totalCostJuels
+ );
+
+ function test__FulfillAndBill_Success() public {
+ uint96 juelsPerGas = uint96((1e18 * TX_GASPRICE_START) / uint256(LINK_ETH_RATE));
+ uint96 callbackCostGas = 5072; // Taken manually
+ uint96 callbackCostJuels = juelsPerGas * callbackCostGas;
+ uint96 gasOverheadJuels = juelsPerGas *
+ (getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback);
+
+ uint96 totalCostJuels = gasOverheadJuels + callbackCostJuels + s_donFee + s_adminFee;
+
+ // topic0 (function signature, always checked), check topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true).
+ bool checkTopic1 = true;
+ bool checkTopic2 = false;
+ bool checkTopic3 = false;
+ bool checkData = true;
+ vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData);
+ emit RequestBilled(s_requests[1].requestId, juelsPerGas, 0, callbackCostJuels, totalCostJuels);
+
+ FunctionsResponse.FulfillResult resultCode = s_functionsCoordinator.fulfillAndBill_HARNESS(
+ s_requests[1].requestId,
+ new bytes(0),
+ new bytes(0),
+ abi.encode(s_requests[1].commitment),
+ new bytes(0),
+ 1
+ );
+
+ assertEq(uint256(resultCode), uint256(FunctionsResponse.FulfillResult.FULFILLED));
+ }
}
/// @notice #deleteCommitment
diff --git a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
index b2e5ec4b09..397ea3d18b 100644
--- a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
+++ b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
@@ -71,8 +71,8 @@ type FunctionsResponseRequestMeta struct {
}
var FunctionsCoordinatorMetaData = &bind.MetaData{
- ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x60c06040523480156200001157600080fd5b506040516200556438038062005564833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614ee16200068360003960008181610845015281816109d301528181610ca601528181610f3a015281816110450152818161183001526133aa0152600061126e0152614ee16000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a0366004613857565b61059c565b005b6101a56101b5366004613a00565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613b24565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613bc5565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613c54565b6108d7565b6101a5610a90565b6101a5610b92565b6101a5610293366004613857565b610d92565b6102a0610de2565b6040516102039190613cde565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613cf1565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613d0a565b610fd4565b6040516102039190613e5f565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613eb3565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b6040516102039190613f6a565b61053b61053636600461405a565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004614173565b6119e3565b61057b61240f565b604051908152602001610203565b6101a5610597366004614240565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec8284836142f6565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f518486290610836908390613f6a565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d2919061441c565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff16614468565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd261448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c3161448d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf561448d565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d87816144bc565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec8284836142f6565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e609061425d565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea89061425d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed49061425d565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a8836144f4565b6128b2565b90506110bf6060830160408401614240565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a088016145e1565b61111f61016088016101408901614240565b61112988806145fe565b61113b6101208b016101008c01614663565b60208b01356111516101008d0160e08e0161467e565b8b6040516111679998979695949392919061469b565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d50565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a89190614743565b6112b2919061478b565b6112bd906001614743565b60ff1690506112dd565b60208201516112d7906001614743565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f26147ad565b6002811115611403576114036147ad565b9052509050600281602001516002811115611420576114206147ad565b14801561146757506006816000015160ff16815481106114425761144261448d565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da6137ef565b6000808a8a6040516114ed9291906147dc565b604051908190038120611504918e906020016147ec565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d61448d565b61157a91901a601b614743565b8e8e8681811061158c5761158c61448d565b905060200201358d8d878181106115a5576115a561448d565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff80821685529296509294508401916101009004166002811115611684576116846147ad565b6002811115611695576116956147ad565b90525092506001836020015160028111156116b2576116b26147ad565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f81106117335761173361448d565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf61448d565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa600186614743565b94505080611807906144bc565b905061154e565b50505061181f833383858e8e612e07565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd7565b98975050505050505050565b6060600c805461199b9061425d565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea89061425d565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b59816003614800565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c109088613144565b60055415611dc557600554600090611c2a90600190614817565b9050600060058281548110611c4157611c4161448d565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b61448d565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb61482a565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d6461482a565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee61448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e386147ad565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed061448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f716147ad565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b61448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe56147ad565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f61448d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115612120576121206147ad565b02179055505082518051600592508390811061213e5761213e61448d565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba61448d565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905580612224816144bc565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e491849174010000000000000000000000000000000000000000900416614859565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a0015161315d565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff16969095919491939192614876565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c19190614926565b5093505092505080426125d49190614817565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b61267981613208565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b90508051600003612768576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600b54600091612787916bffffffffffffffffffffffff16614976565b905060005b82518110156128535781600a60008584815181106127ac576127ac61448d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff1661281491906149a1565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284c906144bc565b905061278c565b50815161286090826149c6565b600b80546000906128809084906bffffffffffffffffffffffff16614468565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6d576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aaa8560e001513a848860800151612fd7565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b06576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b1f91906149ee565b905060003087604001518860a001518960c001516001612b3f9190614a01565b8a5180516020918201206101008d015160e08e0151604051612bf398979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d029190613e5f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5d826020614800565b612d68856020614800565b612d74886101446149ee565b612d7e91906149ee565b612d8891906149ee565b612d939060006149ee565b9050368114612dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e1986880188614afd565b8451949950929750909550935091501580612e3657508351855114155b80612e4357508251855114155b80612e5057508151855114155b80612e5d57508051855114155b15612e94576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8551811015612fc9576000612f2e878381518110612eb757612eb761448d565b6020026020010151878481518110612ed157612ed161448d565b6020026020010151878581518110612eeb57612eeb61448d565b6020026020010151878681518110612f0557612f0561448d565b6020026020010151878781518110612f1f57612f1f61448d565b60200260200101518c516132fd565b90506000816006811115612f4457612f446147ad565b1480612f6157506001816006811115612f5f57612f5f6147ad565b145b15612fb857868281518110612f7857612f7861448d565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc2816144bc565b9050612e97565b505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561303257600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b6008546000906127109061304c9063ffffffff1687614800565b6130569190614bcf565b61306090866149ee565b60085490915060009087906130999063ffffffff6c01000000000000000000000000820481169168010000000000000000900416614859565b6130a39190614859565b63ffffffff16905060006130ed6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356d92505050565b9050600061310e826130ff8587614800565b61310991906149ee565b6136af565b9050600061312a68ffffffffffffffffff808916908a166149a1565b905061313681836149a1565b9a9950505050505050505050565b600061314e610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161318199989796959493929190614be3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133149190614caf565b905060003a82610120015183610100015161332f9190614d77565b64ffffffffff166133409190614800565b905060008460ff166133886000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356d92505050565b6133929190614bcf565b905060006133a361310983856149ee565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298d8d6133ef3a6136af565b60e08b01516134099068ffffffffffffffffff16896149a1565b338c6040518763ffffffff1660e01b815260040161342c96959493929190614d95565b60408051808303816000875af115801561344a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061346e9190614e11565b90925090506000826006811115613487576134876147ad565b14806134a4575060018260068111156134a2576134a26147ad565b145b1561355d5760008d8152600760205260408120556134c281846149a1565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0880151600b805468ffffffffffffffffff9092169390929161352e918591166149a1565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b509b9a5050505050505050505050565b600046613579816136e3565b156135f557606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ee9190614e44565b9392505050565b6135fe81613706565b156136a65773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e84604051806080016040528060488152602001614e8d6048913960405160200161365e929190614e5d565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016136899190613b24565b602060405180830381865afa1580156135ca573d6000803e3d6000fd5b50600092915050565b60006136dd6136bc61240f565b6136ce84670de0b6b3a7640000614800565b6136d89190614bcf565b61374d565b92915050565b600061a4b18214806136f7575062066eed82145b806136dd57505062066eee1490565b6000600a82148061371857506101a482145b80613725575062aa37dc82145b80613731575061210582145b8061373e575062014a3382145b806136dd57505062014a341490565b60006bffffffffffffffffffffffff8211156137eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f84011261382057600080fd5b50813567ffffffffffffffff81111561383857600080fd5b60208301915083602082850101111561385057600080fd5b9250929050565b6000806020838503121561386a57600080fd5b823567ffffffffffffffff81111561388157600080fd5b61388d8582860161380e565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156138ec576138ec613899565b60405290565b604051610160810167ffffffffffffffff811182821017156138ec576138ec613899565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561395d5761395d613899565b604052919050565b63ffffffff8116811461267957600080fd5b803561117081613965565b68ffffffffffffffffff8116811461267957600080fd5b803561117081613982565b64ffffffffff8116811461267957600080fd5b8035611170816139a4565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613a1357600080fd5b613a1b6138c8565b613a2483613977565b8152613a3260208401613977565b6020820152613a4360408401613977565b6040820152613a5460608401613977565b6060820152613a6560808401613999565b6080820152613a7660a084016139b7565b60a0820152613a8760c084016139c2565b60c0820152613a9860e084016139d4565b60e0820152610100613aab818501613977565b908201529392505050565b60005b83811015613ad1578181015183820152602001613ab9565b50506000910152565b60008151808452613af2816020860160208601613ab6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006135ee6020830184613ada565b600082601f830112613b4857600080fd5b813567ffffffffffffffff811115613b6257613b62613899565b613b9360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613916565b818152846020838601011115613ba857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613bd757600080fd5b813567ffffffffffffffff811115613bee57600080fd5b613bfa84828501613b37565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b803561117081613c02565b6bffffffffffffffffffffffff8116811461267957600080fd5b803561117081613c2f565b60008060408385031215613c6757600080fd5b8235613c7281613c02565b91506020830135613c8281613c2f565b809150509250929050565b600081518084526020808501945080840160005b83811015613cd357815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613ca1565b509495945050505050565b6020815260006135ee6020830184613c8d565b600060208284031215613d0357600080fd5b5035919050565b600060208284031215613d1c57600080fd5b813567ffffffffffffffff811115613d3357600080fd5b820161016081850312156135ee57600080fd5b805182526020810151613d71602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613d9160408401826bffffffffffffffffffffffff169052565b506060810151613db9606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613dd5608084018267ffffffffffffffff169052565b5060a0810151613ded60a084018263ffffffff169052565b5060c0810151613e0a60c084018268ffffffffffffffffff169052565b5060e0810151613e2760e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016136dd8284613d46565b60008083601f840112613e8057600080fd5b50813567ffffffffffffffff811115613e9857600080fd5b6020830191508360208260051b850101111561385057600080fd5b60008060008060008060008060e0898b031215613ecf57600080fd5b606089018a811115613ee057600080fd5b8998503567ffffffffffffffff80821115613efa57600080fd5b613f068c838d0161380e565b909950975060808b0135915080821115613f1f57600080fd5b613f2b8c838d01613e6e565b909750955060a08b0135915080821115613f4457600080fd5b50613f518b828c01613e6e565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151613fbe608084018268ffffffffffffffffff169052565b5060a0830151613fd760a084018264ffffffffff169052565b5060c0830151613fed60c084018261ffff169052565b5060e083015161401d60e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b803561117081614039565b60008060008060006080868803121561407257600080fd5b853561407d81614039565b9450602086013567ffffffffffffffff81111561409957600080fd5b6140a58882890161380e565b90955093505060408601356140b981613965565b949793965091946060013592915050565b600067ffffffffffffffff8211156140e4576140e4613899565b5060051b60200190565b600082601f8301126140ff57600080fd5b8135602061411461410f836140ca565b613916565b82815260059290921b8401810191818101908684111561413357600080fd5b8286015b8481101561415757803561414a81613c02565b8352918301918301614137565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561418c57600080fd5b863567ffffffffffffffff808211156141a457600080fd5b6141b08a838b016140ee565b975060208901359150808211156141c657600080fd5b6141d28a838b016140ee565b96506141e060408a01614162565b955060608901359150808211156141f657600080fd5b6142028a838b01613b37565b945061421060808a0161404f565b935060a089013591508082111561422657600080fd5b5061423389828a01613b37565b9150509295509295509295565b60006020828403121561425257600080fd5b81356135ee81613c02565b600181811c9082168061427157607f821691505b6020821081036142aa577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c810160208610156142d75750805b601f850160051c820191505b81811015610a88578281556001016142e3565b67ffffffffffffffff83111561430e5761430e613899565b6143228361431c835461425d565b836142b0565b6000601f841160018114614374576000851561433e5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561440a565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156143c357868501358255602094850194600190920191016143a3565b50868210156143fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613982565b60006020828403121561442e57600080fd5b81516135ee81613982565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff82811682821603908082111561266157612661614439565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036144ed576144ed614439565b5060010190565b6000610160823603121561450757600080fd5b61450f6138f2565b823567ffffffffffffffff81111561452657600080fd5b61453236828601613b37565b8252506020830135602082015261454b60408401613c24565b604082015261455c60608401613c49565b606082015261456d60808401613999565b608082015261457e60a0840161404f565b60a082015261458f60c0840161404f565b60c08201526145a060e08401613977565b60e08201526101006145b38185016139c2565b908201526101206145c584820161404f565b908201526101406145d7848201613c24565b9082015292915050565b6000602082840312156145f357600080fd5b81356135ee81614039565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261463357600080fd5b83018035915067ffffffffffffffff82111561464e57600080fd5b60200191503681900382131561385057600080fd5b60006020828403121561467557600080fd5b6135ee826139c2565b60006020828403121561469057600080fd5b81356135ee81613965565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061313660e0830184613d46565b60ff81811683821601908111156136dd576136dd614439565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061479e5761479e61475c565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b80820281158282048414176136dd576136dd614439565b818103818111156136dd576136dd614439565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff81811683821601908082111561266157612661614439565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526148a68184018a613c8d565b905082810360808401526148ba8189613c8d565b905060ff871660a084015282810360c08401526148d78187613ada565b905067ffffffffffffffff851660e08401528281036101008401526148fc8185613ada565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a0868803121561493e57600080fd5b6149478661490c565b945060208601519350604086015192506060860151915061496a6080870161490c565b90509295509295909350565b60006bffffffffffffffffffffffff808416806149955761499561475c565b92169190910492915050565b6bffffffffffffffffffffffff81811683821601908082111561266157612661614439565b6bffffffffffffffffffffffff81811683821602808216919082811461403157614031614439565b808201808211156136dd576136dd614439565b67ffffffffffffffff81811683821601908082111561266157612661614439565b600082601f830112614a3357600080fd5b81356020614a4361410f836140ca565b82815260059290921b84018101918181019086841115614a6257600080fd5b8286015b848110156141575780358352918301918301614a66565b600082601f830112614a8e57600080fd5b81356020614a9e61410f836140ca565b82815260059290921b84018101918181019086841115614abd57600080fd5b8286015b8481101561415757803567ffffffffffffffff811115614ae15760008081fd5b614aef8986838b0101613b37565b845250918301918301614ac1565b600080600080600060a08688031215614b1557600080fd5b853567ffffffffffffffff80821115614b2d57600080fd5b614b3989838a01614a22565b96506020880135915080821115614b4f57600080fd5b614b5b89838a01614a7d565b95506040880135915080821115614b7157600080fd5b614b7d89838a01614a7d565b94506060880135915080821115614b9357600080fd5b614b9f89838a01614a7d565b93506080880135915080821115614bb557600080fd5b50614bc288828901614a7d565b9150509295509295909350565b600082614bde57614bde61475c565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614c2a8285018b613c8d565b91508382036080850152614c3e828a613c8d565b915060ff881660a085015283820360c0850152614c5b8288613ada565b90861660e085015283810361010085015290506148fc8185613ada565b805161117081613c02565b805161117081613c2f565b805161117081614039565b805161117081613965565b8051611170816139a4565b60006101608284031215614cc257600080fd5b614cca6138f2565b82518152614cda60208401614c78565b6020820152614ceb60408401614c83565b6040820152614cfc60608401614c78565b6060820152614d0d60808401614c8e565b6080820152614d1e60a08401614c99565b60a0820152614d2f60c08401614411565b60c0820152614d4060e08401614411565b60e0820152610100614d53818501614ca4565b90820152610120614d65848201614ca4565b90820152610140613aab848201614c99565b64ffffffffff81811683821601908082111561266157612661614439565b6000610200808352614da98184018a613ada565b90508281036020840152614dbd8189613ada565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614e06905060a0830184613d46565b979650505050505050565b60008060408385031215614e2457600080fd5b825160078110614e3357600080fd5b6020840151909250613c8281613c2f565b600060208284031215614e5657600080fd5b5051919050565b60008351614e6f818460208801613ab6565b835190830190614e83818360208801613ab6565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
+ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"juelsPerGas\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1FeeShareWei\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"callbackCostJuels\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalCostJuels\",\"type\":\"uint96\"}],\"name\":\"RequestBilled\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ Bin: "0x60c06040523480156200001157600080fd5b506040516200560838038062005608833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614f856200068360003960008181610845015281816109d301528181610ca601528181610f3a015281816110450152818161183001526133b70152600061126e0152614f856000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a03660046138fb565b61059c565b005b6101a56101b5366004613aa4565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613bc8565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613c69565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613cf8565b6108d7565b6101a5610a90565b6101a5610b92565b6101a56102933660046138fb565b610d92565b6102a0610de2565b6040516102039190613d82565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613d95565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613dae565b610fd4565b6040516102039190613f03565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613f57565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b604051610203919061400e565b61053b6105363660046140fe565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004614217565b6119e3565b61057b61240f565b604051908152602001610203565b6101a56105973660046142e4565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec82848361439a565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f51848629061083690839061400e565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d291906144c0565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd2614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c31614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf5614531565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d8781614560565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec82848361439a565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e6090614301565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea890614301565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed490614301565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a883614598565b6128b2565b90506110bf60608301604084016142e4565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a08801614685565b61111f610160880161014089016142e4565b61112988806146a2565b61113b6101208b016101008c01614707565b60208b01356111516101008d0160e08e01614722565b8b6040516111679998979695949392919061473f565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d50565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a891906147e7565b6112b2919061482f565b6112bd9060016147e7565b60ff1690506112dd565b60208201516112d79060016147e7565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f2614851565b600281111561140357611403614851565b905250905060028160200151600281111561142057611420614851565b14801561146757506006816000015160ff168154811061144257611442614531565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da613893565b6000808a8a6040516114ed929190614880565b604051908190038120611504918e90602001614890565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d614531565b61157a91901a601b6147e7565b8e8e8681811061158c5761158c614531565b905060200201358d8d878181106115a5576115a5614531565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561168457611684614851565b600281111561169557611695614851565b90525092506001836020015160028111156116b2576116b2614851565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061173357611733614531565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf614531565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa6001866147e7565b9450508061180790614560565b905061154e565b50505061181f833383858e8e612e07565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd7565b98975050505050505050565b6060600c805461199b90614301565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea890614301565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b598160036148a4565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c109088613144565b60055415611dc557600554600090611c2a906001906148bb565b9050600060058281548110611c4157611c41614531565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b614531565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb6148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d646148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e38614851565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed0614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f71614851565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe5614851565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561212057612120614851565b02179055505082518051600592508390811061213e5761213e614531565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba614531565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061222481614560565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e4918491740100000000000000000000000000000000000000009004166148fd565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a0015161315d565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff1696909591949193919261491a565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c191906149ca565b5093505092505080426125d491906148bb565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b61267981613208565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b90508051600003612768576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600b54600091612787916bffffffffffffffffffffffff16614a1a565b905060005b82518110156128535781600a60008584815181106127ac576127ac614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128149190614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284c90614560565b905061278c565b5081516128609082614a6a565b600b80546000906128809084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6d576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aaa8560e001513a848860800151612fd7565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b06576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b1f9190614a92565b905060003087604001518860a001518960c001516001612b3f9190614aa5565b8a5180516020918201206101008d015160e08e0151604051612bf398979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d029190613f03565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5d8260206148a4565b612d688560206148a4565b612d7488610144614a92565b612d7e9190614a92565b612d889190614a92565b612d93906000614a92565b9050368114612dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e1986880188614ba1565b8451949950929750909550935091501580612e3657508351855114155b80612e4357508251855114155b80612e5057508151855114155b80612e5d57508051855114155b15612e94576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8551811015612fc9576000612f2e878381518110612eb757612eb7614531565b6020026020010151878481518110612ed157612ed1614531565b6020026020010151878581518110612eeb57612eeb614531565b6020026020010151878681518110612f0557612f05614531565b6020026020010151878781518110612f1f57612f1f614531565b60200260200101518c516132fd565b90506000816006811115612f4457612f44614851565b1480612f6157506001816006811115612f5f57612f5f614851565b145b15612fb857868281518110612f7857612f78614531565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc281614560565b9050612e97565b505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561303257600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b6008546000906127109061304c9063ffffffff16876148a4565b6130569190614c73565b6130609086614a92565b60085490915060009087906130999063ffffffff6c010000000000000000000000008204811691680100000000000000009004166148fd565b6130a391906148fd565b63ffffffff16905060006130ed6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b9050600061310e826130ff85876148a4565b6131099190614a92565b613753565b9050600061312a68ffffffffffffffffff808916908a16614a45565b90506131368183614a45565b9a9950505050505050505050565b600061314e610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161318199989796959493929190614c87565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133149190614d53565b905060003a82610120015183610100015161332f9190614e1b565b64ffffffffff1661334091906148a4565b905060008460ff166133886000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b6133929190614c73565b905060006133a36131098385614a92565b905060006133b03a613753565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff168961340f9190614a45565b338d6040518763ffffffff1660e01b815260040161343296959493929190614e39565b60408051808303816000875af1158015613450573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134749190614eb5565b9092509050600082600681111561348d5761348d614851565b14806134aa575060018260068111156134a8576134a8614851565b145b156136005760008e8152600760205260408120556134c88185614a45565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161353491859116614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b6135b39190614a45565b6135bd9190614a45565b6135c79190614a45565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b60004661361d81613787565b1561369957606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561366e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136929190614ee8565b9392505050565b6136a2816137aa565b1561374a5773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e84604051806080016040528060488152602001614f3160489139604051602001613702929190614f01565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161372d9190613bc8565b602060405180830381865afa15801561366e573d6000803e3d6000fd5b50600092915050565b600061378161376061240f565b61377284670de0b6b3a76400006148a4565b61377c9190614c73565b6137f1565b92915050565b600061a4b182148061379b575062066eed82145b8061378157505062066eee1490565b6000600a8214806137bc57506101a482145b806137c9575062aa37dc82145b806137d5575061210582145b806137e2575062014a3382145b8061378157505062014a341490565b60006bffffffffffffffffffffffff82111561388f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f8401126138c457600080fd5b50813567ffffffffffffffff8111156138dc57600080fd5b6020830191508360208285010111156138f457600080fd5b9250929050565b6000806020838503121561390e57600080fd5b823567ffffffffffffffff81111561392557600080fd5b613931858286016138b2565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156139905761399061393d565b60405290565b604051610160810167ffffffffffffffff811182821017156139905761399061393d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a0157613a0161393d565b604052919050565b63ffffffff8116811461267957600080fd5b803561117081613a09565b68ffffffffffffffffff8116811461267957600080fd5b803561117081613a26565b64ffffffffff8116811461267957600080fd5b803561117081613a48565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613ab757600080fd5b613abf61396c565b613ac883613a1b565b8152613ad660208401613a1b565b6020820152613ae760408401613a1b565b6040820152613af860608401613a1b565b6060820152613b0960808401613a3d565b6080820152613b1a60a08401613a5b565b60a0820152613b2b60c08401613a66565b60c0820152613b3c60e08401613a78565b60e0820152610100613b4f818501613a1b565b908201529392505050565b60005b83811015613b75578181015183820152602001613b5d565b50506000910152565b60008151808452613b96816020860160208601613b5a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006136926020830184613b7e565b600082601f830112613bec57600080fd5b813567ffffffffffffffff811115613c0657613c0661393d565b613c3760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016139ba565b818152846020838601011115613c4c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613c7b57600080fd5b813567ffffffffffffffff811115613c9257600080fd5b613c9e84828501613bdb565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b803561117081613ca6565b6bffffffffffffffffffffffff8116811461267957600080fd5b803561117081613cd3565b60008060408385031215613d0b57600080fd5b8235613d1681613ca6565b91506020830135613d2681613cd3565b809150509250929050565b600081518084526020808501945080840160005b83811015613d7757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613d45565b509495945050505050565b6020815260006136926020830184613d31565b600060208284031215613da757600080fd5b5035919050565b600060208284031215613dc057600080fd5b813567ffffffffffffffff811115613dd757600080fd5b8201610160818503121561369257600080fd5b805182526020810151613e15602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613e3560408401826bffffffffffffffffffffffff169052565b506060810151613e5d606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613e79608084018267ffffffffffffffff169052565b5060a0810151613e9160a084018263ffffffff169052565b5060c0810151613eae60c084018268ffffffffffffffffff169052565b5060e0810151613ecb60e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016137818284613dea565b60008083601f840112613f2457600080fd5b50813567ffffffffffffffff811115613f3c57600080fd5b6020830191508360208260051b85010111156138f457600080fd5b60008060008060008060008060e0898b031215613f7357600080fd5b606089018a811115613f8457600080fd5b8998503567ffffffffffffffff80821115613f9e57600080fd5b613faa8c838d016138b2565b909950975060808b0135915080821115613fc357600080fd5b613fcf8c838d01613f12565b909750955060a08b0135915080821115613fe857600080fd5b50613ff58b828c01613f12565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151614062608084018268ffffffffffffffffff169052565b5060a083015161407b60a084018264ffffffffff169052565b5060c083015161409160c084018261ffff169052565b5060e08301516140c160e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b8035611170816140dd565b60008060008060006080868803121561411657600080fd5b8535614121816140dd565b9450602086013567ffffffffffffffff81111561413d57600080fd5b614149888289016138b2565b909550935050604086013561415d81613a09565b949793965091946060013592915050565b600067ffffffffffffffff8211156141885761418861393d565b5060051b60200190565b600082601f8301126141a357600080fd5b813560206141b86141b38361416e565b6139ba565b82815260059290921b840181019181810190868411156141d757600080fd5b8286015b848110156141fb5780356141ee81613ca6565b83529183019183016141db565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561423057600080fd5b863567ffffffffffffffff8082111561424857600080fd5b6142548a838b01614192565b9750602089013591508082111561426a57600080fd5b6142768a838b01614192565b965061428460408a01614206565b9550606089013591508082111561429a57600080fd5b6142a68a838b01613bdb565b94506142b460808a016140f3565b935060a08901359150808211156142ca57600080fd5b506142d789828a01613bdb565b9150509295509295509295565b6000602082840312156142f657600080fd5b813561369281613ca6565b600181811c9082168061431557607f821691505b60208210810361434e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c8101602086101561437b5750805b601f850160051c820191505b81811015610a8857828155600101614387565b67ffffffffffffffff8311156143b2576143b261393d565b6143c6836143c08354614301565b83614354565b6000601f84116001811461441857600085156143e25750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556144ae565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156144675786850135825560209485019460019092019101614447565b50868210156144a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613a26565b6000602082840312156144d257600080fd5b815161369281613a26565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115612661576126616144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614591576145916144dd565b5060010190565b600061016082360312156145ab57600080fd5b6145b3613996565b823567ffffffffffffffff8111156145ca57600080fd5b6145d636828601613bdb565b825250602083013560208201526145ef60408401613cc8565b604082015261460060608401613ced565b606082015261461160808401613a3d565b608082015261462260a084016140f3565b60a082015261463360c084016140f3565b60c082015261464460e08401613a1b565b60e0820152610100614657818501613a66565b908201526101206146698482016140f3565b9082015261014061467b848201613cc8565b9082015292915050565b60006020828403121561469757600080fd5b8135613692816140dd565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126146d757600080fd5b83018035915067ffffffffffffffff8211156146f257600080fd5b6020019150368190038213156138f457600080fd5b60006020828403121561471957600080fd5b61369282613a66565b60006020828403121561473457600080fd5b813561369281613a09565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061313660e0830184613dea565b60ff8181168382160190811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061484257614842614800565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b8082028115828204841417613781576137816144dd565b81810381811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115612661576126616144dd565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261494a8184018a613d31565b9050828103608084015261495e8189613d31565b905060ff871660a084015282810360c084015261497b8187613b7e565b905067ffffffffffffffff851660e08401528281036101008401526149a08185613b7e565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a086880312156149e257600080fd5b6149eb866149b0565b9450602086015193506040860151925060608601519150614a0e608087016149b0565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614a3957614a39614800565b92169190910492915050565b6bffffffffffffffffffffffff818116838216019080821115612661576126616144dd565b6bffffffffffffffffffffffff8181168382160280821691908281146140d5576140d56144dd565b80820180821115613781576137816144dd565b67ffffffffffffffff818116838216019080821115612661576126616144dd565b600082601f830112614ad757600080fd5b81356020614ae76141b38361416e565b82815260059290921b84018101918181019086841115614b0657600080fd5b8286015b848110156141fb5780358352918301918301614b0a565b600082601f830112614b3257600080fd5b81356020614b426141b38361416e565b82815260059290921b84018101918181019086841115614b6157600080fd5b8286015b848110156141fb57803567ffffffffffffffff811115614b855760008081fd5b614b938986838b0101613bdb565b845250918301918301614b65565b600080600080600060a08688031215614bb957600080fd5b853567ffffffffffffffff80821115614bd157600080fd5b614bdd89838a01614ac6565b96506020880135915080821115614bf357600080fd5b614bff89838a01614b21565b95506040880135915080821115614c1557600080fd5b614c2189838a01614b21565b94506060880135915080821115614c3757600080fd5b614c4389838a01614b21565b93506080880135915080821115614c5957600080fd5b50614c6688828901614b21565b9150509295509295909350565b600082614c8257614c82614800565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614cce8285018b613d31565b91508382036080850152614ce2828a613d31565b915060ff881660a085015283820360c0850152614cff8288613b7e565b90861660e085015283810361010085015290506149a08185613b7e565b805161117081613ca6565b805161117081613cd3565b8051611170816140dd565b805161117081613a09565b805161117081613a48565b60006101608284031215614d6657600080fd5b614d6e613996565b82518152614d7e60208401614d1c565b6020820152614d8f60408401614d27565b6040820152614da060608401614d1c565b6060820152614db160808401614d32565b6080820152614dc260a08401614d3d565b60a0820152614dd360c084016144b5565b60c0820152614de460e084016144b5565b60e0820152610100614df7818501614d48565b90820152610120614e09848201614d48565b90820152610140613b4f848201614d3d565b64ffffffffff818116838216019080821115612661576126616144dd565b6000610200808352614e4d8184018a613b7e565b90508281036020840152614e618189613b7e565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614eaa905060a0830184613dea565b979650505050505050565b60008060408385031215614ec857600080fd5b825160078110614ed757600080fd5b6020840151909250613d2681613cd3565b600060208284031215614efa57600080fd5b5051919050565b60008351614f13818460208801613b5a565b835190830190614f27818360208801613b5a565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
}
var FunctionsCoordinatorABI = FunctionsCoordinatorMetaData.ABI
@@ -1528,6 +1528,137 @@ func (_FunctionsCoordinator *FunctionsCoordinatorFilterer) ParseOwnershipTransfe
return event, nil
}
+type FunctionsCoordinatorRequestBilledIterator struct {
+ Event *FunctionsCoordinatorRequestBilled
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *FunctionsCoordinatorRequestBilledIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(FunctionsCoordinatorRequestBilled)
+ 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(FunctionsCoordinatorRequestBilled)
+ 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 *FunctionsCoordinatorRequestBilledIterator) Error() error {
+ return it.fail
+}
+
+func (it *FunctionsCoordinatorRequestBilledIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type FunctionsCoordinatorRequestBilled struct {
+ RequestId [32]byte
+ JuelsPerGas *big.Int
+ L1FeeShareWei *big.Int
+ CallbackCostJuels *big.Int
+ TotalCostJuels *big.Int
+ Raw types.Log
+}
+
+func (_FunctionsCoordinator *FunctionsCoordinatorFilterer) FilterRequestBilled(opts *bind.FilterOpts, requestId [][32]byte) (*FunctionsCoordinatorRequestBilledIterator, error) {
+
+ var requestIdRule []interface{}
+ for _, requestIdItem := range requestId {
+ requestIdRule = append(requestIdRule, requestIdItem)
+ }
+
+ logs, sub, err := _FunctionsCoordinator.contract.FilterLogs(opts, "RequestBilled", requestIdRule)
+ if err != nil {
+ return nil, err
+ }
+ return &FunctionsCoordinatorRequestBilledIterator{contract: _FunctionsCoordinator.contract, event: "RequestBilled", logs: logs, sub: sub}, nil
+}
+
+func (_FunctionsCoordinator *FunctionsCoordinatorFilterer) WatchRequestBilled(opts *bind.WatchOpts, sink chan<- *FunctionsCoordinatorRequestBilled, requestId [][32]byte) (event.Subscription, error) {
+
+ var requestIdRule []interface{}
+ for _, requestIdItem := range requestId {
+ requestIdRule = append(requestIdRule, requestIdItem)
+ }
+
+ logs, sub, err := _FunctionsCoordinator.contract.WatchLogs(opts, "RequestBilled", 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(FunctionsCoordinatorRequestBilled)
+ if err := _FunctionsCoordinator.contract.UnpackLog(event, "RequestBilled", 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 (_FunctionsCoordinator *FunctionsCoordinatorFilterer) ParseRequestBilled(log types.Log) (*FunctionsCoordinatorRequestBilled, error) {
+ event := new(FunctionsCoordinatorRequestBilled)
+ if err := _FunctionsCoordinator.contract.UnpackLog(event, "RequestBilled", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
type FunctionsCoordinatorTransmittedIterator struct {
Event *FunctionsCoordinatorTransmitted
@@ -1673,6 +1804,8 @@ func (_FunctionsCoordinator *FunctionsCoordinator) ParseLog(log types.Log) (gene
return _FunctionsCoordinator.ParseOwnershipTransferRequested(log)
case _FunctionsCoordinator.abi.Events["OwnershipTransferred"].ID:
return _FunctionsCoordinator.ParseOwnershipTransferred(log)
+ case _FunctionsCoordinator.abi.Events["RequestBilled"].ID:
+ return _FunctionsCoordinator.ParseRequestBilled(log)
case _FunctionsCoordinator.abi.Events["Transmitted"].ID:
return _FunctionsCoordinator.ParseTransmitted(log)
@@ -1709,6 +1842,10 @@ func (FunctionsCoordinatorOwnershipTransferred) Topic() common.Hash {
return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0")
}
+func (FunctionsCoordinatorRequestBilled) Topic() common.Hash {
+ return common.HexToHash("0x90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e046")
+}
+
func (FunctionsCoordinatorTransmitted) Topic() common.Hash {
return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62")
}
@@ -1810,6 +1947,12 @@ type FunctionsCoordinatorInterface interface {
ParseOwnershipTransferred(log types.Log) (*FunctionsCoordinatorOwnershipTransferred, error)
+ FilterRequestBilled(opts *bind.FilterOpts, requestId [][32]byte) (*FunctionsCoordinatorRequestBilledIterator, error)
+
+ WatchRequestBilled(opts *bind.WatchOpts, sink chan<- *FunctionsCoordinatorRequestBilled, requestId [][32]byte) (event.Subscription, error)
+
+ ParseRequestBilled(log types.Log) (*FunctionsCoordinatorRequestBilled, error)
+
FilterTransmitted(opts *bind.FilterOpts) (*FunctionsCoordinatorTransmittedIterator, error)
WatchTransmitted(opts *bind.WatchOpts, sink chan<- *FunctionsCoordinatorTransmitted) (event.Subscription, error)
diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 3543116d21..41524c3a82 100644
--- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -4,7 +4,7 @@ functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServ
functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
functions_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca
functions_client_example: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.bin abf32e69f268f40e8530eb8d8e96bf310b798a4c0049a58022d9d2fb527b601b
-functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 948c04942910f308942fdde460317f9ec038b6b702b018471ce6157a14a09072
+functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 96416d5be2ae4625395567397da88f71b215005cf8ad71a1cdaa56e6b5e16908
functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.bin c8dbbd5ebb34435800d6674700068837c3a252db60046a14b0e61e829db517de
functions_oracle_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
functions_router: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.bin 9dedd3a36043605fd9bedf821e7ec5b4281a5c7ae2e4a1955f37aff8ba13519f
From 22d77f95e1355986120580576632e9880ce36ffe Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Thu, 9 Nov 2023 19:53:33 -0500
Subject: [PATCH 123/327] FUN-958 - Golf golf changes, store repeated .length
as a variable (#11251)
---
.../gas-snapshots/functions.gas-snapshot | 52 +++++++++----------
.../functions/dev/v1_X/FunctionsBilling.sol | 9 ++--
.../dev/v1_X/FunctionsCoordinator.sol | 15 +++---
.../functions_coordinator.go | 2 +-
...rapper-dependency-versions-do-not-edit.txt | 2 +-
5 files changed, 41 insertions(+), 39 deletions(-)
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index af95b75df1..d15666f885 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,12 +1,12 @@
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14534216)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14534194)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14534210)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14545630)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14545607)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14545579)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14545530)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14545519)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14545563)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14534206)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14534184)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14534200)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14545620)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14545597)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14545569)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14545520)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14545509)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14545553)
FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
@@ -17,20 +17,20 @@ FunctionsBilling_GetAdminFee:test_GetAdminFee_Success() (gas: 18226)
FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 23671)
FunctionsBilling_GetDONFee:test_GetDONFee_Success() (gas: 15792)
FunctionsBilling_GetWeiPerUnitLink:test_GetWeiPerUnitLink_Success() (gas: 31773)
-FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70138)
-FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: 106295)
-FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 140174)
-FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 142502)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70128)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: 106285)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 140164)
+FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 142492)
FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13296)
FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 147278)
FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 18974)
FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 38251)
-FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8801)
+FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8810)
FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13302)
FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 180763)
FunctionsClient_Constructor:test_Constructor_Success() (gas: 7573)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 504364)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 205568)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 504354)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 205558)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14623)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22923)
FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55059)
@@ -51,17 +51,17 @@ FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 246)
FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 223)
FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 225)
FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12007)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 174037)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 164368)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 174027)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 164358)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38115)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35238)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 182513)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 182503)
FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 158055)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 327615)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 341236)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2516517)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 546996)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 158046)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 327605)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 341226)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2516507)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 546986)
FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 17983)
FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12904)
FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37159)
@@ -144,8 +144,8 @@ FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 1501
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43685, ~: 45548)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46197, ~: 48060)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14295, ~: 14295)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51089, ~: 53040)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 86057, ~: 89604)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51177, ~: 53040)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 85879, ~: 89604)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15638)
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
index bd13a3a5a1..e4b6fe7d90 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
@@ -374,15 +374,16 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
// All transmitters are assumed to also be observers
// Pay out the DON fee to all transmitters
address[] memory transmitters = _getTransmitters();
- if (transmitters.length == 0) {
+ uint256 numberOfTransmitters = transmitters.length;
+ if (numberOfTransmitters == 0) {
revert NoTransmittersSet();
}
- uint96 feePoolShare = s_feePool / uint96(transmitters.length);
+ uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters);
// Bounded by "maxNumOracles" on OCR2Abstract.sol
- for (uint256 i = 0; i < transmitters.length; ++i) {
+ for (uint256 i = 0; i < numberOfTransmitters; ++i) {
s_withdrawableTokens[transmitters[i]] += feePoolShare;
}
- s_feePool -= feePoolShare * uint96(transmitters.length);
+ s_feePool -= feePoolShare * uint96(numberOfTransmitters);
}
// Overriden in FunctionsCoordinator.sol
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
index 2caab41c74..3ee4931e97 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
@@ -142,19 +142,20 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
report,
(bytes32[], bytes[], bytes[], bytes[], bytes[])
);
+ uint256 numberOfFulfillments = uint8(requestIds.length);
if (
- requestIds.length == 0 ||
- requestIds.length != results.length ||
- requestIds.length != errors.length ||
- requestIds.length != onchainMetadata.length ||
- requestIds.length != offchainMetadata.length
+ numberOfFulfillments == 0 ||
+ numberOfFulfillments != results.length ||
+ numberOfFulfillments != errors.length ||
+ numberOfFulfillments != onchainMetadata.length ||
+ numberOfFulfillments != offchainMetadata.length
) {
revert ReportInvalid();
}
// Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig
- for (uint256 i = 0; i < requestIds.length; ++i) {
+ for (uint256 i = 0; i < numberOfFulfillments; ++i) {
FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult(
_fulfillAndBill(
requestIds[i],
@@ -162,7 +163,7 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
errors[i],
onchainMetadata[i],
offchainMetadata[i],
- uint8(requestIds.length) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig
+ uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig
)
);
diff --git a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
index 397ea3d18b..917107524b 100644
--- a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
+++ b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
@@ -72,7 +72,7 @@ type FunctionsResponseRequestMeta struct {
var FunctionsCoordinatorMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"juelsPerGas\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1FeeShareWei\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"callbackCostJuels\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalCostJuels\",\"type\":\"uint96\"}],\"name\":\"RequestBilled\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x60c06040523480156200001157600080fd5b506040516200560838038062005608833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614f856200068360003960008181610845015281816109d301528181610ca601528181610f3a015281816110450152818161183001526133b70152600061126e0152614f856000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a03660046138fb565b61059c565b005b6101a56101b5366004613aa4565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613bc8565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613c69565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613cf8565b6108d7565b6101a5610a90565b6101a5610b92565b6101a56102933660046138fb565b610d92565b6102a0610de2565b6040516102039190613d82565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613d95565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613dae565b610fd4565b6040516102039190613f03565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613f57565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b604051610203919061400e565b61053b6105363660046140fe565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004614217565b6119e3565b61057b61240f565b604051908152602001610203565b6101a56105973660046142e4565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec82848361439a565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f51848629061083690839061400e565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d291906144c0565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd2614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c31614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf5614531565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d8781614560565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec82848361439a565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e6090614301565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea890614301565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed490614301565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a883614598565b6128b2565b90506110bf60608301604084016142e4565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a08801614685565b61111f610160880161014089016142e4565b61112988806146a2565b61113b6101208b016101008c01614707565b60208b01356111516101008d0160e08e01614722565b8b6040516111679998979695949392919061473f565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d50565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a891906147e7565b6112b2919061482f565b6112bd9060016147e7565b60ff1690506112dd565b60208201516112d79060016147e7565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f2614851565b600281111561140357611403614851565b905250905060028160200151600281111561142057611420614851565b14801561146757506006816000015160ff168154811061144257611442614531565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da613893565b6000808a8a6040516114ed929190614880565b604051908190038120611504918e90602001614890565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d614531565b61157a91901a601b6147e7565b8e8e8681811061158c5761158c614531565b905060200201358d8d878181106115a5576115a5614531565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561168457611684614851565b600281111561169557611695614851565b90525092506001836020015160028111156116b2576116b2614851565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061173357611733614531565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf614531565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa6001866147e7565b9450508061180790614560565b905061154e565b50505061181f833383858e8e612e07565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd7565b98975050505050505050565b6060600c805461199b90614301565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea890614301565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b598160036148a4565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c109088613144565b60055415611dc557600554600090611c2a906001906148bb565b9050600060058281548110611c4157611c41614531565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b614531565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb6148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d646148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e38614851565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed0614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f71614851565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe5614851565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561212057612120614851565b02179055505082518051600592508390811061213e5761213e614531565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba614531565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061222481614560565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e4918491740100000000000000000000000000000000000000009004166148fd565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a0015161315d565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff1696909591949193919261491a565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c191906149ca565b5093505092505080426125d491906148bb565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b61267981613208565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b90508051600003612768576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600b54600091612787916bffffffffffffffffffffffff16614a1a565b905060005b82518110156128535781600a60008584815181106127ac576127ac614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128149190614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284c90614560565b905061278c565b5081516128609082614a6a565b600b80546000906128809084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6d576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aaa8560e001513a848860800151612fd7565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b06576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b1f9190614a92565b905060003087604001518860a001518960c001516001612b3f9190614aa5565b8a5180516020918201206101008d015160e08e0151604051612bf398979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d029190613f03565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5d8260206148a4565b612d688560206148a4565b612d7488610144614a92565b612d7e9190614a92565b612d889190614a92565b612d93906000614a92565b9050368114612dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e1986880188614ba1565b8451949950929750909550935091501580612e3657508351855114155b80612e4357508251855114155b80612e5057508151855114155b80612e5d57508051855114155b15612e94576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8551811015612fc9576000612f2e878381518110612eb757612eb7614531565b6020026020010151878481518110612ed157612ed1614531565b6020026020010151878581518110612eeb57612eeb614531565b6020026020010151878681518110612f0557612f05614531565b6020026020010151878781518110612f1f57612f1f614531565b60200260200101518c516132fd565b90506000816006811115612f4457612f44614851565b1480612f6157506001816006811115612f5f57612f5f614851565b145b15612fb857868281518110612f7857612f78614531565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc281614560565b9050612e97565b505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561303257600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b6008546000906127109061304c9063ffffffff16876148a4565b6130569190614c73565b6130609086614a92565b60085490915060009087906130999063ffffffff6c010000000000000000000000008204811691680100000000000000009004166148fd565b6130a391906148fd565b63ffffffff16905060006130ed6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b9050600061310e826130ff85876148a4565b6131099190614a92565b613753565b9050600061312a68ffffffffffffffffff808916908a16614a45565b90506131368183614a45565b9a9950505050505050505050565b600061314e610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161318199989796959493929190614c87565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133149190614d53565b905060003a82610120015183610100015161332f9190614e1b565b64ffffffffff1661334091906148a4565b905060008460ff166133886000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b6133929190614c73565b905060006133a36131098385614a92565b905060006133b03a613753565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff168961340f9190614a45565b338d6040518763ffffffff1660e01b815260040161343296959493929190614e39565b60408051808303816000875af1158015613450573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134749190614eb5565b9092509050600082600681111561348d5761348d614851565b14806134aa575060018260068111156134a8576134a8614851565b145b156136005760008e8152600760205260408120556134c88185614a45565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161353491859116614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b6135b39190614a45565b6135bd9190614a45565b6135c79190614a45565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b60004661361d81613787565b1561369957606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561366e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136929190614ee8565b9392505050565b6136a2816137aa565b1561374a5773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e84604051806080016040528060488152602001614f3160489139604051602001613702929190614f01565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161372d9190613bc8565b602060405180830381865afa15801561366e573d6000803e3d6000fd5b50600092915050565b600061378161376061240f565b61377284670de0b6b3a76400006148a4565b61377c9190614c73565b6137f1565b92915050565b600061a4b182148061379b575062066eed82145b8061378157505062066eee1490565b6000600a8214806137bc57506101a482145b806137c9575062aa37dc82145b806137d5575061210582145b806137e2575062014a3382145b8061378157505062014a341490565b60006bffffffffffffffffffffffff82111561388f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f8401126138c457600080fd5b50813567ffffffffffffffff8111156138dc57600080fd5b6020830191508360208285010111156138f457600080fd5b9250929050565b6000806020838503121561390e57600080fd5b823567ffffffffffffffff81111561392557600080fd5b613931858286016138b2565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156139905761399061393d565b60405290565b604051610160810167ffffffffffffffff811182821017156139905761399061393d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a0157613a0161393d565b604052919050565b63ffffffff8116811461267957600080fd5b803561117081613a09565b68ffffffffffffffffff8116811461267957600080fd5b803561117081613a26565b64ffffffffff8116811461267957600080fd5b803561117081613a48565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613ab757600080fd5b613abf61396c565b613ac883613a1b565b8152613ad660208401613a1b565b6020820152613ae760408401613a1b565b6040820152613af860608401613a1b565b6060820152613b0960808401613a3d565b6080820152613b1a60a08401613a5b565b60a0820152613b2b60c08401613a66565b60c0820152613b3c60e08401613a78565b60e0820152610100613b4f818501613a1b565b908201529392505050565b60005b83811015613b75578181015183820152602001613b5d565b50506000910152565b60008151808452613b96816020860160208601613b5a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006136926020830184613b7e565b600082601f830112613bec57600080fd5b813567ffffffffffffffff811115613c0657613c0661393d565b613c3760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016139ba565b818152846020838601011115613c4c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613c7b57600080fd5b813567ffffffffffffffff811115613c9257600080fd5b613c9e84828501613bdb565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b803561117081613ca6565b6bffffffffffffffffffffffff8116811461267957600080fd5b803561117081613cd3565b60008060408385031215613d0b57600080fd5b8235613d1681613ca6565b91506020830135613d2681613cd3565b809150509250929050565b600081518084526020808501945080840160005b83811015613d7757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613d45565b509495945050505050565b6020815260006136926020830184613d31565b600060208284031215613da757600080fd5b5035919050565b600060208284031215613dc057600080fd5b813567ffffffffffffffff811115613dd757600080fd5b8201610160818503121561369257600080fd5b805182526020810151613e15602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613e3560408401826bffffffffffffffffffffffff169052565b506060810151613e5d606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613e79608084018267ffffffffffffffff169052565b5060a0810151613e9160a084018263ffffffff169052565b5060c0810151613eae60c084018268ffffffffffffffffff169052565b5060e0810151613ecb60e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016137818284613dea565b60008083601f840112613f2457600080fd5b50813567ffffffffffffffff811115613f3c57600080fd5b6020830191508360208260051b85010111156138f457600080fd5b60008060008060008060008060e0898b031215613f7357600080fd5b606089018a811115613f8457600080fd5b8998503567ffffffffffffffff80821115613f9e57600080fd5b613faa8c838d016138b2565b909950975060808b0135915080821115613fc357600080fd5b613fcf8c838d01613f12565b909750955060a08b0135915080821115613fe857600080fd5b50613ff58b828c01613f12565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151614062608084018268ffffffffffffffffff169052565b5060a083015161407b60a084018264ffffffffff169052565b5060c083015161409160c084018261ffff169052565b5060e08301516140c160e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b8035611170816140dd565b60008060008060006080868803121561411657600080fd5b8535614121816140dd565b9450602086013567ffffffffffffffff81111561413d57600080fd5b614149888289016138b2565b909550935050604086013561415d81613a09565b949793965091946060013592915050565b600067ffffffffffffffff8211156141885761418861393d565b5060051b60200190565b600082601f8301126141a357600080fd5b813560206141b86141b38361416e565b6139ba565b82815260059290921b840181019181810190868411156141d757600080fd5b8286015b848110156141fb5780356141ee81613ca6565b83529183019183016141db565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561423057600080fd5b863567ffffffffffffffff8082111561424857600080fd5b6142548a838b01614192565b9750602089013591508082111561426a57600080fd5b6142768a838b01614192565b965061428460408a01614206565b9550606089013591508082111561429a57600080fd5b6142a68a838b01613bdb565b94506142b460808a016140f3565b935060a08901359150808211156142ca57600080fd5b506142d789828a01613bdb565b9150509295509295509295565b6000602082840312156142f657600080fd5b813561369281613ca6565b600181811c9082168061431557607f821691505b60208210810361434e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c8101602086101561437b5750805b601f850160051c820191505b81811015610a8857828155600101614387565b67ffffffffffffffff8311156143b2576143b261393d565b6143c6836143c08354614301565b83614354565b6000601f84116001811461441857600085156143e25750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556144ae565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156144675786850135825560209485019460019092019101614447565b50868210156144a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613a26565b6000602082840312156144d257600080fd5b815161369281613a26565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115612661576126616144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614591576145916144dd565b5060010190565b600061016082360312156145ab57600080fd5b6145b3613996565b823567ffffffffffffffff8111156145ca57600080fd5b6145d636828601613bdb565b825250602083013560208201526145ef60408401613cc8565b604082015261460060608401613ced565b606082015261461160808401613a3d565b608082015261462260a084016140f3565b60a082015261463360c084016140f3565b60c082015261464460e08401613a1b565b60e0820152610100614657818501613a66565b908201526101206146698482016140f3565b9082015261014061467b848201613cc8565b9082015292915050565b60006020828403121561469757600080fd5b8135613692816140dd565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126146d757600080fd5b83018035915067ffffffffffffffff8211156146f257600080fd5b6020019150368190038213156138f457600080fd5b60006020828403121561471957600080fd5b61369282613a66565b60006020828403121561473457600080fd5b813561369281613a09565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061313660e0830184613dea565b60ff8181168382160190811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061484257614842614800565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b8082028115828204841417613781576137816144dd565b81810381811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115612661576126616144dd565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261494a8184018a613d31565b9050828103608084015261495e8189613d31565b905060ff871660a084015282810360c084015261497b8187613b7e565b905067ffffffffffffffff851660e08401528281036101008401526149a08185613b7e565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a086880312156149e257600080fd5b6149eb866149b0565b9450602086015193506040860151925060608601519150614a0e608087016149b0565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614a3957614a39614800565b92169190910492915050565b6bffffffffffffffffffffffff818116838216019080821115612661576126616144dd565b6bffffffffffffffffffffffff8181168382160280821691908281146140d5576140d56144dd565b80820180821115613781576137816144dd565b67ffffffffffffffff818116838216019080821115612661576126616144dd565b600082601f830112614ad757600080fd5b81356020614ae76141b38361416e565b82815260059290921b84018101918181019086841115614b0657600080fd5b8286015b848110156141fb5780358352918301918301614b0a565b600082601f830112614b3257600080fd5b81356020614b426141b38361416e565b82815260059290921b84018101918181019086841115614b6157600080fd5b8286015b848110156141fb57803567ffffffffffffffff811115614b855760008081fd5b614b938986838b0101613bdb565b845250918301918301614b65565b600080600080600060a08688031215614bb957600080fd5b853567ffffffffffffffff80821115614bd157600080fd5b614bdd89838a01614ac6565b96506020880135915080821115614bf357600080fd5b614bff89838a01614b21565b95506040880135915080821115614c1557600080fd5b614c2189838a01614b21565b94506060880135915080821115614c3757600080fd5b614c4389838a01614b21565b93506080880135915080821115614c5957600080fd5b50614c6688828901614b21565b9150509295509295909350565b600082614c8257614c82614800565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614cce8285018b613d31565b91508382036080850152614ce2828a613d31565b915060ff881660a085015283820360c0850152614cff8288613b7e565b90861660e085015283810361010085015290506149a08185613b7e565b805161117081613ca6565b805161117081613cd3565b8051611170816140dd565b805161117081613a09565b805161117081613a48565b60006101608284031215614d6657600080fd5b614d6e613996565b82518152614d7e60208401614d1c565b6020820152614d8f60408401614d27565b6040820152614da060608401614d1c565b6060820152614db160808401614d32565b6080820152614dc260a08401614d3d565b60a0820152614dd360c084016144b5565b60c0820152614de460e084016144b5565b60e0820152610100614df7818501614d48565b90820152610120614e09848201614d48565b90820152610140613b4f848201614d3d565b64ffffffffff818116838216019080821115612661576126616144dd565b6000610200808352614e4d8184018a613b7e565b90508281036020840152614e618189613b7e565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614eaa905060a0830184613dea565b979650505050505050565b60008060408385031215614ec857600080fd5b825160078110614ed757600080fd5b6020840151909250613d2681613cd3565b600060208284031215614efa57600080fd5b5051919050565b60008351614f13818460208801613b5a565b835190830190614f27818360208801613b5a565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
+ Bin: "0x60c06040523480156200001157600080fd5b506040516200560838038062005608833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614f856200068360003960008181610845015281816109d301528181610ca601528181610f3a015281816110450152818161183001526133b70152600061126e0152614f856000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a03660046138fb565b61059c565b005b6101a56101b5366004613aa4565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613bc8565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613c69565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613cf8565b6108d7565b6101a5610a90565b6101a5610b92565b6101a56102933660046138fb565b610d92565b6102a0610de2565b6040516102039190613d82565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613d95565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613dae565b610fd4565b6040516102039190613f03565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613f57565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b604051610203919061400e565b61053b6105363660046140fe565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004614217565b6119e3565b61057b61240f565b604051908152602001610203565b6101a56105973660046142e4565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec82848361439a565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f51848629061083690839061400e565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d291906144c0565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd2614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c31614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf5614531565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d8781614560565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec82848361439a565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e6090614301565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea890614301565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed490614301565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a883614598565b6128b3565b90506110bf60608301604084016142e4565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a08801614685565b61111f610160880161014089016142e4565b61112988806146a2565b61113b6101208b016101008c01614707565b60208b01356111516101008d0160e08e01614722565b8b6040516111679998979695949392919061473f565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d51565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a891906147e7565b6112b2919061482f565b6112bd9060016147e7565b60ff1690506112dd565b60208201516112d79060016147e7565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f2614851565b600281111561140357611403614851565b905250905060028160200151600281111561142057611420614851565b14801561146757506006816000015160ff168154811061144257611442614531565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da613893565b6000808a8a6040516114ed929190614880565b604051908190038120611504918e90602001614890565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d614531565b61157a91901a601b6147e7565b8e8e8681811061158c5761158c614531565b905060200201358d8d878181106115a5576115a5614531565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561168457611684614851565b600281111561169557611695614851565b90525092506001836020015160028111156116b2576116b2614851565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061173357611733614531565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf614531565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa6001866147e7565b9450508061180790614560565b905061154e565b50505061181f833383858e8e612e08565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd7565b98975050505050505050565b6060600c805461199b90614301565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea890614301565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b598160036148a4565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c109088613144565b60055415611dc557600554600090611c2a906001906148bb565b9050600060058281548110611c4157611c41614531565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b614531565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb6148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d646148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e38614851565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed0614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f71614851565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe5614851565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561212057612120614851565b02179055505082518051600592508390811061213e5761213e614531565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba614531565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061222481614560565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e4918491740100000000000000000000000000000000000000009004166148fd565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a0015161315d565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff1696909591949193919261491a565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c191906149ca565b5093505092505080426125d491906148bb565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b61267981613208565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b8051909150600081900361276b576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b5460009061278a9083906bffffffffffffffffffffffff16614a1a565b905060005b828110156128555781600a60008684815181106127ae576127ae614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128169190614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284e90614560565b905061278f565b506128608282614a6a565b600b80546000906128809084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6e576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aab8560e001513a848860800151612fd7565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b07576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b209190614a92565b905060003087604001518860a001518960c001516001612b409190614aa5565b8a5180516020918201206101008d015160e08e0151604051612bf498979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d039190613f03565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5e8260206148a4565b612d698560206148a4565b612d7588610144614a92565b612d7f9190614a92565b612d899190614a92565b612d94906000614a92565b9050368114612dff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e1a86880188614ba1565b84519499509297509095509350915060ff16801580612e3a575084518114155b80612e46575083518114155b80612e52575082518114155b80612e5e575081518114155b15612e95576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612fc8576000612f2d888381518110612eb757612eb7614531565b6020026020010151888481518110612ed157612ed1614531565b6020026020010151888581518110612eeb57612eeb614531565b6020026020010151888681518110612f0557612f05614531565b6020026020010151888781518110612f1f57612f1f614531565b6020026020010151886132fd565b90506000816006811115612f4357612f43614851565b1480612f6057506001816006811115612f5e57612f5e614851565b145b15612fb757878281518110612f7757612f77614531565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc181614560565b9050612e98565b50505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561303257600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b6008546000906127109061304c9063ffffffff16876148a4565b6130569190614c73565b6130609086614a92565b60085490915060009087906130999063ffffffff6c010000000000000000000000008204811691680100000000000000009004166148fd565b6130a391906148fd565b63ffffffff16905060006130ed6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b9050600061310e826130ff85876148a4565b6131099190614a92565b613753565b9050600061312a68ffffffffffffffffff808916908a16614a45565b90506131368183614a45565b9a9950505050505050505050565b600061314e610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161318199989796959493929190614c87565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133149190614d53565b905060003a82610120015183610100015161332f9190614e1b565b64ffffffffff1661334091906148a4565b905060008460ff166133886000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b6133929190614c73565b905060006133a36131098385614a92565b905060006133b03a613753565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff168961340f9190614a45565b338d6040518763ffffffff1660e01b815260040161343296959493929190614e39565b60408051808303816000875af1158015613450573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134749190614eb5565b9092509050600082600681111561348d5761348d614851565b14806134aa575060018260068111156134a8576134a8614851565b145b156136005760008e8152600760205260408120556134c88185614a45565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161353491859116614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b6135b39190614a45565b6135bd9190614a45565b6135c79190614a45565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b60004661361d81613787565b1561369957606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561366e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136929190614ee8565b9392505050565b6136a2816137aa565b1561374a5773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e84604051806080016040528060488152602001614f3160489139604051602001613702929190614f01565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161372d9190613bc8565b602060405180830381865afa15801561366e573d6000803e3d6000fd5b50600092915050565b600061378161376061240f565b61377284670de0b6b3a76400006148a4565b61377c9190614c73565b6137f1565b92915050565b600061a4b182148061379b575062066eed82145b8061378157505062066eee1490565b6000600a8214806137bc57506101a482145b806137c9575062aa37dc82145b806137d5575061210582145b806137e2575062014a3382145b8061378157505062014a341490565b60006bffffffffffffffffffffffff82111561388f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f8401126138c457600080fd5b50813567ffffffffffffffff8111156138dc57600080fd5b6020830191508360208285010111156138f457600080fd5b9250929050565b6000806020838503121561390e57600080fd5b823567ffffffffffffffff81111561392557600080fd5b613931858286016138b2565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156139905761399061393d565b60405290565b604051610160810167ffffffffffffffff811182821017156139905761399061393d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a0157613a0161393d565b604052919050565b63ffffffff8116811461267957600080fd5b803561117081613a09565b68ffffffffffffffffff8116811461267957600080fd5b803561117081613a26565b64ffffffffff8116811461267957600080fd5b803561117081613a48565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613ab757600080fd5b613abf61396c565b613ac883613a1b565b8152613ad660208401613a1b565b6020820152613ae760408401613a1b565b6040820152613af860608401613a1b565b6060820152613b0960808401613a3d565b6080820152613b1a60a08401613a5b565b60a0820152613b2b60c08401613a66565b60c0820152613b3c60e08401613a78565b60e0820152610100613b4f818501613a1b565b908201529392505050565b60005b83811015613b75578181015183820152602001613b5d565b50506000910152565b60008151808452613b96816020860160208601613b5a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006136926020830184613b7e565b600082601f830112613bec57600080fd5b813567ffffffffffffffff811115613c0657613c0661393d565b613c3760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016139ba565b818152846020838601011115613c4c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613c7b57600080fd5b813567ffffffffffffffff811115613c9257600080fd5b613c9e84828501613bdb565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b803561117081613ca6565b6bffffffffffffffffffffffff8116811461267957600080fd5b803561117081613cd3565b60008060408385031215613d0b57600080fd5b8235613d1681613ca6565b91506020830135613d2681613cd3565b809150509250929050565b600081518084526020808501945080840160005b83811015613d7757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613d45565b509495945050505050565b6020815260006136926020830184613d31565b600060208284031215613da757600080fd5b5035919050565b600060208284031215613dc057600080fd5b813567ffffffffffffffff811115613dd757600080fd5b8201610160818503121561369257600080fd5b805182526020810151613e15602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613e3560408401826bffffffffffffffffffffffff169052565b506060810151613e5d606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613e79608084018267ffffffffffffffff169052565b5060a0810151613e9160a084018263ffffffff169052565b5060c0810151613eae60c084018268ffffffffffffffffff169052565b5060e0810151613ecb60e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016137818284613dea565b60008083601f840112613f2457600080fd5b50813567ffffffffffffffff811115613f3c57600080fd5b6020830191508360208260051b85010111156138f457600080fd5b60008060008060008060008060e0898b031215613f7357600080fd5b606089018a811115613f8457600080fd5b8998503567ffffffffffffffff80821115613f9e57600080fd5b613faa8c838d016138b2565b909950975060808b0135915080821115613fc357600080fd5b613fcf8c838d01613f12565b909750955060a08b0135915080821115613fe857600080fd5b50613ff58b828c01613f12565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151614062608084018268ffffffffffffffffff169052565b5060a083015161407b60a084018264ffffffffff169052565b5060c083015161409160c084018261ffff169052565b5060e08301516140c160e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b8035611170816140dd565b60008060008060006080868803121561411657600080fd5b8535614121816140dd565b9450602086013567ffffffffffffffff81111561413d57600080fd5b614149888289016138b2565b909550935050604086013561415d81613a09565b949793965091946060013592915050565b600067ffffffffffffffff8211156141885761418861393d565b5060051b60200190565b600082601f8301126141a357600080fd5b813560206141b86141b38361416e565b6139ba565b82815260059290921b840181019181810190868411156141d757600080fd5b8286015b848110156141fb5780356141ee81613ca6565b83529183019183016141db565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561423057600080fd5b863567ffffffffffffffff8082111561424857600080fd5b6142548a838b01614192565b9750602089013591508082111561426a57600080fd5b6142768a838b01614192565b965061428460408a01614206565b9550606089013591508082111561429a57600080fd5b6142a68a838b01613bdb565b94506142b460808a016140f3565b935060a08901359150808211156142ca57600080fd5b506142d789828a01613bdb565b9150509295509295509295565b6000602082840312156142f657600080fd5b813561369281613ca6565b600181811c9082168061431557607f821691505b60208210810361434e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c8101602086101561437b5750805b601f850160051c820191505b81811015610a8857828155600101614387565b67ffffffffffffffff8311156143b2576143b261393d565b6143c6836143c08354614301565b83614354565b6000601f84116001811461441857600085156143e25750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556144ae565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156144675786850135825560209485019460019092019101614447565b50868210156144a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613a26565b6000602082840312156144d257600080fd5b815161369281613a26565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115612661576126616144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614591576145916144dd565b5060010190565b600061016082360312156145ab57600080fd5b6145b3613996565b823567ffffffffffffffff8111156145ca57600080fd5b6145d636828601613bdb565b825250602083013560208201526145ef60408401613cc8565b604082015261460060608401613ced565b606082015261461160808401613a3d565b608082015261462260a084016140f3565b60a082015261463360c084016140f3565b60c082015261464460e08401613a1b565b60e0820152610100614657818501613a66565b908201526101206146698482016140f3565b9082015261014061467b848201613cc8565b9082015292915050565b60006020828403121561469757600080fd5b8135613692816140dd565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126146d757600080fd5b83018035915067ffffffffffffffff8211156146f257600080fd5b6020019150368190038213156138f457600080fd5b60006020828403121561471957600080fd5b61369282613a66565b60006020828403121561473457600080fd5b813561369281613a09565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061313660e0830184613dea565b60ff8181168382160190811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061484257614842614800565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b8082028115828204841417613781576137816144dd565b81810381811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115612661576126616144dd565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261494a8184018a613d31565b9050828103608084015261495e8189613d31565b905060ff871660a084015282810360c084015261497b8187613b7e565b905067ffffffffffffffff851660e08401528281036101008401526149a08185613b7e565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a086880312156149e257600080fd5b6149eb866149b0565b9450602086015193506040860151925060608601519150614a0e608087016149b0565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614a3957614a39614800565b92169190910492915050565b6bffffffffffffffffffffffff818116838216019080821115612661576126616144dd565b6bffffffffffffffffffffffff8181168382160280821691908281146140d5576140d56144dd565b80820180821115613781576137816144dd565b67ffffffffffffffff818116838216019080821115612661576126616144dd565b600082601f830112614ad757600080fd5b81356020614ae76141b38361416e565b82815260059290921b84018101918181019086841115614b0657600080fd5b8286015b848110156141fb5780358352918301918301614b0a565b600082601f830112614b3257600080fd5b81356020614b426141b38361416e565b82815260059290921b84018101918181019086841115614b6157600080fd5b8286015b848110156141fb57803567ffffffffffffffff811115614b855760008081fd5b614b938986838b0101613bdb565b845250918301918301614b65565b600080600080600060a08688031215614bb957600080fd5b853567ffffffffffffffff80821115614bd157600080fd5b614bdd89838a01614ac6565b96506020880135915080821115614bf357600080fd5b614bff89838a01614b21565b95506040880135915080821115614c1557600080fd5b614c2189838a01614b21565b94506060880135915080821115614c3757600080fd5b614c4389838a01614b21565b93506080880135915080821115614c5957600080fd5b50614c6688828901614b21565b9150509295509295909350565b600082614c8257614c82614800565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614cce8285018b613d31565b91508382036080850152614ce2828a613d31565b915060ff881660a085015283820360c0850152614cff8288613b7e565b90861660e085015283810361010085015290506149a08185613b7e565b805161117081613ca6565b805161117081613cd3565b8051611170816140dd565b805161117081613a09565b805161117081613a48565b60006101608284031215614d6657600080fd5b614d6e613996565b82518152614d7e60208401614d1c565b6020820152614d8f60408401614d27565b6040820152614da060608401614d1c565b6060820152614db160808401614d32565b6080820152614dc260a08401614d3d565b60a0820152614dd360c084016144b5565b60c0820152614de460e084016144b5565b60e0820152610100614df7818501614d48565b90820152610120614e09848201614d48565b90820152610140613b4f848201614d3d565b64ffffffffff818116838216019080821115612661576126616144dd565b6000610200808352614e4d8184018a613b7e565b90508281036020840152614e618189613b7e565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614eaa905060a0830184613dea565b979650505050505050565b60008060408385031215614ec857600080fd5b825160078110614ed757600080fd5b6020840151909250613d2681613cd3565b600060208284031215614efa57600080fd5b5051919050565b60008351614f13818460208801613b5a565b835190830190614f27818360208801613b5a565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
}
var FunctionsCoordinatorABI = FunctionsCoordinatorMetaData.ABI
diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 41524c3a82..534e5543e8 100644
--- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -4,7 +4,7 @@ functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServ
functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
functions_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca
functions_client_example: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.bin abf32e69f268f40e8530eb8d8e96bf310b798a4c0049a58022d9d2fb527b601b
-functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 96416d5be2ae4625395567397da88f71b215005cf8ad71a1cdaa56e6b5e16908
+functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 38e168fa57c9626140e1e4d05f4124b4b69bd775e6e0f4481e017ad86c4d95a0
functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.bin c8dbbd5ebb34435800d6674700068837c3a252db60046a14b0e61e829db517de
functions_oracle_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
functions_router: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.bin 9dedd3a36043605fd9bedf821e7ec5b4281a5c7ae2e4a1955f37aff8ba13519f
From 96ae30c1eecd5251f1830ba6c40b83863fe0fa65 Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Thu, 9 Nov 2023 21:24:25 -0500
Subject: [PATCH 124/327] Remove Functions OCR2Base config digest check & use
custom errors (#11249)
---
.../gas-snapshots/functions.gas-snapshot | 44 +++++++--------
.../dev/v1_X/FunctionsCoordinator.sol | 6 ++-
.../v0.8/functions/dev/v1_X/ocr/OCR2Base.sol | 54 ++++++-------------
.../functions_coordinator.go | 4 +-
...rapper-dependency-versions-do-not-edit.txt | 2 +-
5 files changed, 46 insertions(+), 64 deletions(-)
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index d15666f885..521b3bffac 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,12 +1,12 @@
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14534206)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14534184)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14534200)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14545620)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14545597)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14545569)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14545520)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14545509)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14545553)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14600662)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14600640)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14600656)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14612076)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14612053)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14612025)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14611976)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14611965)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14612009)
FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
@@ -29,8 +29,8 @@ FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8
FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13302)
FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 180763)
FunctionsClient_Constructor:test_Constructor_Success() (gas: 7573)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 504354)
-FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 205558)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 497786)
+FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 198990)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14623)
FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22923)
FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55059)
@@ -51,17 +51,17 @@ FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 246)
FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 223)
FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 225)
FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12007)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 174027)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 164358)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 167459)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 157790)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38115)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35238)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 182503)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 175935)
FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 158046)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 327605)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 341226)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2516507)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 546986)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 151478)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 321037)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 334658)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2509939)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 540418)
FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 17983)
FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12904)
FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37159)
@@ -141,11 +141,11 @@ FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Reve
FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13459)
FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 59592)
FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15010)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43685, ~: 45548)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46197, ~: 48060)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43863, ~: 45548)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46375, ~: 48060)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14295, ~: 14295)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51177, ~: 53040)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 85879, ~: 89604)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 86057, ~: 89604)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15638)
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
index 3ee4931e97..15949a497e 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
@@ -44,7 +44,7 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
address router,
Config memory config,
address linkToNativeFeed
- ) OCR2Base(true) FunctionsBilling(router, config, linkToNativeFeed) {}
+ ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed) {}
/// @inheritdoc IFunctionsCoordinator
function getThresholdPublicKey() external view override returns (bytes memory) {
@@ -151,7 +151,9 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
numberOfFulfillments != onchainMetadata.length ||
numberOfFulfillments != offchainMetadata.length
) {
- revert ReportInvalid();
+ revert ReportInvalid(
+ "All fields on the report must be of equal length: requestIds, results, errors, onchainMetadata, offchainMetadata"
+ );
}
// Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig
diff --git a/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol b/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol
index dd9ea84a51..375159bf4c 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol
@@ -10,17 +10,10 @@ import {OCR2Abstract} from "./OCR2Abstract.sol";
* doc, which refers to this contract as simply the "contract".
*/
abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
- error ReportInvalid();
+ error ReportInvalid(string message);
error InvalidConfig(string message);
- bool internal immutable i_uniqueReports;
-
- constructor(bool uniqueReports) ConfirmedOwner(msg.sender) {
- i_uniqueReports = uniqueReports;
- }
-
- // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
- uint256 private constant maxUint32 = (1 << 32) - 1;
+ constructor() ConfirmedOwner(msg.sender) {}
// incremented each time a new config is posted. This count is incorporated
// into the config digest, to prevent replay attacks.
@@ -144,12 +137,12 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
// Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol
for (uint256 i = 0; i < args.signers.length; i++) {
+ if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty");
+ if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty");
// add new signer/transmitter addresses
- // solhint-disable-next-line custom-errors
- require(s_oracles[args.signers[i]].role == Role.Unset, "repeated signer address");
+ if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address");
s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer);
- // solhint-disable-next-line custom-errors
- require(s_oracles[args.transmitters[i]].role == Role.Unset, "repeated transmitter address");
+ if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address");
s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter);
s_signers.push(args.signers[i]);
s_transmitters.push(args.transmitters[i]);
@@ -287,8 +280,7 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
ss.length *
32 + // 32 bytes per entry in _ss
0; // placeholder
- // solhint-disable-next-line custom-errors
- require(msg.data.length == expected, "calldata length mismatch");
+ if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch");
}
/**
@@ -319,30 +311,20 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
emit Transmitted(configDigest, uint32(epochAndRound >> 8));
- ConfigInfo memory configInfo = s_configInfo;
- // solhint-disable-next-line custom-errors
- require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch");
+ // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest
+ // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router
+ // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch");
_requireExpectedMsgDataLength(report, rs, ss);
- uint256 expectedNumSignatures;
- if (i_uniqueReports) {
- expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1;
- } else {
- expectedNumSignatures = configInfo.f + 1;
- }
+ uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1;
- // solhint-disable-next-line custom-errors
- require(rs.length == expectedNumSignatures, "wrong number of signatures");
- // solhint-disable-next-line custom-errors
- require(rs.length == ss.length, "signatures out of registration");
+ if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures");
+ if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length");
Oracle memory transmitter = s_oracles[msg.sender];
- // solhint-disable-next-line custom-errors
- require( // Check that sender is authorized to report
- transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index],
- "unauthorized transmitter"
- );
+ if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index])
+ revert ReportInvalid("unauthorized transmitter");
}
address[MAX_NUM_ORACLES] memory signed;
@@ -357,10 +339,8 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
for (uint256 i = 0; i < rs.length; ++i) {
address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]);
o = s_oracles[signer];
- // solhint-disable-next-line custom-errors
- require(o.role == Role.Signer, "address not authorized to sign");
- // solhint-disable-next-line custom-errors
- require(signed[o.index] == address(0), "non-unique signature");
+ if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign");
+ if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature");
signed[o.index] = signer;
signerCount += 1;
}
diff --git a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
index 917107524b..3e3fac16d1 100644
--- a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
+++ b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
@@ -71,8 +71,8 @@ type FunctionsResponseRequestMeta struct {
}
var FunctionsCoordinatorMetaData = &bind.MetaData{
- ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"juelsPerGas\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1FeeShareWei\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"callbackCostJuels\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalCostJuels\",\"type\":\"uint96\"}],\"name\":\"RequestBilled\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x60c06040523480156200001157600080fd5b506040516200560838038062005608833981016040819052620000349162000474565b8282828260013380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000140565b50505015156080526001600160a01b038116620000f457604051632530e88560e11b815260040160405180910390fd5b6001600160a01b0390811660a052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200013482620001eb565b50505050505062000633565b336001600160a01b038216036200019a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001f562000349565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033e9083906200057d565b60405180910390a150565b6200035362000355565b565b6000546001600160a01b03163314620003535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000088565b80516001600160a01b0381168114620003c957600080fd5b919050565b60405161012081016001600160401b03811182821017156200040057634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c957600080fd5b80516001600160481b0381168114620003c957600080fd5b805164ffffffffff81168114620003c957600080fd5b805161ffff81168114620003c957600080fd5b80516001600160e01b0381168114620003c957600080fd5b60008060008385036101608112156200048c57600080fd5b6200049785620003b1565b935061012080601f1983011215620004ae57600080fd5b620004b8620003ce565b9150620004c86020870162000406565b8252620004d86040870162000406565b6020830152620004eb6060870162000406565b6040830152620004fe6080870162000406565b60608301526200051160a087016200041b565b60808301526200052460c0870162000433565b60a08301526200053760e0870162000449565b60c08301526101006200054c8188016200045c565b60e08401526200055e82880162000406565b90830152509150620005746101408501620003b1565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005d060808401826001600160481b03169052565b5060a0830151620005ea60a084018264ffffffffff169052565b5060c08301516200060160c084018261ffff169052565b5060e08301516200061d60e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805160a051614f856200068360003960008181610845015281816109d301528181610ca601528181610f3a015281816110450152818161183001526133b70152600061126e0152614f856000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a03660046138fb565b61059c565b005b6101a56101b5366004613aa4565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613bc8565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613c69565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613cf8565b6108d7565b6101a5610a90565b6101a5610b92565b6101a56102933660046138fb565b610d92565b6102a0610de2565b6040516102039190613d82565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613d95565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613dae565b610fd4565b6040516102039190613f03565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004613f57565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b604051610203919061400e565b61053b6105363660046140fe565b61182c565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f661198c565b6101a561056e366004614217565b6119e3565b61057b61240f565b604051908152602001610203565b6101a56105973660046142e4565b612668565b6105a461267c565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec82848361439a565b505050565b6105f96126ff565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f51848629061083690839061400e565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d291906144c0565b905090565b6108df612707565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6126ff565b610ba2612707565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd2614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c31614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf5614531565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d8781614560565b9050610bb1565b5050565b610d9a61267c565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec82848361439a565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e6090614301565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea890614301565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed490614301565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a883614598565b6128b3565b90506110bf60608301604084016142e4565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a08801614685565b61111f610160880161014089016142e4565b61112988806146a2565b61113b6101208b016101008c01614707565b60208b01356111516101008d0160e08e01614722565b8b6040516111679998979695949392919061473f565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925290831461125c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610b0d565b61126a8b8b8b8b8b8b612d51565b60007f0000000000000000000000000000000000000000000000000000000000000000156112c7576002826020015183604001516112a891906147e7565b6112b2919061482f565b6112bd9060016147e7565b60ff1690506112dd565b60208201516112d79060016147e7565b60ff1690505b888114611346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b8887146113af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113f2576113f2614851565b600281111561140357611403614851565b905250905060028160200151600281111561142057611420614851565b14801561146757506006816000015160ff168154811061144257611442614531565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b50505050506114da613893565b6000808a8a6040516114ed929190614880565b604051908190038120611504918e90602001614890565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b8981101561180e57600060018489846020811061156d5761156d614531565b61157a91901a601b6147e7565b8e8e8681811061158c5761158c614531565b905060200201358d8d878181106115a5576115a5614531565b90506020020135604051600081526020016040526040516115e2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611604573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561168457611684614851565b600281111561169557611695614851565b90525092506001836020015160028111156116b2576116b2614851565b14611719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061173357611733614531565b602002015173ffffffffffffffffffffffffffffffffffffffff16146117b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117cf576117cf614531565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117fa6001866147e7565b9450508061180790614560565b905061154e565b50505061181f833383858e8e612e08565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b5050505066038d7ea4c68000821115611925576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061192f610841565b9050600061197287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b905061198085858385612fd7565b98975050505050505050565b6060600c805461199b90614301565b90506000036119d6576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea890614301565b855185518560ff16601f831115611a56576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611ac0576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611b4e576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611b598160036148a4565b8311611bc1576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611bc961267c565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611c109088613144565b60055415611dc557600554600090611c2a906001906148bb565b9050600060058281548110611c4157611c41614531565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611c7b57611c7b614531565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611cfb57611cfb6148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611d6457611d646148ce565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611c10915050565b60005b81515181101561222c5760006004600084600001518481518110611dee57611dee614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611e3857611e38614851565b14611e9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611ed057611ed0614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115611f7157611f71614851565b021790555060009150611f819050565b6004600084602001518481518110611f9b57611f9b614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611fe557611fe5614851565b1461204c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061207f5761207f614531565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561212057612120614851565b02179055505082518051600592508390811061213e5761213e614531565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106121ba576121ba614531565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061222481614560565b915050611dc8565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916122e4918491740100000000000000000000000000000000000000009004166148fd565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123434630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a0015161315d565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986123fa988b9891977401000000000000000000000000000000000000000090920463ffffffff1696909591949193919261491a565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c191906149ca565b5093505092505080426125d491906148bb565b836020015163ffffffff161080156125f657506000836020015163ffffffff16115b1561262457505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b60008213612661576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b61267061267c565b61267981613208565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6126fd61267c565b600b546bffffffffffffffffffffffff1660000361272157565b600061272b610de2565b8051909150600081900361276b576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b5460009061278a9083906bffffffffffffffffffffffff16614a1a565b905060005b828110156128555781600a60008684815181106127ae576127ae614531565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128169190614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508061284e90614560565b905061278f565b506128608282614a6a565b600b80546000906128809084906bffffffffffffffffffffffff1661450c565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612a6e576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612aab8560e001513a848860800151612fd7565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612b07576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612b209190614a92565b905060003087604001518860a001518960c001516001612b409190614aa5565b8a5180516020918201206101008d015160e08e0151604051612bf498979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612d039190613f03565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612d5e8260206148a4565b612d698560206148a4565b612d7588610144614a92565b612d7f9190614a92565b612d899190614a92565b612d94906000614a92565b9050368114612dff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612e1a86880188614ba1565b84519499509297509095509350915060ff16801580612e3a575084518114155b80612e46575083518114155b80612e52575082518114155b80612e5e575081518114155b15612e95576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612fc8576000612f2d888381518110612eb757612eb7614531565b6020026020010151888481518110612ed157612ed1614531565b6020026020010151888581518110612eeb57612eeb614531565b6020026020010151888681518110612f0557612f05614531565b6020026020010151888781518110612f1f57612f1f614531565b6020026020010151886132fd565b90506000816006811115612f4357612f43614851565b1480612f6057506001816006811115612f5e57612f5e614851565b145b15612fb757878281518110612f7757612f77614531565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b50612fc181614560565b9050612e98565b50505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561303257600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b6008546000906127109061304c9063ffffffff16876148a4565b6130569190614c73565b6130609086614a92565b60085490915060009087906130999063ffffffff6c010000000000000000000000008204811691680100000000000000009004166148fd565b6130a391906148fd565b63ffffffff16905060006130ed6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b9050600061310e826130ff85876148a4565b6131099190614a92565b613753565b9050600061312a68ffffffffffffffffff808916908a16614a45565b90506131368183614a45565b9a9950505050505050505050565b600061314e610de2565b511115610d8e57610d8e612707565b6000808a8a8a8a8a8a8a8a8a60405160200161318199989796959493929190614c87565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133149190614d53565b905060003a82610120015183610100015161332f9190614e1b565b64ffffffffff1661334091906148a4565b905060008460ff166133886000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061361192505050565b6133929190614c73565b905060006133a36131098385614a92565b905060006133b03a613753565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff168961340f9190614a45565b338d6040518763ffffffff1660e01b815260040161343296959493929190614e39565b60408051808303816000875af1158015613450573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134749190614eb5565b9092509050600082600681111561348d5761348d614851565b14806134aa575060018260068111156134a8576134a8614851565b145b156136005760008e8152600760205260408120556134c88185614a45565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161353491859116614a45565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b6135b39190614a45565b6135bd9190614a45565b6135c79190614a45565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b60004661361d81613787565b1561369957606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561366e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136929190614ee8565b9392505050565b6136a2816137aa565b1561374a5773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e84604051806080016040528060488152602001614f3160489139604051602001613702929190614f01565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161372d9190613bc8565b602060405180830381865afa15801561366e573d6000803e3d6000fd5b50600092915050565b600061378161376061240f565b61377284670de0b6b3a76400006148a4565b61377c9190614c73565b6137f1565b92915050565b600061a4b182148061379b575062066eed82145b8061378157505062066eee1490565b6000600a8214806137bc57506101a482145b806137c9575062aa37dc82145b806137d5575061210582145b806137e2575062014a3382145b8061378157505062014a341490565b60006bffffffffffffffffffffffff82111561388f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f8401126138c457600080fd5b50813567ffffffffffffffff8111156138dc57600080fd5b6020830191508360208285010111156138f457600080fd5b9250929050565b6000806020838503121561390e57600080fd5b823567ffffffffffffffff81111561392557600080fd5b613931858286016138b2565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff811182821017156139905761399061393d565b60405290565b604051610160810167ffffffffffffffff811182821017156139905761399061393d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a0157613a0161393d565b604052919050565b63ffffffff8116811461267957600080fd5b803561117081613a09565b68ffffffffffffffffff8116811461267957600080fd5b803561117081613a26565b64ffffffffff8116811461267957600080fd5b803561117081613a48565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613ab757600080fd5b613abf61396c565b613ac883613a1b565b8152613ad660208401613a1b565b6020820152613ae760408401613a1b565b6040820152613af860608401613a1b565b6060820152613b0960808401613a3d565b6080820152613b1a60a08401613a5b565b60a0820152613b2b60c08401613a66565b60c0820152613b3c60e08401613a78565b60e0820152610100613b4f818501613a1b565b908201529392505050565b60005b83811015613b75578181015183820152602001613b5d565b50506000910152565b60008151808452613b96816020860160208601613b5a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006136926020830184613b7e565b600082601f830112613bec57600080fd5b813567ffffffffffffffff811115613c0657613c0661393d565b613c3760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016139ba565b818152846020838601011115613c4c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613c7b57600080fd5b813567ffffffffffffffff811115613c9257600080fd5b613c9e84828501613bdb565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461267957600080fd5b803561117081613ca6565b6bffffffffffffffffffffffff8116811461267957600080fd5b803561117081613cd3565b60008060408385031215613d0b57600080fd5b8235613d1681613ca6565b91506020830135613d2681613cd3565b809150509250929050565b600081518084526020808501945080840160005b83811015613d7757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613d45565b509495945050505050565b6020815260006136926020830184613d31565b600060208284031215613da757600080fd5b5035919050565b600060208284031215613dc057600080fd5b813567ffffffffffffffff811115613dd757600080fd5b8201610160818503121561369257600080fd5b805182526020810151613e15602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613e3560408401826bffffffffffffffffffffffff169052565b506060810151613e5d606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613e79608084018267ffffffffffffffff169052565b5060a0810151613e9160a084018263ffffffff169052565b5060c0810151613eae60c084018268ffffffffffffffffff169052565b5060e0810151613ecb60e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016137818284613dea565b60008083601f840112613f2457600080fd5b50813567ffffffffffffffff811115613f3c57600080fd5b6020830191508360208260051b85010111156138f457600080fd5b60008060008060008060008060e0898b031215613f7357600080fd5b606089018a811115613f8457600080fd5b8998503567ffffffffffffffff80821115613f9e57600080fd5b613faa8c838d016138b2565b909950975060808b0135915080821115613fc357600080fd5b613fcf8c838d01613f12565b909750955060a08b0135915080821115613fe857600080fd5b50613ff58b828c01613f12565b999c989b50969995989497949560c00135949350505050565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151614062608084018268ffffffffffffffffff169052565b5060a083015161407b60a084018264ffffffffff169052565b5060c083015161409160c084018261ffff169052565b5060e08301516140c160e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461267957600080fd5b8035611170816140dd565b60008060008060006080868803121561411657600080fd5b8535614121816140dd565b9450602086013567ffffffffffffffff81111561413d57600080fd5b614149888289016138b2565b909550935050604086013561415d81613a09565b949793965091946060013592915050565b600067ffffffffffffffff8211156141885761418861393d565b5060051b60200190565b600082601f8301126141a357600080fd5b813560206141b86141b38361416e565b6139ba565b82815260059290921b840181019181810190868411156141d757600080fd5b8286015b848110156141fb5780356141ee81613ca6565b83529183019183016141db565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561423057600080fd5b863567ffffffffffffffff8082111561424857600080fd5b6142548a838b01614192565b9750602089013591508082111561426a57600080fd5b6142768a838b01614192565b965061428460408a01614206565b9550606089013591508082111561429a57600080fd5b6142a68a838b01613bdb565b94506142b460808a016140f3565b935060a08901359150808211156142ca57600080fd5b506142d789828a01613bdb565b9150509295509295509295565b6000602082840312156142f657600080fd5b813561369281613ca6565b600181811c9082168061431557607f821691505b60208210810361434e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c8101602086101561437b5750805b601f850160051c820191505b81811015610a8857828155600101614387565b67ffffffffffffffff8311156143b2576143b261393d565b6143c6836143c08354614301565b83614354565b6000601f84116001811461441857600085156143e25750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556144ae565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156144675786850135825560209485019460019092019101614447565b50868210156144a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613a26565b6000602082840312156144d257600080fd5b815161369281613a26565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115612661576126616144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614591576145916144dd565b5060010190565b600061016082360312156145ab57600080fd5b6145b3613996565b823567ffffffffffffffff8111156145ca57600080fd5b6145d636828601613bdb565b825250602083013560208201526145ef60408401613cc8565b604082015261460060608401613ced565b606082015261461160808401613a3d565b608082015261462260a084016140f3565b60a082015261463360c084016140f3565b60c082015261464460e08401613a1b565b60e0820152610100614657818501613a66565b908201526101206146698482016140f3565b9082015261014061467b848201613cc8565b9082015292915050565b60006020828403121561469757600080fd5b8135613692816140dd565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126146d757600080fd5b83018035915067ffffffffffffffff8211156146f257600080fd5b6020019150368190038213156138f457600080fd5b60006020828403121561471957600080fd5b61369282613a66565b60006020828403121561473457600080fd5b813561369281613a09565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061313660e0830184613dea565b60ff8181168382160190811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061484257614842614800565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b8082028115828204841417613781576137816144dd565b81810381811115613781576137816144dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115612661576126616144dd565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261494a8184018a613d31565b9050828103608084015261495e8189613d31565b905060ff871660a084015282810360c084015261497b8187613b7e565b905067ffffffffffffffff851660e08401528281036101008401526149a08185613b7e565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a086880312156149e257600080fd5b6149eb866149b0565b9450602086015193506040860151925060608601519150614a0e608087016149b0565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614a3957614a39614800565b92169190910492915050565b6bffffffffffffffffffffffff818116838216019080821115612661576126616144dd565b6bffffffffffffffffffffffff8181168382160280821691908281146140d5576140d56144dd565b80820180821115613781576137816144dd565b67ffffffffffffffff818116838216019080821115612661576126616144dd565b600082601f830112614ad757600080fd5b81356020614ae76141b38361416e565b82815260059290921b84018101918181019086841115614b0657600080fd5b8286015b848110156141fb5780358352918301918301614b0a565b600082601f830112614b3257600080fd5b81356020614b426141b38361416e565b82815260059290921b84018101918181019086841115614b6157600080fd5b8286015b848110156141fb57803567ffffffffffffffff811115614b855760008081fd5b614b938986838b0101613bdb565b845250918301918301614b65565b600080600080600060a08688031215614bb957600080fd5b853567ffffffffffffffff80821115614bd157600080fd5b614bdd89838a01614ac6565b96506020880135915080821115614bf357600080fd5b614bff89838a01614b21565b95506040880135915080821115614c1557600080fd5b614c2189838a01614b21565b94506060880135915080821115614c3757600080fd5b614c4389838a01614b21565b93506080880135915080821115614c5957600080fd5b50614c6688828901614b21565b9150509295509295909350565b600082614c8257614c82614800565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614cce8285018b613d31565b91508382036080850152614ce2828a613d31565b915060ff881660a085015283820360c0850152614cff8288613b7e565b90861660e085015283810361010085015290506149a08185613b7e565b805161117081613ca6565b805161117081613cd3565b8051611170816140dd565b805161117081613a09565b805161117081613a48565b60006101608284031215614d6657600080fd5b614d6e613996565b82518152614d7e60208401614d1c565b6020820152614d8f60408401614d27565b6040820152614da060608401614d1c565b6060820152614db160808401614d32565b6080820152614dc260a08401614d3d565b60a0820152614dd360c084016144b5565b60c0820152614de460e084016144b5565b60e0820152610100614df7818501614d48565b90820152610120614e09848201614d48565b90820152610140613b4f848201614d3d565b64ffffffffff818116838216019080821115612661576126616144dd565b6000610200808352614e4d8184018a613b7e565b90508281036020840152614e618189613b7e565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614eaa905060a0830184613dea565b979650505050505050565b60008060408385031215614ec857600080fd5b825160078110614ed757600080fd5b6020840151909250613d2681613cd3565b600060208284031215614efa57600080fd5b5051919050565b60008351614f13818460208801613b5a565b835190830190614f27818360208801613b5a565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
+ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"juelsPerGas\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1FeeShareWei\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"callbackCostJuels\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalCostJuels\",\"type\":\"uint96\"}],\"name\":\"RequestBilled\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ Bin: "0x60a06040523480156200001157600080fd5b50604051620057423803806200574283398101604081905262000034916200046d565b8282828233806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c28162000139565b5050506001600160a01b038116620000ed57604051632530e88560e11b815260040160405180910390fd5b6001600160a01b03908116608052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200012d82620001e4565b5050505050506200062c565b336001600160a01b03821603620001935760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee62000342565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033790839062000576565b60405180910390a150565b6200034c6200034e565b565b6000546001600160a01b031633146200034c5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000086565b80516001600160a01b0381168114620003c257600080fd5b919050565b60405161012081016001600160401b0381118282101715620003f957634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c257600080fd5b80516001600160481b0381168114620003c257600080fd5b805164ffffffffff81168114620003c257600080fd5b805161ffff81168114620003c257600080fd5b80516001600160e01b0381168114620003c257600080fd5b60008060008385036101608112156200048557600080fd5b6200049085620003aa565b935061012080601f1983011215620004a757600080fd5b620004b1620003c7565b9150620004c160208701620003ff565b8252620004d160408701620003ff565b6020830152620004e460608701620003ff565b6040830152620004f760808701620003ff565b60608301526200050a60a0870162000414565b60808301526200051d60c087016200042c565b60a08301526200053060e0870162000442565b60c08301526101006200054581880162000455565b60e084015262000557828801620003ff565b908301525091506200056d6101408501620003aa565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005c960808401826001600160481b03169052565b5060a0830151620005e360a084018264ffffffffff169052565b5060c0830151620005fa60c084018261ffff169052565b5060e08301516200061660e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b6080516150d06200067260003960008181610845015281816109d301528181610ca601528181610f3a0152818161104501528181611789015261350201526150d06000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a0366004613a46565b61059c565b005b6101a56101b5366004613bef565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613d13565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613db4565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613e43565b6108d7565b6101a5610a90565b6101a5610b92565b6101a5610293366004613a46565b610d92565b6102a0610de2565b6040516102039190613ecd565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613ee0565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613ef9565b610fd4565b604051610203919061404e565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab3660046140a2565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b6040516102039190614159565b61053b610536366004614249565b611785565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f66118e5565b6101a561056e366004614362565b61193c565b61057b6124b8565b604051908152602001610203565b6101a561059736600461442f565b612711565b6105a4612725565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec8284836144e5565b505050565b6105f96127a8565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f518486290610836908390614159565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d2919061460b565b905090565b6108df6127b0565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff16614657565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6127a8565b610ba26127b0565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd261467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c3161467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf561467c565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d87816146ab565b9050610bb1565b5050565b610d9a612725565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec8284836144e5565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e609061444c565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea89061444c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed49061444c565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a8836146e3565b61295c565b90506110bf606083016040840161442f565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a088016147d0565b61111f6101608801610140890161442f565b61112988806147ed565b61113b6101208b016101008c01614852565b60208b01356111516101008d0160e08e0161486d565b8b6040516111679998979695949392919061488a565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16111d68a8a8a8a8a8a612dfa565b6003546000906002906111f49060ff80821691610100900416614932565b6111fe919061497a565b611209906001614932565b60ff169050878114611277576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b878614611306576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f7265706f727420727320616e64207373206d757374206265206f66206571756160448201527f6c206c656e6774680000000000000000000000000000000000000000000000006064820152608401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113495761134961499c565b600281111561135a5761135a61499c565b90525090506002816020015160028111156113775761137761499c565b141580156113c057506006816000015160ff168154811061139a5761139a61467c565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b15611427576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b505050506114336139de565b6000808a8a6040516114469291906149cb565b60405190819003812061145d918e906020016149db565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b898110156117675760006001848984602081106114c6576114c661467c565b6114d391901a601b614932565b8e8e868181106114e5576114e561467c565b905060200201358d8d878181106114fe576114fe61467c565b905060200201356040516000815260200160405260405161153b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561155d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff808216855292965092945084019161010090041660028111156115dd576115dd61499c565b60028111156115ee576115ee61499c565b905250925060018360200151600281111561160b5761160b61499c565b14611672576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061168c5761168c61467c565b602002015173ffffffffffffffffffffffffffffffffffffffff161461170e576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117285761172861467c565b73ffffffffffffffffffffffffffffffffffffffff9092166020929092020152611753600186614932565b94505080611760906146ab565b90506114a7565b505050611778833383858e8e612eb1565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b15801561182557600080fd5b505afa158015611839573d6000803e3d6000fd5b5050505066038d7ea4c6800082111561187e576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611888610841565b905060006118cb87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b90506118d985858385613122565b98975050505050505050565b6060600c80546118f49061444c565b905060000361192f576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea89061444c565b855185518560ff16601f8311156119af576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611a19576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611aa7576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611ab28160036149ef565b8311611b1a576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611b22612725565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611b69908861328f565b60055415611d1e57600554600090611b8390600190614a06565b9050600060058281548110611b9a57611b9a61467c565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611bd457611bd461467c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611c5457611c54614a19565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611cbd57611cbd614a19565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611b69915050565b60005b8151518110156122d557815180516000919083908110611d4357611d4361467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611dc8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f7369676e6572206d757374206e6f7420626520656d70747900000000000000006044820152606401610b0d565b600073ffffffffffffffffffffffffffffffffffffffff1682602001518281518110611df657611df661467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611e7b576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d7074790000006044820152606401610b0d565b60006004600084600001518481518110611e9757611e9761467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611ee157611ee161499c565b14611f48576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611f7957611f7961467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561201a5761201a61499c565b02179055506000915061202a9050565b60046000846020015184815181106120445761204461467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff16600281111561208e5761208e61499c565b146120f5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff8216815260208101600281525060046000846020015184815181106121285761212861467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156121c9576121c961499c565b0217905550508251805160059250839081106121e7576121e761467c565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106122635761226361467c565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055806122cd816146ab565b915050611d21565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff438116820292909217808555920481169291829160149161238d91849174010000000000000000000000000000000000000000900416614a48565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123ec4630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a001516132a8565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986124a3988b9891977401000000000000000000000000000000000000000090920463ffffffff16969095919491939192614a65565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266a9190614b15565b50935050925050804261267d9190614a06565b836020015163ffffffff1610801561269f57506000836020015163ffffffff16115b156126cd57505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b6000821361270a576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b612719612725565b61272281613353565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146127a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6127a6612725565b600b546bffffffffffffffffffffffff166000036127ca57565b60006127d4610de2565b80519091506000819003612814576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b546000906128339083906bffffffffffffffffffffffff16614b65565b905060005b828110156128fe5781600a60008684815181106128575761285761467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128bf9190614b90565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550806128f7906146ab565b9050612838565b506129098282614bb5565b600b80546000906129299084906bffffffffffffffffffffffff16614657565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612b17576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612b548560e001513a848860800151613122565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612bb0576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612bc99190614bdd565b905060003087604001518860a001518960c001516001612be99190614bf0565b8a5180516020918201206101008d015160e08e0151604051612c9d98979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612dac919061404e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612e078260206149ef565b612e128560206149ef565b612e1e88610144614bdd565b612e289190614bdd565b612e329190614bdd565b612e3d906000614bdd565b9050368114612ea8576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612ec386880188614cec565b84519499509297509095509350915060ff16801580612ee3575084518114155b80612eef575083518114155b80612efb575082518114155b80612f07575081518114155b15612fe0576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152607060248201527f416c6c206669656c6473206f6e20746865207265706f7274206d75737420626560448201527f206f6620657175616c206c656e6774683a20726571756573744964732c20726560648201527f73756c74732c206572726f72732c206f6e636861696e4d657461646174612c2060848201527f6f6666636861696e4d657461646174610000000000000000000000000000000060a482015260c401610b0d565b60005b818110156131135760006130788883815181106130025761300261467c565b602002602001015188848151811061301c5761301c61467c565b60200260200101518885815181106130365761303661467c565b60200260200101518886815181106130505761305061467c565b602002602001015188878151811061306a5761306a61467c565b602002602001015188613448565b9050600081600681111561308e5761308e61499c565b14806130ab575060018160068111156130a9576130a961499c565b145b15613102578782815181106130c2576130c261467c565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b5061310c816146ab565b9050612fe3565b50505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561317d57600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b600854600090612710906131979063ffffffff16876149ef565b6131a19190614dbe565b6131ab9086614bdd565b60085490915060009087906131e49063ffffffff6c01000000000000000000000000820481169168010000000000000000900416614a48565b6131ee9190614a48565b63ffffffff16905060006132386000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061375c92505050565b905060006132598261324a85876149ef565b6132549190614bdd565b61389e565b9050600061327568ffffffffffffffffff808916908a16614b90565b90506132818183614b90565b9a9950505050505050505050565b6000613299610de2565b511115610d8e57610d8e6127b0565b6000808a8a8a8a8a8a8a8a8a6040516020016132cc99989796959493929190614dd2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036133d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000808480602001905181019061345f9190614e9e565b905060003a82610120015183610100015161347a9190614f66565b64ffffffffff1661348b91906149ef565b905060008460ff166134d36000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061375c92505050565b6134dd9190614dbe565b905060006134ee6132548385614bdd565b905060006134fb3a61389e565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff168961355a9190614b90565b338d6040518763ffffffff1660e01b815260040161357d96959493929190614f84565b60408051808303816000875af115801561359b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135bf9190615000565b909250905060008260068111156135d8576135d861499c565b14806135f5575060018260068111156135f3576135f361499c565b145b1561374b5760008e8152600760205260408120556136138185614b90565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161367f91859116614b90565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b6136fe9190614b90565b6137089190614b90565b6137129190614b90565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b600046613768816138d2565b156137e457606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137dd9190615033565b9392505050565b6137ed816138f5565b156138955773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e8460405180608001604052806048815260200161507c6048913960405160200161384d92919061504c565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016138789190613d13565b602060405180830381865afa1580156137b9573d6000803e3d6000fd5b50600092915050565b60006138cc6138ab6124b8565b6138bd84670de0b6b3a76400006149ef565b6138c79190614dbe565b61393c565b92915050565b600061a4b18214806138e6575062066eed82145b806138cc57505062066eee1490565b6000600a82148061390757506101a482145b80613914575062aa37dc82145b80613920575061210582145b8061392d575062014a3382145b806138cc57505062014a341490565b60006bffffffffffffffffffffffff8211156139da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f840112613a0f57600080fd5b50813567ffffffffffffffff811115613a2757600080fd5b602083019150836020828501011115613a3f57600080fd5b9250929050565b60008060208385031215613a5957600080fd5b823567ffffffffffffffff811115613a7057600080fd5b613a7c858286016139fd565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715613adb57613adb613a88565b60405290565b604051610160810167ffffffffffffffff81118282101715613adb57613adb613a88565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613b4c57613b4c613a88565b604052919050565b63ffffffff8116811461272257600080fd5b803561117081613b54565b68ffffffffffffffffff8116811461272257600080fd5b803561117081613b71565b64ffffffffff8116811461272257600080fd5b803561117081613b93565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613c0257600080fd5b613c0a613ab7565b613c1383613b66565b8152613c2160208401613b66565b6020820152613c3260408401613b66565b6040820152613c4360608401613b66565b6060820152613c5460808401613b88565b6080820152613c6560a08401613ba6565b60a0820152613c7660c08401613bb1565b60c0820152613c8760e08401613bc3565b60e0820152610100613c9a818501613b66565b908201529392505050565b60005b83811015613cc0578181015183820152602001613ca8565b50506000910152565b60008151808452613ce1816020860160208601613ca5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006137dd6020830184613cc9565b600082601f830112613d3757600080fd5b813567ffffffffffffffff811115613d5157613d51613a88565b613d8260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613b05565b818152846020838601011115613d9757600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613dc657600080fd5b813567ffffffffffffffff811115613ddd57600080fd5b613de984828501613d26565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461272257600080fd5b803561117081613df1565b6bffffffffffffffffffffffff8116811461272257600080fd5b803561117081613e1e565b60008060408385031215613e5657600080fd5b8235613e6181613df1565b91506020830135613e7181613e1e565b809150509250929050565b600081518084526020808501945080840160005b83811015613ec257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e90565b509495945050505050565b6020815260006137dd6020830184613e7c565b600060208284031215613ef257600080fd5b5035919050565b600060208284031215613f0b57600080fd5b813567ffffffffffffffff811115613f2257600080fd5b820161016081850312156137dd57600080fd5b805182526020810151613f60602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613f8060408401826bffffffffffffffffffffffff169052565b506060810151613fa8606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613fc4608084018267ffffffffffffffff169052565b5060a0810151613fdc60a084018263ffffffff169052565b5060c0810151613ff960c084018268ffffffffffffffffff169052565b5060e081015161401660e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016138cc8284613f35565b60008083601f84011261406f57600080fd5b50813567ffffffffffffffff81111561408757600080fd5b6020830191508360208260051b8501011115613a3f57600080fd5b60008060008060008060008060e0898b0312156140be57600080fd5b606089018a8111156140cf57600080fd5b8998503567ffffffffffffffff808211156140e957600080fd5b6140f58c838d016139fd565b909950975060808b013591508082111561410e57600080fd5b61411a8c838d0161405d565b909750955060a08b013591508082111561413357600080fd5b506141408b828c0161405d565b999c989b50969995989497949560c00135949350505050565b815163ffffffff9081168252602080840151821690830152604080840151821690830152606080840151918216908301526101208201905060808301516141ad608084018268ffffffffffffffffff169052565b5060a08301516141c660a084018264ffffffffff169052565b5060c08301516141dc60c084018261ffff169052565b5060e083015161420c60e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461272257600080fd5b803561117081614228565b60008060008060006080868803121561426157600080fd5b853561426c81614228565b9450602086013567ffffffffffffffff81111561428857600080fd5b614294888289016139fd565b90955093505060408601356142a881613b54565b949793965091946060013592915050565b600067ffffffffffffffff8211156142d3576142d3613a88565b5060051b60200190565b600082601f8301126142ee57600080fd5b813560206143036142fe836142b9565b613b05565b82815260059290921b8401810191818101908684111561432257600080fd5b8286015b8481101561434657803561433981613df1565b8352918301918301614326565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561437b57600080fd5b863567ffffffffffffffff8082111561439357600080fd5b61439f8a838b016142dd565b975060208901359150808211156143b557600080fd5b6143c18a838b016142dd565b96506143cf60408a01614351565b955060608901359150808211156143e557600080fd5b6143f18a838b01613d26565b94506143ff60808a0161423e565b935060a089013591508082111561441557600080fd5b5061442289828a01613d26565b9150509295509295509295565b60006020828403121561444157600080fd5b81356137dd81613df1565b600181811c9082168061446057607f821691505b602082108103614499577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c810160208610156144c65750805b601f850160051c820191505b81811015610a88578281556001016144d2565b67ffffffffffffffff8311156144fd576144fd613a88565b6145118361450b835461444c565b8361449f565b6000601f841160018114614563576000851561452d5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556145f9565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156145b25786850135825560209485019460019092019101614592565b50868210156145ed577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613b71565b60006020828403121561461d57600080fd5b81516137dd81613b71565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff82811682821603908082111561270a5761270a614628565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146dc576146dc614628565b5060010190565b600061016082360312156146f657600080fd5b6146fe613ae1565b823567ffffffffffffffff81111561471557600080fd5b61472136828601613d26565b8252506020830135602082015261473a60408401613e13565b604082015261474b60608401613e38565b606082015261475c60808401613b88565b608082015261476d60a0840161423e565b60a082015261477e60c0840161423e565b60c082015261478f60e08401613b66565b60e08201526101006147a2818501613bb1565b908201526101206147b484820161423e565b908201526101406147c6848201613e13565b9082015292915050565b6000602082840312156147e257600080fd5b81356137dd81614228565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261482257600080fd5b83018035915067ffffffffffffffff82111561483d57600080fd5b602001915036819003821315613a3f57600080fd5b60006020828403121561486457600080fd5b6137dd82613bb1565b60006020828403121561487f57600080fd5b81356137dd81613b54565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061328160e0830184613f35565b60ff81811683821601908111156138cc576138cc614628565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061498d5761498d61494b565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b80820281158282048414176138cc576138cc614628565b818103818111156138cc576138cc614628565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff81811683821601908082111561270a5761270a614628565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a958184018a613e7c565b90508281036080840152614aa98189613e7c565b905060ff871660a084015282810360c0840152614ac68187613cc9565b905067ffffffffffffffff851660e0840152828103610100840152614aeb8185613cc9565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a08688031215614b2d57600080fd5b614b3686614afb565b9450602086015193506040860151925060608601519150614b5960808701614afb565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614b8457614b8461494b565b92169190910492915050565b6bffffffffffffffffffffffff81811683821601908082111561270a5761270a614628565b6bffffffffffffffffffffffff81811683821602808216919082811461422057614220614628565b808201808211156138cc576138cc614628565b67ffffffffffffffff81811683821601908082111561270a5761270a614628565b600082601f830112614c2257600080fd5b81356020614c326142fe836142b9565b82815260059290921b84018101918181019086841115614c5157600080fd5b8286015b848110156143465780358352918301918301614c55565b600082601f830112614c7d57600080fd5b81356020614c8d6142fe836142b9565b82815260059290921b84018101918181019086841115614cac57600080fd5b8286015b8481101561434657803567ffffffffffffffff811115614cd05760008081fd5b614cde8986838b0101613d26565b845250918301918301614cb0565b600080600080600060a08688031215614d0457600080fd5b853567ffffffffffffffff80821115614d1c57600080fd5b614d2889838a01614c11565b96506020880135915080821115614d3e57600080fd5b614d4a89838a01614c6c565b95506040880135915080821115614d6057600080fd5b614d6c89838a01614c6c565b94506060880135915080821115614d8257600080fd5b614d8e89838a01614c6c565b93506080880135915080821115614da457600080fd5b50614db188828901614c6c565b9150509295509295909350565b600082614dcd57614dcd61494b565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614e198285018b613e7c565b91508382036080850152614e2d828a613e7c565b915060ff881660a085015283820360c0850152614e4a8288613cc9565b90861660e08501528381036101008501529050614aeb8185613cc9565b805161117081613df1565b805161117081613e1e565b805161117081614228565b805161117081613b54565b805161117081613b93565b60006101608284031215614eb157600080fd5b614eb9613ae1565b82518152614ec960208401614e67565b6020820152614eda60408401614e72565b6040820152614eeb60608401614e67565b6060820152614efc60808401614e7d565b6080820152614f0d60a08401614e88565b60a0820152614f1e60c08401614600565b60c0820152614f2f60e08401614600565b60e0820152610100614f42818501614e93565b90820152610120614f54848201614e93565b90820152610140613c9a848201614e88565b64ffffffffff81811683821601908082111561270a5761270a614628565b6000610200808352614f988184018a613cc9565b90508281036020840152614fac8189613cc9565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614ff5905060a0830184613f35565b979650505050505050565b6000806040838503121561501357600080fd5b82516007811061502257600080fd5b6020840151909250613e7181613e1e565b60006020828403121561504557600080fd5b5051919050565b6000835161505e818460208801613ca5565b835190830190615072818360208801613ca5565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
}
var FunctionsCoordinatorABI = FunctionsCoordinatorMetaData.ABI
diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 534e5543e8..93c4e64a3a 100644
--- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -4,7 +4,7 @@ functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServ
functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
functions_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca
functions_client_example: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.bin abf32e69f268f40e8530eb8d8e96bf310b798a4c0049a58022d9d2fb527b601b
-functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 38e168fa57c9626140e1e4d05f4124b4b69bd775e6e0f4481e017ad86c4d95a0
+functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 4e05ca5e624b7a1e604b81b84bc088818b376d533f556ba1c2ee586b7eb38b68
functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.bin c8dbbd5ebb34435800d6674700068837c3a252db60046a14b0e61e829db517de
functions_oracle_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
functions_router: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.bin 9dedd3a36043605fd9bedf821e7ec5b4281a5c7ae2e4a1955f37aff8ba13519f
From 75d0743eae6f419756f5de12ddd922a711809c35 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Fri, 10 Nov 2023 11:07:07 +0000
Subject: [PATCH 125/327] Add medianpoc to plugins dockerfile (#11247)
---
GNUmakefile | 4 ++++
plugins/chainlink.Dockerfile | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/GNUmakefile b/GNUmakefile
index 32f74e285e..69d82da6c8 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -61,6 +61,10 @@ chainlink-local-start:
install-median: ## Build & install the chainlink-median binary.
go install $(GOFLAGS) ./plugins/cmd/chainlink-median
+.PHONY: install-medianpoc
+install-medianpoc: ## Build & install the chainlink-medianpoc binary.
+ go install $(GOFLAGS) ./plugins/cmd/chainlink-medianpoc
+
.PHONY: docker ## Build the chainlink docker image
docker:
docker buildx build \
diff --git a/plugins/chainlink.Dockerfile b/plugins/chainlink.Dockerfile
index 001ee30bf7..f07fab4812 100644
--- a/plugins/chainlink.Dockerfile
+++ b/plugins/chainlink.Dockerfile
@@ -19,6 +19,9 @@ RUN make install-chainlink
# Build LOOP Plugins
RUN make install-median
+# Install medianpoc binary
+RUN make install-medianpoc
+
RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana | xargs -I % ln -s % /chainlink-solana
RUN mkdir /chainlink-starknet
RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer | xargs -I % ln -s % /chainlink-starknet/relayer
@@ -49,6 +52,7 @@ RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& apt-get clean all
COPY --from=buildgo /go/bin/chainlink /usr/local/bin/
+COPY --from=buildgo /go/bin/chainlink-medianpoc /usr/local/bin/
COPY --from=buildgo /go/bin/chainlink-median /usr/local/bin/
ENV CL_MEDIAN_CMD chainlink-median
From 0918b37d4e27c465a2e360167ad6e1ca594fe6e5 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Fri, 10 Nov 2023 15:52:08 +0100
Subject: [PATCH 126/327] solidity style guide 2.0 (#10995)
* solidity style guide 2.0
* split into rules and guidelines
* improve layout
---
contracts/STYLE.md | 234 -----------------------
contracts/STYLE_GUIDE.md | 391 +++++++++++++++++++++++++++++++++++++++
2 files changed, 391 insertions(+), 234 deletions(-)
delete mode 100644 contracts/STYLE.md
create mode 100644 contracts/STYLE_GUIDE.md
diff --git a/contracts/STYLE.md b/contracts/STYLE.md
deleted file mode 100644
index d9692a6521..0000000000
--- a/contracts/STYLE.md
+++ /dev/null
@@ -1,234 +0,0 @@
-# Solidity Style Guide
-
-## Background
-
-Our starting point is the [official Solidity Style Guide](https://solidity.readthedocs.io/en/v0.8.0/style-guide.html) and [ConsenSys's Secure Development practices](https://consensys.github.io/smart-contract-best-practices/), but we deviate in some ways. We lean heavily on [Prettier](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/.prettierrc) for formatting, and if you have to set up a new Solidity project we recommend starting with [our prettier config](https://github.com/smartcontractkit/chainlink/blob/develop/.prettierrc.js). We are trying to automate as much of this styleguide with Solhint as possible.
-
-### Code Organization
-
-- Group functionality together. E.g. Declare structs, events, and helper functions near the functions that use them. This is helpful when reading code because the related pieces are localized. It is also consistent with inheritance and libraries, which are separate pieces of code designed for a specific goal.
- - Why not follow the Solidity recommendation of grouping by visibility? Visibility is clearly defined next to the method signature, making it trivial to check. However, searching can be deceiving because of inherited methods. Given this inconsistency in grouping, we find it easier to read and more consistent to organize code around functionality. Additionally, we recommend testing the public interface for any Solidity contract to ensure it only exposes expected methods.
-
-### Delineate Unaudited Code
-
-- In a large repo it is worthwhile to keep code that has not yet been audited separate from the code that has been audited. This allows you to easily keep track of which files need to be reviewed.
- - E.g. we keep unaudited code in a directory named `dev`. Only once it has been audited we move the audited files out of `dev` and only then is it considered safe to deploy.
-
-## Variables
-
-### Visibility
-
-- All contract variables should be private. Getters should be explicitly written and documented when you want to expose a variable publicly. Whether a getter function reads from storage, a constant, or calculates a value from somewhere else, that’s all implementation details that should not be exposed to the consumer by casing or other conventions.
-
-Examples:
-
-Good:
-
-```javascript
-uint256 private s_myVar;
-
-function getMyVar() external view returns(uint256){
- return s_myVar;
-}
-```
-
-Bad:
-
-```javascript
-uint256 public s_myVar;
-```
-
-### Naming and Casing
-
-- Function arguments are named like this: `argumentName`. No leading or trailing underscores necessary.
-- Storage variables prefixed with an `s_` to make it clear that they live in storage and are expensive to read and write: `s_variableName`. They should always be private, and you should write explicit getters if you want to expose a storage variable.
-- Immutable variables should be prefixed with an `i_` to make it clear that they are immutable. E.g. `i_decimalPlaces`. They should always be private, and you should write explicit getters if you want to expose an immutable variable.
-- Internal/private constants should be all caps with underscores: `FOO_BAR`. Like other contract variables, constants should not be public. Create getter methods if you want to publicly expose constants.
-- Explicitly declare variable size: `uint256` not just `uint`. In addition to being explicit, it matches the naming used to calculate function selectors.
-
-Examples:
-
-Good:
-
-```javascript
-uint256 private s_myVar;
-uint256 private immutable i_myImmutVar;
-uint256 private constant MY_CONST_VAR;
-
-function multiplyMyVar(uint256 multiplier) external view returns(uint256){
- return multiplier * s_myVar;
-}
-```
-
-Bad:
-
-```javascript
-uint private s_myVar;
-uint256 private immutable myImmutVar;
-uint256 private constant s_myConstVar;
-
-function multiplyMyVar_(uint _multiplier) external view returns(uint256){
- return _mutliplier * s_myVar;
-}
-```
-
-### Types
-
-- If you are storing an address and know/expect it to be of a type(or interface), make the variable that type. This more clearly documents the behavior of this variable than the `address` type and often leads to less casting code whenever the address is used.
-
-Examples:
-
-Good:
-
-```javascript
-import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
-// .
-// .
-// .
-AggregatorV3Interface private s_priceFeed;
-
-constructor(address priceFeed) {
- s_priceFeed = AggregatorV3Interface(priceFeed);
-}
-```
-
-Bad:
-
-```javascript
-import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
-// .
-// .
-// .
-address private s_priceFeed;
-
-constructor(address priceFeed) {
- s_priceFeed = priceFeed;
-}
-```
-
-## Functions
-
-### Visibility
-
-- Method visibility should always be explicitly declared. Contract’s [public interfaces should be tested](https://github.com/smartcontractkit/chainlink/blob/master/contracts/test/test-helpers/helpers.ts#L221) to enforce this and make sure that internal logic is not accidentally exposed.
-
-### Naming
-
-- Function names should start with imperative verbs, not nouns or other tenses.
- - `requestData` not `dataRequest`
- - `approve` not `approved`
-- Prefix private and internal methods with an underscore. There should never be a publicly callable method starting with an underscore.
- - E.g. `_setOwner(address)`
-- Prefix your public getters with `get` and your public setters with `set`.
- - `getConfig` and `setConfig`.
-
-## Modifiers
-
-- Only extract a modifier once a check is duplicated in multiple places. Modifiers arguably hurt readability, so we have found that they are not worth extracting until there is duplication.
-- Modifiers should be treated as if they are view functions. They should not change state, only read it. While it is possible to change state in a modifier, it is unconventional and surprising.
-
-### Naming
-
-There are two common classes of modifiers, and their name should be prefixed accordingly to quickly represent their behavior:
-
-- Control flow modifiers: Prefix the modifier name with `if` in the case that a modifier only enables or disables the subsequent code in the modified method, but does not revert.
-- Reverting modifiers: Prefix the modifier name with `validate` in the case that a modifier reverts if a condition is not met.
-
-### Return Values
-
-- If an address is cast as a contract type, return the type, do not cast back to the address type. This prevents the consumer of the method signature from having to cast again, but presents an equivalent API for off-chain APIs. Additionally it is a more declarative API, providing more context if we return a type.
-
-## Events
-
-- Events should only be triggered on state changes. If the value is set but not changed, we prefer avoiding a log emission indicating a change. (e.g. Either do not emit a log, or name the event `ConfigSet` instead of `ConfigUpdated`.)
-
-### Naming
-
-- When possible event names should correspond to the method they are in or the action that is being taken. Events preferably follow the format , where the action performed is the past tense of the imperative verb in the method name. e.g. calling `setConfig` should emit an event called `ConfigSet`, not `ConfigUpdated` in a method named `setConfig`.
-
-## Errors
-
-### Use Custom Errors
-
-Whenever possible (Solidity v0.8+) use [custom errors](https://blog.soliditylang.org/2021/04/21/custom-errors/) instead of emitting strings. This saves contract code size and simultaneously provides more informative error messages.
-
-### Expose Errors
-
-It is common to call a contract and then check the call succeeded:
-
-```javascript
-(bool success, ) = to.call(data);
-require(success, "Contract call failed");
-```
-
-While this may look descriptive it swallows the error. Instead bubble up the error:
-
-```javascript
-error YourError(bytes response);
-
-(bool success, bytes memory response) = to.call(data);
-if (!success) { revert YourError(response); }
-```
-
-This will cost slightly more gas to copy the response into memory, but will ultimately make contract usage more understandable and easier to debug. Whether it is worth the extra gas is a judgement call you’ll have to make based on your needs.
-
-The original error will not be human readable in an off-chain explorer because it is RLP hex encoded but is easily decoded with standard Solidity ABI decoding tools, or a hex to UTF-8 converter and some basic ABI knowledge.
-
-## Control Flow
-
-### `if` Statements
-
-Always wrap the result statement of your `if` conditions in a closure, even if it is only one line.
-
-Bad:
-
-```javascript
- if (condition) statement;
-```
-
-Good:
-
-```javascript
- if (condition) { statement; }
-```
-
-## Interfaces
-
-### Scope
-
-- Interfaces should be as concise as reasonably possible. Break it up into smaller composable interfaces when that is sensible.
-
-### Naming
-
-- Up through Solidity version 0.8: Interfaces should be named `FooInterface`, this follows our historical naming pattern.
-- Starting in Solidity v0.9: Interfaces should be named `IFoo` instead of `FooInterface`. This follows the patterns of popular [libraries like OpenZeppelin’s](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L9).
-
-## Vendor Dependencies
-
-- That’s it, vendor your Solidity dependencies. Supply chain attacks are all the rage these days. There is not yet a silver bullet for best way to vendor, it depends on the size of your project and your needs. You should be as explicit as possible about where the code comes from and make sure that this is enforced in some way; e.g. reference a hash. Some options:
- - NPM packages work for repos already in the JavaScript ecosystem. If you go this route you should lock to a hash of the repo or use a proxy registry like GitHub Packages.
- - Git submodules are great if you don’t mind git submodules.
- - Copy and paste the code into a `vendor` directory. Record attribution of the code and license in the repo along with the commit or version that you pulled the code from.
-
-## Common Behaviors
-
-### Transferring Ownership
-
-- When transferring control, whether it is of a token or a role in a contract, prefer "safe ownership" transfer patterns where the recipient must accept ownership. This avoids accidentally burning the control. This is also inline with the secure pattern of [prefer pull over push](https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls).
-
-### Use Factories
-
-- If you expect multiple instances of a contract to be deployed, it is probably best to [build a factory](https://www.quicknode.com/guides/solidity/how-to-create-a-smart-contract-factory-in-solidity-using-hardhat) as this allows for simpler deployments later. Additionally it reduces the burden of verifying the correctness of the contract deployment. If many people have to deploy an instance of a contract then doing so with a contract makes it much easier for verification because instead of checking the code hash and/or the compiler and maybe the source code, you only have to check that the contract was deployed through a factory.
-- Factories can add some pain when deploying with immutable variables. In general it is difficult to parse those out immutable variables from internal transactions. There is nothing inherently wrong with contracts deployed in this manner but at the time of writing they may not easily verify on Etherscan.
-
-### Call with Exact Gas
-
-- `call` accepts a gas parameter, but that parameter is a ceiling on gas usage. If a transaction does not have enough gas, `call` will simply provide as much gas as it safely can. This is unintuitive and can lead to transactions failing for unexpected reasons. We have [an implementation of `callWithExactGas`](https://github.com/smartcontractkit/chainlink/blob/075f3e2caf61b8685d2dc78714f1ee39764fda17/contracts/src/v0.8/KeeperRegistry.sol#L792) to ensure the precise gas amount requested is provided.
-
-## Picking a Pragma
-
-- If a contract or library is expected to be imported by outside parties then the pragma should be kept as loose as possible without sacrificing safety. We publish versions for every minor semver version of Solidity, and maintain a corresponding set of tests for each published version.
- - Examples: libraries, interfaces, abstract contracts, and contracts expected to be inherited from
-- Otherwise, Solidity contracts should have a pragma which is locked to a specific version.
- - Example: Most concrete contracts.
-- Avoid changing pragmas after audit. Unless there is a bug that has affects your contract, then you should try to stick to a known good pragma. In practice this means we typically only support one (occasionally two) pragma for any “major”(minor by semver naming) Solidity version.
diff --git a/contracts/STYLE_GUIDE.md b/contracts/STYLE_GUIDE.md
new file mode 100644
index 0000000000..3868117d4b
--- /dev/null
+++ b/contracts/STYLE_GUIDE.md
@@ -0,0 +1,391 @@
+# Structure
+
+This guide is split into two sections: [Guidelines](#guidelines) and [Rules](#rules).
+Guidelines are recommendations that should be followed but are hard to enforce in an automated way.
+Rules are all enforced through CI, this can be through Solhint rules or other tools.
+
+## Background
+
+Our starting point is the [official Solidity Style Guide](https://docs.soliditylang.org/en/v0.8.21/style-guide.html) and [ConsenSys's Secure Development practices](https://consensys.github.io/smart-contract-best-practices/), but we deviate in some ways. We lean heavily on [Prettier](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/.prettierrc) for formatting, and if you have to set up a new Solidity project we recommend starting with [our prettier config](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/.prettierrc). We are trying to automate as much of this styleguide with Solhint as possible.
+
+This guide is not meant to be applied retroactively. There is no need to rewrite existing code to adhere to this guide, and when making (small) changes in existing files, it is not required to do so in accordance to this guide if it would conflict with other practices in that existing file. Consistency is preferred.
+
+We will be looking into `forge fmt`, but for now we still use `prettier`.
+
+
+# Guidelines
+
+## Code Organization
+- Group functionality together. E.g. Declare structs, events, and helper functions near the functions that use them. This is helpful when reading code because the related pieces are localized. It is also consistent with inheritance and libraries, which are separate pieces of code designed for a specific goal.
+- 🤔Why not follow the Solidity recommendation of grouping by visibility? Visibility is clearly defined next to the method signature, making it trivial to check. However, searching can be deceiving because of inherited methods. Given this inconsistency in grouping, we find it easier to read and more consistent to organize code around functionality. Additionally, we recommend testing the public interface for any Solidity contract to ensure it only exposes expected methods.
+- Follow the [Solidity folder structure CLIP](https://github.com/smartcontractkit/CLIPs/tree/main/clips/2023-04-13-solidity-folder-structure)
+
+### Delineate Unaudited Code
+
+- In a large repo it is worthwhile to keep code that has not yet been audited separate from the code that has been audited. This allows you to easily keep track of which files need to be reviewed.
+ - E.g. we keep unaudited code in a directory named `dev` that exists within each projects folder. Only once it has been audited we move the audited files out of `dev` and only then is it considered safe to deploy.
+ - This `dev` folder also has implications for when code is valid for bug bounties, so be extra careful to move functionality out of a `dev` folder.
+
+
+## comments
+- Besides comment above functions/structs, comments should live everywhere a reader might be confused.
+ Don’t overestimate the reader of your contract, expect confusion in many places and document accordingly.
+ This will help massively during audits and onboarding new team members.
+- Headers should be used to group functionality, the following header style and length is recommended.
+ - Don’t use headers for a single function, or to say “getters”. Group by functionality e.g. the `Tokens and pools` , or `fees` logic within the CCIP OnRamp.
+
+```solidity
+ // ================================================================
+ // │ Tokens and pools │
+ // ================================================================
+
+....
+
+ // ================================================================
+ // │ Fees │
+ // ================================================================
+```
+
+## Variables
+
+- Function arguments are named like this: `argumentName`. No leading or trailing underscores necessary.
+- Names should be explicit on the unit it contains, e.g. a network fee that is charged in USD cents
+
+```solidity
+uint256 fee; // bad
+uint256 networkFee; // bad
+uint256 networkFeeUSD; // bad
+uint256 networkFeeUSDCents; // good
+```
+
+### Types
+
+- If you are storing an address and know/expect it to be of a type(or interface), make the variable that type. This more clearly documents the behavior of this variable than the `address` type and often leads to less casting code whenever the address is used.
+
+### Structs
+
+- All structs should be packed to have the lowest memory footprint to reduce gas usage. Even structs that will never be written to storage should be packed.
+ - A contract can be considered a struct; it should also be packed to reduce gas cost.
+- Structs should contain struct packing comments to clearly indicate the storage slot layout
+ - Using the exact characters from the example below will ensure visually appealing struct packing comments.
+ - Notice there is no line on the unpacked last `fee` item.
+- Struct should contain comments, clearly indicating the denomination of values e.g. 0.01 USD if the variable name doesn’t already do that (which it should).
+ - Simple tool that could help packing structs and adding comments: https://github.com/RensR/Spack
+
+```solidity
+/// @dev Struct to hold the fee configuration for a fee token, same as the FeeTokenConfig but with
+/// token included so that an array of these can be passed in to setFeeTokenConfig to set the mapping
+struct FeeTokenConfigArgs {
+ address token; // ────────────╮ Token address
+ uint32 networkFeeUSD; // │ Flat network fee to charge for messages, multiples of 0.01 USD
+ // │ multiline comments should work like this. More fee info
+ uint64 gasMultiplier; // ─────╯ Price multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost
+ uint64 premiumMultiplier; // ─╮ Multiplier for fee-token-specific premiums
+ bool enabled; // ─────────────╯ Whether this fee token is enabled
+ uint256 fee; // The flat fee the user pays in juels
+}
+```
+## Functions
+
+### Naming
+
+- Function names should start with imperative verbs, not nouns or other tenses.
+ - `requestData` not `dataRequest`
+ - `approve` not `approved`
+ - `getFeeParameters` not `feeParameters`
+
+- Prefix your public getters with `get` and your public setters with `set`.
+ - `getConfig` and `setConfig`.
+
+### Return Values
+
+- If an address is cast as a contract type, return the type, do not cast back to the address type.
+ This prevents the consumer of the method signature from having to cast again, but presents an equivalent API for off-chain APIs.
+ Additionally, it is a more declarative API, providing more context if we return a type.
+
+## Modifiers
+
+- Only extract a modifier once a check is duplicated in multiple places. Modifiers arguably hurt readability, so we have found that they are not worth extracting until there is duplication.
+- Modifiers should be treated as if they are view functions. They should not change state, only read it. While it is possible to change state in a modifier, it is unconventional and surprising.
+- Modifiers tend to bloat contract size because the code is duplicated wherever the modifier is used.
+
+## Events
+
+- Events should only be triggered on state changes. If the value is set but not changed, we prefer avoiding a log emission indicating a change. (e.g. Either do not emit a log, or name the event `ConfigSet` instead of `ConfigUpdated`.)
+- Events should be emitted for all state changes, not emitting should be an exception
+- When possible event names should correspond to the method they are in or the action that is being taken. Events preferably follow the format , where the action performed is the past tense of the imperative verb in the method name. e.g. calling `setConfig` should emit an event called `ConfigSet`, not `ConfigUpdated` in a method named `setConfig`.
+
+
+### Expose Errors
+
+It is common to call a contract and then check the call succeeded:
+
+```solidity
+(bool success, ) = to.call(data);
+require(success, "Contract call failed");
+```
+
+While this may look descriptive it swallows the error. Instead, bubble up the error:
+
+```solidity
+bool success;
+retData = new bytes(maxReturnBytes);
+assembly {
+ // call and return whether we succeeded. ignore return data
+ // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength)
+ success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0, 0)
+
+ // limit our copy to maxReturnBytes bytes
+ let toCopy := returndatasize()
+ if gt(toCopy, maxReturnBytes) {
+ toCopy := maxReturnBytes
+ }
+ // Store the length of the copied bytes
+ mstore(retData, toCopy)
+ // copy the bytes from retData[0:_toCopy]
+ returndatacopy(add(retData, 0x20), 0, toCopy)
+}
+return (success, retData);
+```
+
+This will cost slightly more gas to copy the response into memory, but will ultimately make contract usage more understandable and easier to debug. Whether it is worth the extra gas is a judgement call you’ll have to make based on your needs.
+
+The original error will not be human-readable in an off-chain explorer because it is RLP hex encoded but is easily decoded with standard Solidity ABI decoding tools, or a hex to UTF-8 converter and some basic ABI knowledge.
+
+
+## Interfaces
+
+- Interfaces should be as concise as reasonably possible. Break it up into smaller composable interfaces when that is sensible.
+
+## Dependencies
+
+- Prefer not reinventing the wheel, especially if there is an Openzeppelin wheel.
+- The `shared` folder can be treated as a first party dependency and it is recommend to check if some functionality might already be in there before either writing it yourself or adding a third party dependency.
+- When we have reinvented the wheel already (like with ownership), it is OK to keep using these contracts. If there are clear benefits of using another standard like OZ, we can deprecate the custom implementation and start using the new standard in all new projects. Migration will not be required unless there are serious issues with the old implementation.
+- When the decision is made to use a new standard, it is no longer allowed to use the old standard for new projects.
+
+### Vendor dependencies
+
+- That’s it, vendor your Solidity dependencies. Supply chain attacks are all the rage these days. There is not yet a silver bullet for best way to vendor, it depends on the size of your project and your needs. You should be as explicit as possible about where the code comes from and make sure that this is enforced in some way; e.g. reference a hash. Some options:
+ - NPM packages work for repos already in the JavaScript ecosystem. If you go this route you should lock to a hash of the repo or use a proxy registry like GitHub Packages.
+ - Copy and paste the code into a `vendor` directory. Record attribution of the code and license in the repo along with the commit or version that you pulled the code from.
+ - Foundry uses git submodules for its dependencies. We only use the `forge-std` lib through submodules, we don’t import any non-Foundry-testing code through this method.
+
+
+## Common Behaviors
+
+### Transferring Ownership
+
+- When transferring control, whether it is of a token or a role in a contract, prefer "safe ownership" transfer patterns where the recipient must accept ownership. This avoids accidentally burning the control. This is also inline with the secure pattern of [prefer pull over push](https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls).
+
+### Call with Exact Gas
+
+- `call` accepts a gas parameter, but that parameter is a ceiling on gas usage. If a transaction does not have enough gas, `call` will simply provide as much gas as it safely can. This is unintuitive and can lead to transactions failing for unexpected reasons. We have [an implementation of `callWithExactGas`](https://github.com/smartcontractkit/chainlink/blob/075f3e2caf61b8685d2dc78714f1ee39764fda17/contracts/src/v0.8/KeeperRegistry.sol#L792) to ensure the precise gas amount requested is provided.
+
+### Sending tokens
+
+- Prefer [ERC20.safeTransfer](https://docs.openzeppelin.com/contracts/2.x/api/token/erc20#SafeERC20) over ERC20.transfer
+
+### Gas golfing
+
+- Golf your code. Make it cheap, within reason.
+ - Focus on the hot path
+- Most of the cost of executing Solidity is related to reading/writing storage
+- Calling other contracts will also be costly
+- Common types to safely use are
+ - uint40 for timestamps (or uint32 if you really need the space)
+ - uint96 for link, as there are only 1b link tokens
+- prefer `++i` over `i++`
+- If you’re unsure about golfing, ask in the #tech-solidity channel
+
+## Testing
+
+- Test using Foundry.
+- Aim for at least 90% *useful* coverage as a baseline, but (near) 100% is achievable in Solidity. Always 100% test the critical path.
+ - Make sure to test for each event emitted
+ - Test each reverting path
+- Consider fuzzing, start with stateless (very easy in Foundry) and if that works, try stateful fuzzing.
+- Consider fork testing if applicable
+
+### Foundry
+
+- Create a Foundry profile for each project folder in `foundry.toml`
+- Foundry tests live in the project folder in `src`, not in the `contracts/test/` folder
+- Set the block number and timestamp. It is preferred to set these values to some reasonable value close to reality.
+- There should be no code between `vm.expectEmit`/`vm.expectRevert` and the function call
+
+## Picking a Pragma
+
+- If a contract or library is expected to be imported by outside parties then the pragma should be kept as loose as possible without sacrificing safety. We publish versions for every minor semver version of Solidity, and maintain a corresponding set of tests for each published version.
+ - Examples: libraries, interfaces, abstract contracts, and contracts expected to be inherited from
+- Otherwise, Solidity contracts should have a pragma which is locked to a specific version.
+ - Example: Most concrete contracts.
+- Avoid changing pragmas after audit. Unless there is a bug that has affects your contract, then you should try to stick to a known good pragma. In practice this means we typically only support one (occasionally two) pragma for any “major”(minor by semver naming) Solidity version.
+- The current advised pragma is `0.8.19` or higher, lower versions should be avoided when starting a new project. Newer versions can be considered.
+- All contracts should have a SPDX license identifier. If unsure about which one to pick, please consult with legal. Most older contracts have been MIT, but some of the newer products have been using BUSL-1.1
+
+
+## Versioning
+
+Contracts should implement the following interface
+
+```solidity
+interface ITypeAndVersion {
+ function typeAndVersion() external pure returns (string memory);
+}
+```
+
+Here are some examples of what this should look like:
+
+```solidity
+contract AccessControlledFoo is Foo {
+ // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
+ string public constant override typeAndVersion = "AccessControlledFoo 1.0.0";
+}
+
+contract OffchainAggregator is ITypeAndVersion {
+ // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
+ string public constant override typeAndVersion = "OffchainAggregator 1.0.0";
+
+ function getData() public returns(uint256) {
+ return 4;
+ }
+}
+
+// Next version of Aggregator contract
+contract SuperDuperAggregator is ITypeAndVersion {
+ /// This is a new contract that has not been released yet, so we
+ /// add a `-dev` suffix to the typeAndVersion.
+
+ // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
+ string public constant override typeAndVersion = "SuperDuperAggregator 1.1.0-dev";
+
+ function getData() public returns(uint256) {
+ return 5;
+ }
+}
+```
+
+All contracts will expose a `typeAndVersion` constant.
+The string has the following format: `-` with the `-dev` part only being applicable to contracts that have not been fully released.
+Try to fit it into 32 bytes to keep impact on contract sizes minimal.
+Solhint will complain about a public constant variable that isn’t FULL_CAPS without the solhint-disable comment.
+
+
+
+
+
+
+
+
+
+
+# Rules
+
+All rules have a `rule` tag which indicated how the rule is enforced.
+
+
+## Comments
+
+- Comments should be in the `//` (default) or `///` (natspec) format, not the `/* */` format.
+ - rule: `tbd`
+- Comments should follow [NatSpec](https://docs.soliditylang.org/en/latest/natspec-format.html)
+ - rule: `tbd`
+
+## Imports
+
+- Imports should always be explicit
+ - rule: `no-global-import`
+- Imports have follow the following format:
+ - rule: `tbd`
+
+```solidity
+import {IInterface} from "../interfaces/IInterface.sol";
+
+import {AnythingElse} from "../code/AnythingElse.sol";
+
+import {ThirdPartyCode} from "../../vendor/ThirdPartyCode.sol";
+```
+
+- An example would be
+
+```solidity
+import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol";
+import {IPool} from "../interfaces/pools/IPool.sol";
+
+import {AggregateRateLimiter} from "../AggregateRateLimiter.sol";
+import {Client} from "../libraries/Client.sol";
+
+import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol";
+import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
+```
+
+## Variables
+
+### Visibility
+
+All contract variables should be private by default. Getters should be explicitly written and documented when you want to expose a variable publicly.
+Whether a getter function reads from storage, a constant, or calculates a value from somewhere else, that’s all implementation details that should not be exposed to the consumer by casing or other conventions.
+
+rule: tbd
+
+### Naming and Casing
+
+- Storage variables prefixed with an `s_` to make it clear that they live in storage and are expensive to read and write: `s_variableName`. They should always be private, and you should write explicit getters if you want to expose a storage variable.
+ - rule: `chainlink-solidity/prefix-storage-variables-with-s-underscore`
+- Immutable variables should be prefixed with an `i_` to make it clear that they are immutable. E.g. `i_decimalPlaces`. They should always be private, and you should write explicit getters if you want to expose an immutable variable.
+ - rule: `chainlink-solidity/prefix-immutable-variables-with-i`
+- Internal/private constants should be all caps with underscores: `FOO_BAR`. Like other contract variables, constants should not be public. Create getter methods if you want to publicly expose constants.
+ - rule: `chainlink-solidity/all-caps-constant-storage-variables`
+- Explicitly declare variable size: `uint256` not just `uint`. In addition to being explicit, it matches the naming used to calculate function selectors.
+ - rule: `explicit-types`
+- Mapping should always be named if Solidity allows it (≥0.8.18)
+ - rule: `tbd`
+
+
+## Functions
+
+### Visibility
+
+- Method visibility should always be explicitly declared.
+ - rule: `state-visibility`
+
+- Prefix private and internal methods with an underscore. There should never be a publicly callable method starting with an underscore.
+ - E.g. `_setOwner(address)`
+ - rule: `chainlink-solidity/prefix-internal-functions-with-underscore`
+
+### Return values
+
+- Returned values should always be explicit. Using named return values and then returning with an empty return should be avoided
+ - rule: `chainlink-solidity/explicit-returns`
+
+```solidity
+// Bad
+function getNum() external view returns (uint64 num) {
+ num = 4;
+ return;
+}
+
+// Good
+function getNum() external view returns (uint64 num) {
+ num = 4;
+ return num;
+}
+
+// Good
+function getNum() external view returns (uint64 num) {
+ return 4;
+}
+```
+
+## Errors
+
+Use [custom errors](https://blog.soliditylang.org/2021/04/21/custom-errors/) instead of emitting strings. This saves contract code size and simultaneously provides more informative error messages.
+
+rule: `custom-errors`
+
+## Interfaces
+
+Interfaces should be named `IFoo` instead of `FooInterface`. This follows the patterns of popular [libraries like OpenZeppelin’s](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L9).
+
+rule: `tbd`
\ No newline at end of file
From 41025f45fcf3c5e7135d03f0e77dfb66ee770163 Mon Sep 17 00:00:00 2001
From: Tate
Date: Fri, 10 Nov 2023 08:37:12 -0700
Subject: [PATCH 127/327] [TT-689] Send slack notification on test base image
build/publish failure (#11248)
---
.github/workflows/integration-tests-publish.yml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml
index 60f67f0357..a66ea61228 100644
--- a/.github/workflows/integration-tests-publish.yml
+++ b/.github/workflows/integration-tests-publish.yml
@@ -37,3 +37,11 @@ jobs:
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 }}
+ - name: Notify Slack
+ if: failure()
+ uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
+ env:
+ SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
+ with:
+ channel-id: "#team-test-tooling-internal"
+ slack-message: ":x: :mild-panic-intensifies: Publish Integration Test Image failed: ${{ job.html_url }}\n${{ format('https://github.com/smartcontractkit/chainlink/actions/runs/{0}', github.run_id) }}"
From 4a6f2fe749e19d92be013b9b8f59cefe829b07eb Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Fri, 10 Nov 2023 19:52:39 +0100
Subject: [PATCH 128/327] turn off 0.6 & 0.7 tests (#11132)
* turn off 0.6 tests
* reduce splits and mark other tests as sow
* add modification protection
* rm 0.7 tests
---
.github/workflows/solidity.yml | 18 +
contracts/ci.json | 22 +-
contracts/test/v0.6/AggregatorFacade.test.ts | 167 -
contracts/test/v0.6/BasicConsumer.test.ts | 243 --
contracts/test/v0.6/BlockhashStore.test.ts | 285 --
contracts/test/v0.6/Chainlink.test.ts | 186 -
contracts/test/v0.6/ChainlinkClient.test.ts | 376 --
contracts/test/v0.6/CheckedMath.test.ts | 183 -
.../v0.6/DeviationFlaggingValidator.test.ts | 296 --
contracts/test/v0.6/Flags.test.ts | 405 --
contracts/test/v0.6/FluxAggregator.test.ts | 3252 --------------
contracts/test/v0.6/Median.test.ts | 237 -
contracts/test/v0.6/Owned.test.ts | 84 -
contracts/test/v0.6/SignedSafeMath.test.ts | 187 -
.../v0.6/SimpleReadAccessController.test.ts | 250 --
.../v0.6/SimpleWriteAccessController.test.ts | 214 -
contracts/test/v0.6/VRFD20.test.ts | 303 --
contracts/test/v0.7/AggregatorProxy.test.ts | 743 ----
.../test/v0.7/AuthorizedForwarder.test.ts | 444 --
contracts/test/v0.7/Chainlink.test.ts | 186 -
contracts/test/v0.7/ChainlinkClient.test.ts | 454 --
.../CompoundPriceFlaggingValidator.test.ts | 471 --
contracts/test/v0.7/ConfirmedOwner.test.ts | 136 -
contracts/test/v0.7/KeeperRegistry1_1.test.ts | 1725 --------
contracts/test/v0.7/Operator.test.ts | 3819 -----------------
contracts/test/v0.7/OperatorFactory.test.ts | 293 --
.../v0.7/StalenessFlaggingValidator.test.ts | 632 ---
.../v0.7/UpkeepRegistrationRequests.test.ts | 603 ---
contracts/test/v0.7/VRFD20.test.ts | 303 --
contracts/test/v0.7/gasUsage.test.ts | 178 -
30 files changed, 27 insertions(+), 16668 deletions(-)
delete mode 100644 contracts/test/v0.6/AggregatorFacade.test.ts
delete mode 100644 contracts/test/v0.6/BasicConsumer.test.ts
delete mode 100644 contracts/test/v0.6/BlockhashStore.test.ts
delete mode 100644 contracts/test/v0.6/Chainlink.test.ts
delete mode 100644 contracts/test/v0.6/ChainlinkClient.test.ts
delete mode 100644 contracts/test/v0.6/CheckedMath.test.ts
delete mode 100644 contracts/test/v0.6/DeviationFlaggingValidator.test.ts
delete mode 100644 contracts/test/v0.6/Flags.test.ts
delete mode 100644 contracts/test/v0.6/FluxAggregator.test.ts
delete mode 100644 contracts/test/v0.6/Median.test.ts
delete mode 100644 contracts/test/v0.6/Owned.test.ts
delete mode 100644 contracts/test/v0.6/SignedSafeMath.test.ts
delete mode 100644 contracts/test/v0.6/SimpleReadAccessController.test.ts
delete mode 100644 contracts/test/v0.6/SimpleWriteAccessController.test.ts
delete mode 100644 contracts/test/v0.6/VRFD20.test.ts
delete mode 100644 contracts/test/v0.7/AggregatorProxy.test.ts
delete mode 100644 contracts/test/v0.7/AuthorizedForwarder.test.ts
delete mode 100644 contracts/test/v0.7/Chainlink.test.ts
delete mode 100644 contracts/test/v0.7/ChainlinkClient.test.ts
delete mode 100644 contracts/test/v0.7/CompoundPriceFlaggingValidator.test.ts
delete mode 100644 contracts/test/v0.7/ConfirmedOwner.test.ts
delete mode 100644 contracts/test/v0.7/KeeperRegistry1_1.test.ts
delete mode 100644 contracts/test/v0.7/Operator.test.ts
delete mode 100644 contracts/test/v0.7/OperatorFactory.test.ts
delete mode 100644 contracts/test/v0.7/StalenessFlaggingValidator.test.ts
delete mode 100644 contracts/test/v0.7/UpkeepRegistrationRequests.test.ts
delete mode 100644 contracts/test/v0.7/VRFD20.test.ts
delete mode 100644 contracts/test/v0.7/gasUsage.test.ts
diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml
index 069d9de45a..5699657fa5 100644
--- a/.github/workflows/solidity.yml
+++ b/.github/workflows/solidity.yml
@@ -20,11 +20,29 @@ jobs:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
+ list-files: "csv"
filters: |
src:
- 'contracts/**/*'
- '.github/workflows/solidity.yml'
- '.github/workflows/solidity-foundry.yml'
+ old_sol:
+ - 'contracts/src/v0.4/**/*'
+ - 'contracts/src/v0.5/**/*'
+ - 'contracts/src/v0.6/**/*'
+ - 'contracts/src/v0.7/**/*'
+
+
+ - name: Fail if read-only files have changed
+ if: ${{ steps.changes.outputs.old_sol == 'true' }}
+ run: |
+ echo "One or more read-only Solidity file(s) has changed."
+ for file in ${{ steps.changes.outputs.old_sol_files }}; do
+ echo "$file was changed"
+ done
+ exit 1
+
+
prepublish-test:
needs: [changes]
diff --git a/contracts/ci.json b/contracts/ci.json
index dd1fbb0a88..f1eff76513 100644
--- a/contracts/ci.json
+++ b/contracts/ci.json
@@ -6,23 +6,19 @@
"dir": "cross-version",
"numOfSplits": 1
},
- {
- "dir": "v0.6",
- "numOfSplits": 1
- },
- {
- "dir": "v0.7",
- "numOfSplits": 1
- },
{
"dir": "v0.8",
- "numOfSplits": 8,
+ "numOfSplits": 6,
"slowTests": [
- "Keeper",
- "Cron.test",
- "CronUpkeep.test",
+ "Cron",
+ "CronUpkeep",
+ "VRFSubscriptionBalanceMonitor",
"EthBalanceMonitor",
- "CanaryUpkeep"
+ "KeeperRegistrar",
+ "KeeperRegistry1_2",
+ "KeeperRegistry1_3",
+ "KeeperRegistry2_0",
+ "KeeperRegistry2_1"
]
}
]
diff --git a/contracts/test/v0.6/AggregatorFacade.test.ts b/contracts/test/v0.6/AggregatorFacade.test.ts
deleted file mode 100644
index f85c24ae6c..0000000000
--- a/contracts/test/v0.6/AggregatorFacade.test.ts
+++ /dev/null
@@ -1,167 +0,0 @@
-import { ethers } from 'hardhat'
-import { numToBytes32, publicAbi } from '../test-helpers/helpers'
-import { assert } from 'chai'
-import { Contract, ContractFactory, Signer } from 'ethers'
-import { getUsers } from '../test-helpers/setup'
-import { convertFufillParams, decodeRunRequest } from '../test-helpers/oracle'
-import { bigNumEquals, evmRevert } from '../test-helpers/matchers'
-
-let defaultAccount: Signer
-
-let linkTokenFactory: ContractFactory
-let aggregatorFactory: ContractFactory
-let oracleFactory: ContractFactory
-let aggregatorFacadeFactory: ContractFactory
-
-before(async () => {
- const users = await getUsers()
-
- defaultAccount = users.roles.defaultAccount
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- defaultAccount,
- )
- aggregatorFactory = await ethers.getContractFactory(
- 'src/v0.4/Aggregator.sol:Aggregator',
- defaultAccount,
- )
- oracleFactory = await ethers.getContractFactory(
- 'src/v0.6/Oracle.sol:Oracle',
- defaultAccount,
- )
- aggregatorFacadeFactory = await ethers.getContractFactory(
- 'src/v0.6/AggregatorFacade.sol:AggregatorFacade',
- defaultAccount,
- )
-})
-
-describe('AggregatorFacade', () => {
- const jobId1 =
- '0x4c7b7ffb66b344fbaa64995af81e355a00000000000000000000000000000001'
- const previousResponse = numToBytes32(54321)
- const response = numToBytes32(67890)
- const decimals = 18
- const description = 'LINK / USD: Historic Aggregator Facade'
-
- let link: Contract
- let aggregator: Contract
- let oc1: Contract
- let facade: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(defaultAccount).deploy()
- oc1 = await oracleFactory.connect(defaultAccount).deploy(link.address)
- aggregator = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(link.address, 0, 1, [oc1.address], [jobId1])
- facade = await aggregatorFacadeFactory
- .connect(defaultAccount)
- .deploy(aggregator.address, decimals, description)
-
- let requestTx = await aggregator.requestRateUpdate()
- let receipt = await requestTx.wait()
- let request = decodeRunRequest(receipt.logs?.[3])
- await oc1.fulfillOracleRequest(
- ...convertFufillParams(request, previousResponse),
- )
- requestTx = await aggregator.requestRateUpdate()
- receipt = await requestTx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- await oc1.fulfillOracleRequest(...convertFufillParams(request, response))
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(facade, [
- 'aggregator',
- 'decimals',
- 'description',
- 'getAnswer',
- 'getRoundData',
- 'getTimestamp',
- 'latestAnswer',
- 'latestRound',
- 'latestRoundData',
- 'latestTimestamp',
- 'version',
- ])
- })
-
- describe('#constructor', () => {
- it('uses the decimals set in the constructor', async () => {
- bigNumEquals(decimals, await facade.decimals())
- })
-
- it('uses the description set in the constructor', async () => {
- assert.equal(description, await facade.description())
- })
-
- it('sets the version to 2', async () => {
- bigNumEquals(2, await facade.version())
- })
- })
-
- describe('#getAnswer/latestAnswer', () => {
- it('pulls the rate from the aggregator', async () => {
- bigNumEquals(response, await facade.latestAnswer())
- const latestRound = await facade.latestRound()
- bigNumEquals(response, await facade.getAnswer(latestRound))
- })
- })
-
- describe('#getTimestamp/latestTimestamp', () => {
- it('pulls the timestamp from the aggregator', async () => {
- const height = await aggregator.latestTimestamp()
- assert.notEqual('0', height.toString())
- bigNumEquals(height, await facade.latestTimestamp())
- const latestRound = await facade.latestRound()
- bigNumEquals(
- await aggregator.latestTimestamp(),
- await facade.getTimestamp(latestRound),
- )
- })
- })
-
- describe('#getRoundData', () => {
- it('assembles the requested round data', async () => {
- const previousId = (await facade.latestRound()).sub(1)
- const round = await facade.getRoundData(previousId)
- bigNumEquals(previousId, round.roundId)
- bigNumEquals(previousResponse, round.answer)
- bigNumEquals(await facade.getTimestamp(previousId), round.startedAt)
- bigNumEquals(await facade.getTimestamp(previousId), round.updatedAt)
- bigNumEquals(previousId, round.answeredInRound)
- })
-
- it('returns zero data for non-existing rounds', async () => {
- const roundId = 13371337
- await evmRevert(facade.getRoundData(roundId), 'No data present')
- })
- })
-
- describe('#latestRoundData', () => {
- it('assembles the requested round data', async () => {
- const latestId = await facade.latestRound()
- const round = await facade.latestRoundData()
- bigNumEquals(latestId, round.roundId)
- bigNumEquals(response, round.answer)
- bigNumEquals(await facade.getTimestamp(latestId), round.startedAt)
- bigNumEquals(await facade.getTimestamp(latestId), round.updatedAt)
- bigNumEquals(latestId, round.answeredInRound)
- })
-
- describe('when there is no latest round', () => {
- beforeEach(async () => {
- aggregator = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(link.address, 0, 1, [oc1.address], [jobId1])
- facade = await aggregatorFacadeFactory
- .connect(defaultAccount)
- .deploy(aggregator.address, decimals, description)
- })
-
- it('assembles the requested round data', async () => {
- await evmRevert(facade.latestRoundData(), 'No data present')
- })
- })
- })
-})
diff --git a/contracts/test/v0.6/BasicConsumer.test.ts b/contracts/test/v0.6/BasicConsumer.test.ts
deleted file mode 100644
index ce0b7c643e..0000000000
--- a/contracts/test/v0.6/BasicConsumer.test.ts
+++ /dev/null
@@ -1,243 +0,0 @@
-import { ethers } from 'hardhat'
-import { toWei, increaseTime5Minutes, toHex } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { BigNumber, constants, Contract, ContractFactory } from 'ethers'
-import { Roles, getUsers } from '../test-helpers/setup'
-import { bigNumEquals, evmRevert } from '../test-helpers/matchers'
-import {
- convertFufillParams,
- decodeRunRequest,
- encodeOracleRequest,
- RunRequest,
-} from '../test-helpers/oracle'
-import cbor from 'cbor'
-import { makeDebug } from '../test-helpers/debug'
-
-const d = makeDebug('BasicConsumer')
-let basicConsumerFactory: ContractFactory
-let oracleFactory: ContractFactory
-let linkTokenFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- roles = (await getUsers()).roles
- basicConsumerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/BasicConsumer.sol:BasicConsumer',
- roles.defaultAccount,
- )
- oracleFactory = await ethers.getContractFactory(
- 'src/v0.6/Oracle.sol:Oracle',
- roles.oracleNode,
- )
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
-})
-
-describe('BasicConsumer', () => {
- const specId = '0x4c7b7ffb66b344fbaa64995af81e355a'.padEnd(66, '0')
- const currency = 'USD'
- const payment = toWei('1')
- let link: Contract
- let oc: Contract
- let cc: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- oc = await oracleFactory.connect(roles.oracleNode).deploy(link.address)
- cc = await basicConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, oc.address, specId)
- })
-
- it('has a predictable gas price [ @skip-coverage ]', async () => {
- const rec = await ethers.provider.getTransactionReceipt(
- cc.deployTransaction.hash ?? '',
- )
- assert.isBelow(rec.gasUsed?.toNumber() ?? -1, 1750000)
- })
-
- describe('#requestEthereumPrice', () => {
- describe('without LINK', () => {
- it('reverts', async () =>
- await expect(cc.requestEthereumPrice(currency, payment)).to.be.reverted)
- })
-
- describe('with LINK', () => {
- beforeEach(async () => {
- await link.transfer(cc.address, toWei('1'))
- })
-
- it('triggers a log event in the Oracle contract', async () => {
- const tx = await cc.requestEthereumPrice(currency, payment)
- const receipt = await tx.wait()
-
- const log = receipt?.logs?.[3]
- assert.equal(log?.address.toLowerCase(), oc.address.toLowerCase())
-
- const request = decodeRunRequest(log)
- const expected = {
- path: ['USD'],
- get: 'https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY',
- }
-
- assert.equal(toHex(specId), request.specId)
- bigNumEquals(toWei('1'), request.payment)
- assert.equal(cc.address.toLowerCase(), request.requester.toLowerCase())
- assert.equal(1, request.dataVersion)
- assert.deepEqual(expected, cbor.decodeFirstSync(request.data))
- })
-
- it('has a reasonable gas cost [ @skip-coverage ]', async () => {
- const tx = await cc.requestEthereumPrice(currency, payment)
- const receipt = await tx.wait()
-
- assert.isBelow(receipt?.gasUsed?.toNumber() ?? -1, 140000)
- })
- })
- })
-
- describe('#fulfillOracleRequest', () => {
- const response = ethers.utils.formatBytes32String('1,000,000.00')
- let request: RunRequest
-
- beforeEach(async () => {
- await link.transfer(cc.address, toWei('1'))
- const tx = await cc.requestEthereumPrice(currency, payment)
- const receipt = await tx.wait()
-
- request = decodeRunRequest(receipt?.logs?.[3])
- })
-
- it('records the data given to it by the oracle', async () => {
- await oc
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- const currentPrice = await cc.currentPrice()
- assert.equal(currentPrice, response)
- })
-
- it('logs the data given to it by the oracle', async () => {
- const tx = await oc
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
- const receipt = await tx.wait()
-
- assert.equal(2, receipt?.logs?.length)
- const log = receipt?.logs?.[1]
-
- assert.equal(log?.topics[2], response)
- })
-
- describe('when the consumer does not recognize the request ID', () => {
- let otherRequest: RunRequest
-
- beforeEach(async () => {
- // Create a request directly via the oracle, rather than through the
- // chainlink client (consumer). The client should not respond to
- // fulfillment of this request, even though the oracle will faithfully
- // forward the fulfillment to it.
- const args = encodeOracleRequest(
- toHex(specId),
- cc.address,
- basicConsumerFactory.interface.getSighash('fulfill'),
- 43,
- constants.HashZero,
- )
- const tx = await link.transferAndCall(oc.address, 0, args)
- const receipt = await tx.wait()
-
- otherRequest = decodeRunRequest(receipt?.logs?.[2])
- })
-
- it('does not accept the data provided', async () => {
- d('otherRequest %s', otherRequest)
- await oc
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(otherRequest, response))
-
- const received = await cc.currentPrice()
-
- assert.equal(ethers.utils.parseBytes32String(received), '')
- })
- })
-
- describe('when called by anyone other than the oracle contract', () => {
- it('does not accept the data provided', async () => {
- await evmRevert(
- cc.connect(roles.oracleNode).fulfill(request.requestId, response),
- )
-
- const received = await cc.currentPrice()
- assert.equal(ethers.utils.parseBytes32String(received), '')
- })
- })
- })
-
- describe('#cancelRequest', () => {
- const depositAmount = toWei('1')
- let request: RunRequest
-
- beforeEach(async () => {
- await link.transfer(cc.address, depositAmount)
- const tx = await cc.requestEthereumPrice(currency, payment)
- const receipt = await tx.wait()
-
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- describe('before 5 minutes', () => {
- it('cant cancel the request', () =>
- evmRevert(
- cc
- .connect(roles.consumer)
- .cancelRequest(
- oc.address,
- request.requestId,
- request.payment,
- request.callbackFunc,
- request.expiration,
- ),
- ))
- })
-
- describe('after 5 minutes', () => {
- it('can cancel the request', async () => {
- await increaseTime5Minutes(ethers.provider)
-
- await cc
- .connect(roles.consumer)
- .cancelRequest(
- oc.address,
- request.requestId,
- request.payment,
- request.callbackFunc,
- request.expiration,
- )
- })
- })
- })
-
- describe('#withdrawLink', () => {
- const depositAmount = toWei('1')
-
- beforeEach(async () => {
- await link.transfer(cc.address, depositAmount)
- const balance = await link.balanceOf(cc.address)
- bigNumEquals(balance, depositAmount)
- })
-
- it('transfers LINK out of the contract', async () => {
- await cc.connect(roles.consumer).withdrawLink()
- const ccBalance = await link.balanceOf(cc.address)
- const consumerBalance = BigNumber.from(
- await link.balanceOf(await roles.consumer.getAddress()),
- )
- bigNumEquals(ccBalance, 0)
- bigNumEquals(consumerBalance, depositAmount)
- })
- })
-})
diff --git a/contracts/test/v0.6/BlockhashStore.test.ts b/contracts/test/v0.6/BlockhashStore.test.ts
deleted file mode 100644
index 453b2eca3b..0000000000
--- a/contracts/test/v0.6/BlockhashStore.test.ts
+++ /dev/null
@@ -1,285 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert, expect } from 'chai'
-import { Contract, ContractFactory } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-
-let personas: Personas
-let blockhashStoreTestHelperFactory: ContractFactory
-
-type TestBlocks = {
- num: number
- rlpHeader: Uint8Array
- hash: string
-}
-
-const mainnetBlocks: TestBlocks[] = [
- {
- num: 10000467,
- rlpHeader: ethers.utils.arrayify(
- '0xf90215a058ee3c05e880cb25a3db92b9f1479c5453690ca97f9bcbb18d21965d3213578ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea674fdde714fd979de3edf0f56aa9716b898ec8a0a448355652812a7d518b5c979a15bba02cfe4576d8eb61e8b5731ecc37f2bec6a0049f25ed97f9ed9a9c8521ab39cd2c48438d1d18c84dcab5bf494c19595bd462a0b1169f28bdbe5dd61ebc20b7a459be9d7fa898f5a3ba5fed6d502d94b9a8101bb901001000008180000210000080010001080310e004800c3040000060484000010804088050044302a500240041040010012120840002400005092000808000640012081000880010008040200208000004050800400002244044006041040040010890040504020040008004222502000800220000021800006400802036500000000400014640d00020002110000001440000001509543802080004210004100de04744a2810000000032250080810000502210c04289480800000423080800004000a020220030203000020001000000042c00420090000008003308459020e010a01000200190900040e81000040040000020000a8044001000202010000600c087086c49cadb1b57839898538398909483984b9e845eb02fbf94505059452d65746865726d696e652d6575312d34a06d0287c21536fac432714bd3f3712ff1a7e409faf1b10edac9b9547da1d4f7b188930531280477460c',
- ),
- hash: '0x4a65bcdf3466a16740b74849cc10fc57d4acb24cce148665482812699a400464',
- },
- {
- num: 10000468,
- rlpHeader: ethers.utils.arrayify(
- '0xf9020da04a65bcdf3466a16740b74849cc10fc57d4acb24cce148665482812699a400464a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479404668ec2f57cc15c381b461b9fedab5d451c8f7fa0bcd4ddbb7125a5c06df96d862921dc0bba8664b3f759a233fe565a615c0ab3eaa0087ab379852c83e4b660de1668fc93333201ad0d233167ea6cef8bacaf5cba2aa0d81855037b2a6b56eba0c2ed129fb4102fb831b0baa187a0f6e0c155400f7855b9010080040040200000000010102081000000500040010408040800010110000000008000005808020000902021818000210000000000081100401000400014400001041008000020448800180128800008000200000420e01200000000000000011000001000020000208000b42200a0008000510200080200008c002018108010014030200000080000000002000010008000011008004003081000400080100803040080040300000002044080480000000000008080101000000050000000000840000002200040000a0080000442008006005502800000040008000890201002022402208002900020900000000080000100100201080000000003400000004887086d57541477ba839898548398968083989147845eb02fc28c73706964657230380b03ac53a076c676a0ab090b373b6242851a4beab7b8cdc9d3ebe211747a255b78c0278c42880ea13d40042dd1e6',
- ),
- hash: '0x00fd2589a272b85ffaf63223641571bf95891c936b7514ee4e87a593e52de7c9',
- },
- {
- num: 10000469,
- rlpHeader: ethers.utils.arrayify(
- '0xf90211a000fd2589a272b85ffaf63223641571bf95891c936b7514ee4e87a593e52de7c9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca01b28d3b4e4d3442a9e6caed9f80b6a639bce6f3a283d4e004e6bb44e483ceeeba067c00d9067bc023b8fab8e3afd1bc0f2470f08003bdf9f167fbfeede2422ac4ea09d8b344d9ab1b7288f8c5e644c53b1a5288da6d6ee0e388ec76f291def48da15b90100c462095870a26a0804132e208110329710d459054558159c103208d44820002016108136199200061063699d8400254a22828c11b5512e3303c98ec7747cc02d00161880c2f2c580e806bccc04805190265f096601342058020a8324c277735d8202220412f03303201252a3000038883a4bb0010e6b004408306232150a84d110100d0c4b9d228022812602c05c801d20500d4ed10010ce2400428a96950a98050c00e603292a806c4983b25814880000440a23821191121996410c5110c949616c2066a4a0488087d4c226c14208042c00d609b5cc44051400219d93626818728612a9b18690e03c902014a900e0018828011494b80d4708799b0d8a83cace87086e64fefefb48839898558398968083986664845eb02fc7906574682d70726f2d687a662d74303032a09f1918a362b55ebd072cc9548fb74f89301d41c2a1feb13c08a1c2c3cb0606d88810dfa530069367fb',
- ),
- hash: '0x325fde74e261fc483a16506bbc711b645b043ad24c7db0136845a1be262cf0c9',
- },
- {
- num: 10000470,
- rlpHeader: ethers.utils.arrayify(
- '0xf90215a0325fde74e261fc483a16506bbc711b645b043ad24c7db0136845a1be262cf0c9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea674fdde714fd979de3edf0f56aa9716b898ec8a020647cfa35563093442a12d80bf2bacb83da1de8340366677f3822591a334ccea066ad7285f6c5b6407f62c6b65a83aeaaa71ad9a97c2bb15139140f2dbb60f7e0a0c0e633851d0b5ce661ecc054517425e82425fcc6170db9693e5b5a6dd5ef6d6bb90100c0c000c1520708182080c8e461891c2402800a80d44a00034259414012012a5006a1416331181504902044960808f1129018800311621e920886804693749b10542400142e984580ccba634881c4156962200ecfb004000005468db44842781c59923110262660802315006106388b028412c42c000820c508e66b7851fa68002008144cd7860cd884280802915163399c168d5a11b0649486084110149469a1e61c31134204b903206566885180bc0426c0c6c0a4d408e182242f08180d204c624a040248425041ac028010d088820402ba4bd38c2d1215829300543465603822110500811290490148049300040e000c280086a09e8100089818ce480a887e87086c4965bf3c8a839898568398705c839847d2845eb02fe994505059452d65746865726d696e652d6575312d35a09d8ae288d0eede524f3ef5e6cfcc5ba07f380bc695bb71578a7b91cfa517071b8859d0976006378e52',
- ),
- hash: '0x5cf096dfd1fc2d2947a96fdec5377ab7beaa0eb00c80728a3b96f0864cec506a',
- },
-]
-
-const maticBlocks: TestBlocks[] = [
- {
- num: 10000467,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025da0212093b89337e6741aca0c6c1cbfc64b56155bdcc3623fa9bcbfa0498fa135aba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ac0ec242516093308f7a2cc6965f38835eb3db69cba93401daef672666a3aefea0d06985e9ae671d22fb4b3d73ef4e074a448f66b4769ad8d59c3b8aef1ede15e2a00076d4897a88e08c25ca12c558f622d03d532d8b674e8c6b9847000b98dbe480b90100040000000200000000000000000000000000000000000000100000000000400000000000000000000000002800000000100080000000000000000001000000400000000000000000000000080002008000000000000000000021000000000000000000000200000000001000000008000000000008000001800800100000000000010000000010100000800000000000001000000200100000000000000000002000000004000000000000000080010000000000000000200000000000000040000000420000000000010000000000000004040004000000001000001000200100100080000000000400000000100000100000000000000000000000021000000e839898538401312d008302e54b84600df884b861d78301091883626f7288676f312e31352e35856c696e7578000000000000000003eb49c29f5facd767206f64b8a5c9b325bced5c9156f489c6281c68eddc9e5f2ef1177c02a99d8ab6216dcf2879eefddfc27c75ffa9ef6a2185ce9983d1434901a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0x6c3b869ca26fece236545f7914d8249651d729852dc1445f53a94d5a59cdc9da',
- },
- {
- num: 10000468,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025da06c3b869ca26fece236545f7914d8249651d729852dc1445f53a94d5a59cdc9daa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fa236c78bbe5939cc62985e32582c2158468a5b2b4dd02d514edb0bea95f0fd3a0e05ccfb09764e5cd6811ef2c2616d4a57f187be84235e2569c9b8d70489f1a44a0aea27aed2ad1d553e30501e6fe47fee0842c3b7ce5867e579b29975f02ec4282b90100008000100000000000000400080800000009000000010020000000000800000000000000080000000000000000000000000080000080000820400000000000000000200000000000000000080000008000200000200000000003009000020000000200000010000000001000000000000000000000000000800040100000000000000000000010000000100100000000000000000102004000000040000000002000000008000000000000000000000000000000200000000000000000000041000000020000080001010000000000000008000000110000001001800020000000100000000001400000040000000000000010010000000001000000001000000e839898548401312d00830494ed84600df886b861d78301091883626f7288676f312e31352e35856c696e75780000000000000000aa8ed86143b48b6aa7170d2083c3a7be31cbdfdc40f39badb8747f4c2198279a71c0d3eb5d25f3b7da5a48b887f61e22fe0baa692aa03807ad12f6fe25af087e00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0x258aa48bde013579fbfef2e222bcc222b1f57bf898a71c623f9024229c9f6111',
- },
- {
- num: 10000469,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025aa0258aa48bde013579fbfef2e222bcc222b1f57bf898a71c623f9024229c9f6111a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fa236c78bbe5939cc62985e32582c2158468a5b2b4dd02d514edb0bea95f0fd3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e839898558401312d008084600df888b861d78301091883626f7288676f312e31352e35856c696e75780000000000000000bd8668cc5d89583a7cc26fb96650e61f045ffe5248ae80c667ba7648df41e3d552060998ac151f2d15bd1b98f0a2a50c4281729a4c0aae4758a3bad280207c2901a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0x611779767f1deb5a17723ec71d1b397b18a0fc9a40d282810a33bd6a0a5f46f9',
- },
- {
- num: 10000470,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025aa0611779767f1deb5a17723ec71d1b397b18a0fc9a40d282810a33bd6a0a5f46f9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fa236c78bbe5939cc62985e32582c2158468a5b2b4dd02d514edb0bea95f0fd3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e839898568401312d008084600df88ab861d78301091883626f7288676f312e31352e35856c696e75780000000000000000b617675c3b01e98319508130e1a583d57ce6b3a8a97fa2fbdaa33673cc6c609d6f7c361c833838f54b724d3a83cdd73e2398bb147970cd0b057865386cb08e1300a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0x2edf2f5c5faa5046b2304f76c92096a25e7c4343a7b75c36b29e8e9755d93397',
- },
-]
-
-// The following headers from Binance Smart Chain were retrieved using `go run
-// binance.go`, where binance.go contains
-//
-// package main
-//
-// import (
-// "context"
-// "fmt"
-// "log"
-// "math/big"
-// "math/rand"
-// "strings"
-//
-// "github.com/ethereum/go-ethereum/ethclient"
-// "github.com/ethereum/go-ethereum/rlp"
-// )
-//
-// var tsBlockTemplate = `
-// {
-// num: %d,
-// rlpHeader: ethers.utils.arrayify(
-// '0x%x',
-// ),
-// hash: '0x%x',
-// },
-// `
-//
-// func main() {
-// client, err := ethclient.Dial("https://bsc-dataseed.binance.org/")
-// if err != nil {
-// log.Fatal(err)
-// }
-//
-// header, err := client.HeaderByNumber(context.Background(), nil)
-// if err != nil {
-// log.Fatal(err)
-// }
-// topBlockNum := header.Number.Int64()
-// numBlocks := int64(4)
-// if topBlockNum < numBlocks {
-// log.Fatalf("need at least %d consecutive blocks", numBlocks)
-// }
-// targetBlock := int64(rand.Intn(int(topBlockNum - numBlocks)))
-// simulatedHeadBlock := targetBlock + numBlocks - 1
-// for blockNum := targetBlock; blockNum <= simulatedHeadBlock; blockNum++ {
-// header, err := client.HeaderByNumber(context.Background(), big.NewInt(blockNum))
-// if err != nil {
-// log.Fatal(err)
-// }
-// s, err := rlp.EncodeToBytes(header)
-// if err != nil {
-// log.Fatalf("could not encode header: got error %s from %v", err, header)
-// }
-// // fmt.Printf("header for block number %d: 0x%x\n", blockNum, s)
-// fmt.Printf(strings.TrimLeft(tsBlockTemplate, "\n"), blockNum, s, header.Hash())
-// }
-// }
-const binanceBlocks: TestBlocks[] = [
- {
- num: 1875651,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025da029c26248bebbe0d0acb209d13ac9337c4b5c313696c031dd63b3cd16cbdc0c21a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b8f7166496996a7da21cf1f1b04d9b3e26a3d077a03f962867b5e86191c3280bd52c4249587e08ddfa9851cea981fb7a5721c9157aa05924ae05d17347687ba81d093aee159ccc65cefc8314b0515ef921e553df05a2a089af99a7afa586e7d67062d051df4255304bb730f6d62fdd3bdb207f1513b23bb901000100000000000000000800000000000000000000000200000000000000800000000000000200100000000000000800000000000000000000000000000000000000000000000000800000140800000008201000001000000202000000001200000000002002020000000000000000080000000000000002000000001000000000000002000000008010000000000000000002040080008400280000c00000081000400000004000000010000000020000000000000000000000000000000000000001000210200000000000000000000800000000000000000000000000002010000004000000000001000000000000000000000800020000000000000000000002831c9ec38401c9c380830789c2845f9faab1b861d883010002846765746888676f312e31332e34856c696e7578000000000000003311ee6830f31dc9116d8a59178b539d91eb6811c1d533c4a59bf77262689c552218bb1eae9cb9d6bf6e1066bea78052c8767313ace71c919d02e70760bd255401a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0xe0a935b1e37420ac1d855215bdad4730a5ffe315eda287c6c18aa86c426ede74',
- },
- {
- num: 1875652,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025da0e0a935b1e37420ac1d855215bdad4730a5ffe315eda287c6c18aa86c426ede74a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794c2be4ec20253b8642161bc3f444f53679c1f3d47a0dbf2d40cf5533b65ac9b5be35cac75f7b106244ba14ee476a832c28d46a53452a04f83b8a51d3e17b6a02a0caa79acc7597996c5b8c68dba12c33095ae086089eea02fa2642645b2de17227a6c18c3fa491f54b3bdfe8ac8e04924a33a005a0e9e61b901000100000100000000000008000000000000000000040000000000000000800000000000000000000000000000000800000800000000000400000000000020000040100080000000000000000800000000209000001000000200000000801000400800002002030000000000000100080000002000000002004000011000000002000100040000000000100000000000000000040100009000300000000000000002004000004000000000000000020000002000000010000000200000800000000001000280000000000000008000000000000000800000000000020000002000041000000000000001200020001000080000002a40020040000000000000000002831c9ec48401c9c38083044b40845f9faab4b861d883010002846765746888676f312e31332e34856c696e757800000000000000cfc02687b2394922055792a8e67dad566f6690de06b229d752433b2067207b5f43b9f3c63f91cea5a79bbfc51d9132b933a706ab504038a92f37d57af2bb6c2e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0x629e5abcae42940e00d7b38aa7b2ecccfbab582cb7a0b2c3658c2dad8e66549d',
- },
- {
- num: 1875653,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025da0629e5abcae42940e00d7b38aa7b2ecccfbab582cb7a0b2c3658c2dad8e66549da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ce2fd7544e0b2cc94692d4a704debef7bcb61328a0718e7db53041585a814d658c32c88fd550c2c6d200826020008925e0a0f7967fa000fbf842e492a47cc9786885783259a08aed71055e78216006408932515fd960a0c7ffeb2189b8fcde43733cf1958cdb1c38c44052cfbb41125382240c232a98f8b901000000000000000000000000000000000000000002000000000004000000000000000000010000000000000000000000000000000000000200000000004020200000010000000800000000208800000000201000000000000000080000000000000000002002220000000000000000080000000000000000000000001000000000100000000000080010000000000000000000040000000000000000000000000002000000000008000000004000000000000000000000200000000000000000000000000202000000000000000000000000000000000008000000000000002080001000000000000001000000000000000000080100000000000000000000000002831c9ec58401c9c38083025019845f9faab7b861d883010002846765746888676f312e31332e34856c696e7578000000000000008c3c7a5c83e930fbd9d14f83c9b3931f032f0f678919c35b8b32ca6dae9948950bfa326fae134fa234fa7b84c06bdc3f7c6d6414c2a266df1339e563be8bd9cc00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0xae8574651adabfd0ca55e2cee0e2e639ced73ec1cc0a35debeeceee6943442a9',
- },
- {
- num: 1875654,
- rlpHeader: ethers.utils.arrayify(
- '0xf9025da0ae8574651adabfd0ca55e2cee0e2e639ced73ec1cc0a35debeeceee6943442a9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d6caa02bbebaebb5d7e581e4b66559e635f805ffa02df6a1173c63ec0a8acc46c818670f030aece1154b9f3bbc70f46a8427dd8dd6a0fa8835c499682d8c90759ff9ea1c291048755b967e48880a0fc21d19ec034a59a0b4e22607cb105c04156044b3f98c2cecae1553b45aa9b6044c37573791a27576b901000200000008000000000001000000000000000000000020000000000000020000000000000000000000000000000000000000000000000040000000000220000000000000000400000000001802000000201000000000000000000000000000000000002002020000000000000000080000000000000000000000001000000000000000000000100000000000000000000000040000000000000000010200200002000400000000400000000200000000000000080000000000000000000008000000000200000000000000000000000000000000000000000000000000002000001000000000000001000000000000000000000000000000000008080000000002831c9ec68401c9c3808301e575845f9faabab861d883010002846765746888676f312e31332e34856c696e757800000000000000399e73b0e963ec029e815623a414aa852508a28dd9799a1bf4e2380c8db687a46cc5b6cc20352ae21e35cfd28124a32fcd49ac8fac5b03901b3e03963e4fff5801a00000000000000000000000000000000000000000000000000000000000000000880000000000000000',
- ),
- hash: '0x189990455c59a5dea78071df9a2008ede292ff0a062fc5c4c6ca35fbe476f834',
- },
-]
-
-before(async () => {
- personas = (await getUsers()).personas
- blockhashStoreTestHelperFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/BlockhashStoreTestHelper.sol:BlockhashStoreTestHelper',
- personas.Default,
- )
-})
-
-runBlockhashStoreTests(mainnetBlocks, 'Ethereum')
-runBlockhashStoreTests(maticBlocks, 'Matic')
-runBlockhashStoreTests(binanceBlocks, 'Binance Smart Chain')
-
-async function runBlockhashStoreTests(
- blocks: TestBlocks[],
- description: string,
-) {
- describe(`BlockhashStore (${description})`, () => {
- let blockhashStoreTestHelper: Contract
-
- beforeEach(async () => {
- blockhashStoreTestHelper = await blockhashStoreTestHelperFactory
- .connect(personas.Default)
- .deploy()
-
- const [lastBlock] = blocks.slice(-1)
- await blockhashStoreTestHelper
- .connect(personas.Default)
- .godmodeSetHash(lastBlock.num, lastBlock.hash)
- assert.strictEqual(
- await blockhashStoreTestHelper.getBlockhash(lastBlock.num),
- lastBlock.hash,
- )
- })
-
- it('getBlockhash reverts for unknown blockhashes', async () => {
- await expect(
- blockhashStoreTestHelper.getBlockhash(99999999),
- ).to.be.revertedWith('blockhash not found in store')
- })
-
- it('storeVerifyHeader records valid blockhashes', async () => {
- for (let i = blocks.length - 2; i >= 0; i--) {
- assert.strictEqual(
- ethers.utils.keccak256(blocks[i + 1].rlpHeader),
- await blockhashStoreTestHelper.getBlockhash(blocks[i + 1].num),
- )
- await blockhashStoreTestHelper
- .connect(personas.Default)
- .storeVerifyHeader(blocks[i].num, blocks[i + 1].rlpHeader)
- assert.strictEqual(
- await blockhashStoreTestHelper.getBlockhash(blocks[i].num),
- blocks[i].hash,
- )
- }
- })
-
- it('storeVerifyHeader rejects unknown headers', async () => {
- const unknownBlock = blocks[0]
- await expect(
- blockhashStoreTestHelper
- .connect(personas.Default)
- .storeVerifyHeader(unknownBlock.num - 1, unknownBlock.rlpHeader),
- ).to.be.revertedWith('header has unknown blockhash')
- })
-
- it('storeVerifyHeader rejects corrupted headers', async () => {
- const [lastBlock] = blocks.slice(-1)
- const modifiedHeader = new Uint8Array(lastBlock.rlpHeader)
- modifiedHeader[137] += 1
- await expect(
- blockhashStoreTestHelper
- .connect(personas.Default)
- .storeVerifyHeader(lastBlock.num - 1, modifiedHeader),
- ).to.be.revertedWith('header has unknown blockhash')
- })
-
- it('store accepts recent block numbers', async () => {
- await ethers.provider.send('evm_mine', [])
-
- const n = (await ethers.provider.getBlockNumber()) - 1
- await blockhashStoreTestHelper.connect(personas.Default).store(n)
-
- assert.equal(
- await blockhashStoreTestHelper.getBlockhash(n),
- (await ethers.provider.getBlock(n)).hash,
- )
- })
-
- it('store rejects future block numbers', async () => {
- await expect(
- blockhashStoreTestHelper.connect(personas.Default).store(99999999999),
- ).to.be.revertedWith('blockhash(n) failed')
- })
-
- it('store rejects old block numbers', async () => {
- for (let i = 0; i < 300; i++) {
- await ethers.provider.send('evm_mine', [])
- }
-
- await expect(
- blockhashStoreTestHelper
- .connect(personas.Default)
- .store((await ethers.provider.getBlockNumber()) - 256),
- ).to.be.revertedWith('blockhash(n) failed')
- })
-
- it('storeEarliest works', async () => {
- for (let i = 0; i < 300; i++) {
- await ethers.provider.send('evm_mine', [])
- }
-
- await blockhashStoreTestHelper.connect(personas.Default).storeEarliest()
-
- const n = (await ethers.provider.getBlockNumber()) - 256
- assert.equal(
- await blockhashStoreTestHelper.getBlockhash(n),
- (await ethers.provider.getBlock(n)).hash,
- )
- })
- })
-}
diff --git a/contracts/test/v0.6/Chainlink.test.ts b/contracts/test/v0.6/Chainlink.test.ts
deleted file mode 100644
index f3587dc30a..0000000000
--- a/contracts/test/v0.6/Chainlink.test.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi, decodeDietCBOR, hexToBuf } from '../test-helpers/helpers'
-import { assert } from 'chai'
-import { Contract, ContractFactory, providers, Signer } from 'ethers'
-import { Roles, getUsers } from '../test-helpers/setup'
-import { makeDebug } from '../test-helpers/debug'
-
-const debug = makeDebug('ChainlinkTestHelper')
-let concreteChainlinkFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- roles = (await getUsers()).roles
- concreteChainlinkFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/ChainlinkTestHelper.sol:ChainlinkTestHelper',
- roles.defaultAccount,
- )
-})
-
-describe('ChainlinkTestHelper', () => {
- let ccl: Contract
- let defaultAccount: Signer
-
- beforeEach(async () => {
- defaultAccount = roles.defaultAccount
- ccl = await concreteChainlinkFactory.connect(defaultAccount).deploy()
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(ccl, [
- 'add',
- 'addBytes',
- 'addInt',
- 'addStringArray',
- 'addUint',
- 'closeEvent',
- 'setBuffer',
- ])
- })
-
- async function parseCCLEvent(tx: providers.TransactionResponse) {
- const receipt = await tx.wait()
- const data = receipt.logs?.[0].data
- const d = debug.extend('parseCCLEvent')
- d('data %s', data)
- return ethers.utils.defaultAbiCoder.decode(['bytes'], data ?? '')
- }
-
- describe('#close', () => {
- it('handles empty payloads', async () => {
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, {})
- })
- })
-
- describe('#setBuffer', () => {
- it('emits the buffer', async () => {
- await ccl.setBuffer('0xA161616162')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { a: 'b' })
- })
- })
-
- describe('#add', () => {
- it('stores and logs keys and values', async () => {
- await ccl.add('first', 'word!!')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { first: 'word!!' })
- })
-
- it('handles two entries', async () => {
- await ccl.add('first', 'uno')
- await ccl.add('second', 'dos')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- assert.deepEqual(decoded, {
- first: 'uno',
- second: 'dos',
- })
- })
- })
-
- describe('#addBytes', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addBytes('first', '0xaabbccddeeff')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- const expected = hexToBuf('0xaabbccddeeff')
- assert.deepEqual(decoded, { first: expected })
- })
-
- it('handles two entries', async () => {
- await ccl.addBytes('first', '0x756E6F')
- await ccl.addBytes('second', '0x646F73')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- const expectedFirst = hexToBuf('0x756E6F')
- const expectedSecond = hexToBuf('0x646F73')
- assert.deepEqual(decoded, {
- first: expectedFirst,
- second: expectedSecond,
- })
- })
-
- it('handles strings', async () => {
- await ccl.addBytes('first', ethers.utils.toUtf8Bytes('apple'))
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- const expected = ethers.utils.toUtf8Bytes('apple')
- assert.deepEqual(decoded, { first: expected })
- })
- })
-
- describe('#addInt', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addInt('first', 1)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { first: 1 })
- })
-
- it('handles two entries', async () => {
- await ccl.addInt('first', 1)
- await ccl.addInt('second', 2)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- assert.deepEqual(decoded, {
- first: 1,
- second: 2,
- })
- })
- })
-
- describe('#addUint', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addUint('first', 1)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { first: 1 })
- })
-
- it('handles two entries', async () => {
- await ccl.addUint('first', 1)
- await ccl.addUint('second', 2)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- assert.deepEqual(decoded, {
- first: 1,
- second: 2,
- })
- })
- })
-
- describe('#addStringArray', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addStringArray('word', [
- ethers.utils.formatBytes32String('seinfeld'),
- ethers.utils.formatBytes32String('"4"'),
- ethers.utils.formatBytes32String('LIFE'),
- ])
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { word: ['seinfeld', '"4"', 'LIFE'] })
- })
- })
-})
diff --git a/contracts/test/v0.6/ChainlinkClient.test.ts b/contracts/test/v0.6/ChainlinkClient.test.ts
deleted file mode 100644
index bfd43d7f3f..0000000000
--- a/contracts/test/v0.6/ChainlinkClient.test.ts
+++ /dev/null
@@ -1,376 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert } from 'chai'
-import { Contract, ContractFactory } from 'ethers'
-import { Roles, getUsers } from '../test-helpers/setup'
-import {
- convertFufillParams,
- decodeCCRequest,
- decodeRunRequest,
- RunRequest,
-} from '../test-helpers/oracle'
-import { decodeDietCBOR } from '../test-helpers/helpers'
-import { evmRevert } from '../test-helpers/matchers'
-
-let concreteChainlinkClientFactory: ContractFactory
-let emptyOracleFactory: ContractFactory
-let getterSetterFactory: ContractFactory
-let oracleFactory: ContractFactory
-let linkTokenFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- roles = (await getUsers()).roles
-
- concreteChainlinkClientFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/ChainlinkClientTestHelper.sol:ChainlinkClientTestHelper',
- roles.defaultAccount,
- )
- emptyOracleFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/EmptyOracle.sol:EmptyOracle',
- roles.defaultAccount,
- )
- getterSetterFactory = await ethers.getContractFactory(
- 'src/v0.5/tests/GetterSetter.sol:GetterSetter',
- roles.defaultAccount,
- )
- oracleFactory = await ethers.getContractFactory(
- 'src/v0.4/Oracle.sol:Oracle',
- roles.defaultAccount,
- )
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
-})
-
-describe('ChainlinkClientTestHelper', () => {
- const specId =
- '0x4c7b7ffb66b344fbaa64995af81e355a00000000000000000000000000000000'
- let cc: Contract
- let gs: Contract
- let oc: Contract
- let newoc: Contract
- let link: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- oc = await oracleFactory.connect(roles.defaultAccount).deploy(link.address)
- newoc = await oracleFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
- gs = await getterSetterFactory.connect(roles.defaultAccount).deploy()
- cc = await concreteChainlinkClientFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, oc.address)
- })
-
- describe('#newRequest', () => {
- it('forwards the information to the oracle contract through the link token', async () => {
- const tx = await cc.publicNewRequest(
- specId,
- gs.address,
- ethers.utils.toUtf8Bytes('requestedBytes32(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
-
- assert.equal(1, receipt.logs?.length)
- const [jId, cbAddr, cbFId, cborData] = receipt.logs
- ? decodeCCRequest(receipt.logs[0])
- : []
- const params = decodeDietCBOR(cborData ?? '')
-
- assert.equal(specId, jId)
- assert.equal(gs.address, cbAddr)
- assert.equal('0xed53e511', cbFId)
- assert.deepEqual({}, params)
- })
- })
-
- describe('#chainlinkRequest(Request)', () => {
- it('emits an event from the contract showing the run ID', async () => {
- const tx = await cc.publicRequest(
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
-
- const { events, logs } = await tx.wait()
-
- assert.equal(4, events?.length)
-
- assert.equal(logs?.[0].address, cc.address)
- assert.equal(events?.[0].event, 'ChainlinkRequested')
- })
- })
-
- describe('#chainlinkRequestTo(Request)', () => {
- it('emits an event from the contract showing the run ID', async () => {
- const tx = await cc.publicRequestRunTo(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { events } = await tx.wait()
-
- assert.equal(4, events?.length)
- assert.equal(events?.[0].event, 'ChainlinkRequested')
- })
-
- it('emits an event on the target oracle contract', async () => {
- const tx = await cc.publicRequestRunTo(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { logs } = await tx.wait()
- const event = logs && newoc.interface.parseLog(logs[3])
-
- assert.equal(4, logs?.length)
- assert.equal(event?.name, 'OracleRequest')
- })
-
- it('does not modify the stored oracle address', async () => {
- await cc.publicRequestRunTo(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
-
- const actualOracleAddress = await cc.publicOracleAddress()
- assert.equal(oc.address, actualOracleAddress)
- })
- })
-
- describe('#cancelChainlinkRequest', () => {
- let requestId: string
- // a concrete chainlink attached to an empty oracle
- let ecc: Contract
-
- beforeEach(async () => {
- const emptyOracle = await emptyOracleFactory
- .connect(roles.defaultAccount)
- .deploy()
- ecc = await concreteChainlinkClientFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, emptyOracle.address)
-
- const tx = await ecc.publicRequest(
- specId,
- ecc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { events } = await tx.wait()
- requestId = (events?.[0]?.args as any).id
- })
-
- it('emits an event from the contract showing the run was cancelled', async () => {
- const tx = await ecc.publicCancelRequest(
- requestId,
- 0,
- ethers.utils.hexZeroPad('0x', 4),
- 0,
- )
- const { events } = await tx.wait()
-
- assert.equal(1, events?.length)
- assert.equal(events?.[0].event, 'ChainlinkCancelled')
- assert.equal(requestId, (events?.[0].args as any).id)
- })
-
- it('throws if given a bogus event ID', async () => {
- await evmRevert(
- ecc.publicCancelRequest(
- ethers.utils.formatBytes32String('bogusId'),
- 0,
- ethers.utils.hexZeroPad('0x', 4),
- 0,
- ),
- )
- })
- })
-
- describe('#recordChainlinkFulfillment(modifier)', () => {
- let request: RunRequest
-
- beforeEach(async () => {
- const tx = await cc.publicRequest(
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { logs } = await tx.wait()
-
- request = decodeRunRequest(logs?.[3])
- })
-
- it('emits an event marking the request fulfilled', async () => {
- const tx = await oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
- const { logs } = await tx.wait()
-
- const event = logs && cc.interface.parseLog(logs[0])
-
- assert.equal(1, logs?.length)
- assert.equal(event?.name, 'ChainlinkFulfilled')
- assert.equal(request.requestId, event?.args.id)
- })
-
- it('should only allow one fulfillment per id', async () => {
- await oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
-
- await evmRevert(
- oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Must have a valid requestId',
- )
- })
-
- it('should only allow the oracle to fulfill the request', async () => {
- await evmRevert(
- oc
- .connect(roles.stranger)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Not an authorized node to fulfill requests',
- )
- })
- })
-
- describe('#fulfillChainlinkRequest(function)', () => {
- let request: RunRequest
-
- beforeEach(async () => {
- const tx = await cc.publicRequest(
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes(
- 'publicFulfillChainlinkRequest(bytes32,bytes32)',
- ),
- 0,
- )
- const { logs } = await tx.wait()
-
- request = decodeRunRequest(logs?.[3])
- })
-
- it('emits an event marking the request fulfilled', async () => {
- const tx = await oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
-
- const { logs } = await tx.wait()
- const event = logs && cc.interface.parseLog(logs[0])
-
- assert.equal(1, logs?.length)
- assert.equal(event?.name, 'ChainlinkFulfilled')
- assert.equal(request.requestId, event?.args?.id)
- })
-
- it('should only allow one fulfillment per id', async () => {
- await oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
-
- await evmRevert(
- oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Must have a valid requestId',
- )
- })
-
- it('should only allow the oracle to fulfill the request', async () => {
- await evmRevert(
- oc
- .connect(roles.stranger)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Not an authorized node to fulfill requests',
- )
- })
- })
-
- describe('#chainlinkToken', () => {
- it('returns the Link Token address', async () => {
- const addr = await cc.publicChainlinkToken()
- assert.equal(addr, link.address)
- })
- })
-
- describe('#addExternalRequest', () => {
- let mock: Contract
- let request: RunRequest
-
- beforeEach(async () => {
- mock = await concreteChainlinkClientFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, oc.address)
-
- const tx = await cc.publicRequest(
- specId,
- mock.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const receipt = await tx.wait()
-
- request = decodeRunRequest(receipt.logs?.[3])
- await mock.publicAddExternalRequest(oc.address, request.requestId)
- })
-
- it('allows the external request to be fulfilled', async () => {
- await oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
- })
-
- it('does not allow the same requestId to be used', async () => {
- await evmRevert(
- cc.publicAddExternalRequest(newoc.address, request.requestId),
- )
- })
- })
-})
diff --git a/contracts/test/v0.6/CheckedMath.test.ts b/contracts/test/v0.6/CheckedMath.test.ts
deleted file mode 100644
index 14520d9d9b..0000000000
--- a/contracts/test/v0.6/CheckedMath.test.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-// SPDX-License-Identifier: MIT
-// Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/c9630526e24ba53d9647787588a19ffaa3dd65e1/test/math/SignedSafeMath.test.js
-
-import { ethers } from 'hardhat'
-import { assert } from 'chai'
-import { BigNumber, constants, Contract, ContractFactory } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { bigNumEquals } from '../test-helpers/matchers'
-
-let mathFactory: ContractFactory
-let personas: Personas
-
-before(async () => {
- personas = (await getUsers()).personas
- mathFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/CheckedMathTestHelper.sol:CheckedMathTestHelper',
- personas.Default,
- )
-})
-
-const int256Max = constants.MaxInt256
-const int256Min = constants.MinInt256
-
-describe('CheckedMath', () => {
- let math: Contract
-
- beforeEach(async () => {
- math = await mathFactory.connect(personas.Default).deploy()
- })
-
- describe('#add', () => {
- const a = BigNumber.from('1234')
- const b = BigNumber.from('5678')
-
- it('is commutative', async () => {
- const c1 = await math.add(a, b)
- const c2 = await math.add(b, a)
-
- bigNumEquals(c1.result, c2.result)
- assert.isTrue(c1.ok)
- assert.isTrue(c2.ok)
- })
-
- it('is commutative with big numbers', async () => {
- const c1 = await math.add(int256Max, int256Min)
- const c2 = await math.add(int256Min, int256Max)
-
- bigNumEquals(c1.result, c2.result)
- assert.isTrue(c1.ok)
- assert.isTrue(c2.ok)
- })
-
- it('returns false when overflowing', async () => {
- const c1 = await math.add(int256Max, 1)
- const c2 = await math.add(1, int256Max)
-
- bigNumEquals(0, c1.result)
- bigNumEquals(0, c2.result)
- assert.isFalse(c1.ok)
- assert.isFalse(c2.ok)
- })
-
- it('returns false when underflowing', async () => {
- const c1 = await math.add(int256Min, -1)
- const c2 = await math.add(-1, int256Min)
-
- bigNumEquals(0, c1.result)
- bigNumEquals(0, c2.result)
- assert.isFalse(c1.ok)
- assert.isFalse(c2.ok)
- })
- })
-
- describe('#sub', () => {
- const a = BigNumber.from('1234')
- const b = BigNumber.from('5678')
-
- it('subtracts correctly if it does not overflow and the result is negative', async () => {
- const c = await math.sub(a, b)
- const expected = a.sub(b)
-
- bigNumEquals(expected, c.result)
- assert.isTrue(c.ok)
- })
-
- it('subtracts correctly if it does not overflow and the result is positive', async () => {
- const c = await math.sub(b, a)
- const expected = b.sub(a)
-
- bigNumEquals(expected, c.result)
- assert.isTrue(c.ok)
- })
-
- it('returns false on overflow', async () => {
- const c = await math.sub(int256Max, -1)
-
- bigNumEquals(0, c.result)
- assert.isFalse(c.ok)
- })
-
- it('returns false on underflow', async () => {
- const c = await math.sub(int256Min, 1)
-
- bigNumEquals(0, c.result)
- assert.isFalse(c.ok)
- })
- })
-
- describe('#mul', () => {
- const a = BigNumber.from('5678')
- const b = BigNumber.from('-1234')
-
- it('is commutative', async () => {
- const c1 = await math.mul(a, b)
- const c2 = await math.mul(b, a)
-
- bigNumEquals(c1.result, c2.result)
- assert.isTrue(c1.ok)
- assert.isTrue(c2.ok)
- })
-
- it('multiplies by 0 correctly', async () => {
- const c = await math.mul(a, 0)
-
- bigNumEquals(0, c.result)
- assert.isTrue(c.ok)
- })
-
- it('returns false on multiplication overflow', async () => {
- const c = await math.mul(int256Max, 2)
-
- bigNumEquals(0, c.result)
- assert.isFalse(c.ok)
- })
-
- it('returns false when the integer minimum is negated', async () => {
- const c = await math.mul(int256Min, -1)
-
- bigNumEquals(0, c.result)
- assert.isFalse(c.ok)
- })
- })
-
- describe('#div', () => {
- const a = BigNumber.from('5678')
- const b = BigNumber.from('-5678')
-
- it('divides correctly', async () => {
- const c = await math.div(a, b)
-
- bigNumEquals(a.div(b), c.result)
- assert.isTrue(c.ok)
- })
-
- it('divides a 0 numerator correctly', async () => {
- const c = await math.div(0, a)
-
- bigNumEquals(0, c.result)
- assert.isTrue(c.ok)
- })
-
- it('returns complete number result on non-even division', async () => {
- const c = await math.div(7000, 5678)
-
- bigNumEquals(1, c.result)
- assert.isTrue(c.ok)
- })
-
- it('reverts when 0 is the denominator', async () => {
- const c = await math.div(a, 0)
-
- bigNumEquals(0, c.result)
- assert.isFalse(c.ok)
- })
-
- it('reverts on underflow with a negative denominator', async () => {
- const c = await math.div(int256Min, -1)
-
- bigNumEquals(0, c.result)
- assert.isFalse(c.ok)
- })
- })
-})
diff --git a/contracts/test/v0.6/DeviationFlaggingValidator.test.ts b/contracts/test/v0.6/DeviationFlaggingValidator.test.ts
deleted file mode 100644
index f79a8c7aa4..0000000000
--- a/contracts/test/v0.6/DeviationFlaggingValidator.test.ts
+++ /dev/null
@@ -1,296 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { BigNumber, Contract, ContractFactory } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { bigNumEquals } from '../test-helpers/matchers'
-
-let personas: Personas
-let validatorFactory: ContractFactory
-let flagsFactory: ContractFactory
-let acFactory: ContractFactory
-
-before(async () => {
- personas = (await getUsers()).personas
- validatorFactory = await ethers.getContractFactory(
- 'src/v0.6/DeviationFlaggingValidator.sol:DeviationFlaggingValidator',
- personas.Carol,
- )
- flagsFactory = await ethers.getContractFactory(
- 'src/v0.6/Flags.sol:Flags',
- personas.Carol,
- )
- acFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleWriteAccessController.sol:SimpleWriteAccessController',
- personas.Carol,
- )
-})
-
-describe('DeviationFlaggingValidator', () => {
- let validator: Contract
- let flags: Contract
- let ac: Contract
- const flaggingThreshold = 10000 // 10%
- const previousRoundId = 2
- const previousValue = 1000000
- const currentRoundId = 3
- const currentValue = 1000000
-
- beforeEach(async () => {
- ac = await acFactory.connect(personas.Carol).deploy()
- flags = await flagsFactory.connect(personas.Carol).deploy(ac.address)
- validator = await validatorFactory
- .connect(personas.Carol)
- .deploy(flags.address, flaggingThreshold)
- await ac.connect(personas.Carol).addAccess(validator.address)
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(validator, [
- 'THRESHOLD_MULTIPLIER',
- 'flaggingThreshold',
- 'flags',
- 'isValid',
- 'setFlagsAddress',
- 'setFlaggingThreshold',
- 'validate',
- // Owned methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#constructor', () => {
- it('sets the arguments passed in', async () => {
- assert.equal(flags.address, await validator.flags())
- bigNumEquals(flaggingThreshold, await validator.flaggingThreshold())
- })
- })
-
- describe('#validate', () => {
- describe('when the deviation is greater than the threshold', () => {
- const currentValue = 1100010
-
- it('does raises a flag for the calling address', async () => {
- await expect(
- validator
- .connect(personas.Nelly)
- .validate(
- previousRoundId,
- previousValue,
- currentRoundId,
- currentValue,
- ),
- )
- .to.emit(flags, 'FlagRaised')
- .withArgs(await personas.Nelly.getAddress())
- })
-
- it('uses less than the gas allotted by the aggregator', async () => {
- const tx = await validator
- .connect(personas.Nelly)
- .validate(
- previousRoundId,
- previousValue,
- currentRoundId,
- currentValue,
- )
- const receipt = await tx.wait()
- assert(receipt)
- if (receipt && receipt.gasUsed) {
- assert.isAbove(receipt.gasUsed.toNumber(), 60000)
- }
- })
- })
-
- describe('when the deviation is less than or equal to the threshold', () => {
- const currentValue = 1100009
-
- it('does raises a flag for the calling address', async () => {
- await expect(
- validator
- .connect(personas.Nelly)
- .validate(
- previousRoundId,
- previousValue,
- currentRoundId,
- currentValue,
- ),
- ).to.not.emit(flags, 'FlagRaised')
- })
-
- it('uses less than the gas allotted by the aggregator', async () => {
- const tx = await validator
- .connect(personas.Nelly)
- .validate(
- previousRoundId,
- previousValue,
- currentRoundId,
- currentValue,
- )
- const receipt = await tx.wait()
- assert(receipt)
- if (receipt && receipt.gasUsed) {
- assert.isAbove(receipt.gasUsed.toNumber(), 24000)
- }
- })
- })
-
- describe('when called with a previous value of zero', () => {
- const previousValue = 0
-
- it('does not raise any flags', async () => {
- const tx = await validator
- .connect(personas.Nelly)
- .validate(
- previousRoundId,
- previousValue,
- currentRoundId,
- currentValue,
- )
- const receipt = await tx.wait()
- assert.equal(0, receipt.events?.length)
- })
- })
- })
-
- describe('#isValid', () => {
- const previousValue = 1000000
-
- describe('with a validation larger than the deviation', () => {
- const currentValue = 1100010
- it('is not valid', async () => {
- assert.isFalse(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
-
- describe('with a validation smaller than the deviation', () => {
- const currentValue = 1100009
- it('is valid', async () => {
- assert.isTrue(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
-
- describe('with positive previous and negative current', () => {
- const previousValue = 1000000
- const currentValue = -900000
- it('correctly detects the difference', async () => {
- assert.isFalse(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
-
- describe('with negative previous and positive current', () => {
- const previousValue = -900000
- const currentValue = 1000000
- it('correctly detects the difference', async () => {
- assert.isFalse(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
-
- describe('when the difference overflows', () => {
- const previousValue = BigNumber.from(2).pow(255).sub(1)
- const currentValue = BigNumber.from(-1)
-
- it('does not revert and returns false', async () => {
- assert.isFalse(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
-
- describe('when the rounding overflows', () => {
- const previousValue = BigNumber.from(2).pow(255).div(10000)
- const currentValue = BigNumber.from(1)
-
- it('does not revert and returns false', async () => {
- assert.isFalse(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
-
- describe('when the division overflows', () => {
- const previousValue = BigNumber.from(2).pow(255).sub(1)
- const currentValue = BigNumber.from(-1)
-
- it('does not revert and returns false', async () => {
- assert.isFalse(
- await validator.isValid(0, previousValue, 1, currentValue),
- )
- })
- })
- })
-
- describe('#setFlaggingThreshold', () => {
- const newThreshold = 777
-
- it('changes the flagging thresold', async () => {
- assert.equal(flaggingThreshold, await validator.flaggingThreshold())
-
- await validator.connect(personas.Carol).setFlaggingThreshold(newThreshold)
-
- assert.equal(newThreshold, await validator.flaggingThreshold())
- })
-
- it('emits a log event only when actually changed', async () => {
- await expect(
- validator.connect(personas.Carol).setFlaggingThreshold(newThreshold),
- )
- .to.emit(validator, 'FlaggingThresholdUpdated')
- .withArgs(flaggingThreshold, newThreshold)
-
- await expect(
- validator.connect(personas.Carol).setFlaggingThreshold(newThreshold),
- ).to.not.emit(validator, 'FlaggingThresholdUpdated')
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- validator.connect(personas.Neil).setFlaggingThreshold(newThreshold),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
- })
-
- describe('#setFlagsAddress', () => {
- const newFlagsAddress = '0x0123456789012345678901234567890123456789'
-
- it('changes the flags address', async () => {
- assert.equal(flags.address, await validator.flags())
-
- await validator.connect(personas.Carol).setFlagsAddress(newFlagsAddress)
-
- assert.equal(newFlagsAddress, await validator.flags())
- })
-
- it('emits a log event only when actually changed', async () => {
- await expect(
- validator.connect(personas.Carol).setFlagsAddress(newFlagsAddress),
- )
- .to.emit(validator, 'FlagsAddressUpdated')
- .withArgs(flags.address, newFlagsAddress)
-
- await expect(
- validator.connect(personas.Carol).setFlagsAddress(newFlagsAddress),
- ).to.not.emit(validator, 'FlagsAddressUpdated')
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- validator.connect(personas.Neil).setFlagsAddress(newFlagsAddress),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
- })
-})
diff --git a/contracts/test/v0.6/Flags.test.ts b/contracts/test/v0.6/Flags.test.ts
deleted file mode 100644
index 8f58918429..0000000000
--- a/contracts/test/v0.6/Flags.test.ts
+++ /dev/null
@@ -1,405 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { Contract, ContractFactory } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-
-let personas: Personas
-
-let controllerFactory: ContractFactory
-let flagsFactory: ContractFactory
-let consumerFactory: ContractFactory
-
-let controller: Contract
-let flags: Contract
-let consumer: Contract
-
-before(async () => {
- personas = (await getUsers()).personas
- controllerFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleWriteAccessController.sol:SimpleWriteAccessController',
- personas.Nelly,
- )
- consumerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/FlagsTestHelper.sol:FlagsTestHelper',
- personas.Nelly,
- )
- flagsFactory = await ethers.getContractFactory(
- 'src/v0.6/Flags.sol:Flags',
- personas.Nelly,
- )
-})
-
-describe('Flags', () => {
- beforeEach(async () => {
- controller = await controllerFactory.deploy()
- flags = await flagsFactory.deploy(controller.address)
- await flags.disableAccessCheck()
- consumer = await consumerFactory.deploy(flags.address)
- })
-
- it('has a limited public interface [ @skip-coverage ]', async () => {
- publicAbi(flags, [
- 'getFlag',
- 'getFlags',
- 'lowerFlags',
- 'raiseFlag',
- 'raiseFlags',
- 'raisingAccessController',
- 'setRaisingAccessController',
- // Ownable methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- // AccessControl methods:
- 'addAccess',
- 'disableAccessCheck',
- 'enableAccessCheck',
- 'removeAccess',
- 'checkEnabled',
- 'hasAccess',
- ])
- })
-
- describe('#raiseFlag', () => {
- describe('when called by the owner', () => {
- it('updates the warning flag', async () => {
- assert.equal(false, await flags.getFlag(consumer.address))
-
- await flags.connect(personas.Nelly).raiseFlag(consumer.address)
-
- assert.equal(true, await flags.getFlag(consumer.address))
- })
-
- it('emits an event log', async () => {
- await expect(flags.connect(personas.Nelly).raiseFlag(consumer.address))
- .to.emit(flags, 'FlagRaised')
- .withArgs(consumer.address)
- })
-
- describe('if a flag has already been raised', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).raiseFlag(consumer.address)
- })
-
- it('emits an event log', async () => {
- const tx = await flags
- .connect(personas.Nelly)
- .raiseFlag(consumer.address)
- const receipt = await tx.wait()
- assert.equal(0, receipt.events?.length)
- })
- })
- })
-
- describe('when called by an enabled setter', () => {
- beforeEach(async () => {
- await controller
- .connect(personas.Nelly)
- .addAccess(await personas.Neil.getAddress())
- })
-
- it('sets the flags', async () => {
- await flags.connect(personas.Neil).raiseFlag(consumer.address),
- assert.equal(true, await flags.getFlag(consumer.address))
- })
- })
-
- describe('when called by a non-enabled setter', () => {
- it('reverts', async () => {
- await expect(
- flags.connect(personas.Neil).raiseFlag(consumer.address),
- ).to.be.revertedWith('Not allowed to raise flags')
- })
- })
-
- describe('when called when there is no raisingAccessController', () => {
- beforeEach(async () => {
- await expect(
- flags
- .connect(personas.Nelly)
- .setRaisingAccessController(
- '0x0000000000000000000000000000000000000000',
- ),
- ).to.emit(flags, 'RaisingAccessControllerUpdated')
- assert.equal(
- '0x0000000000000000000000000000000000000000',
- await flags.raisingAccessController(),
- )
- })
-
- it('succeeds for the owner', async () => {
- await flags.connect(personas.Nelly).raiseFlag(consumer.address)
- assert.equal(true, await flags.getFlag(consumer.address))
- })
-
- it('reverts for non-owner', async () => {
- await expect(flags.connect(personas.Neil).raiseFlag(consumer.address))
- .to.be.reverted
- })
- })
- })
-
- describe('#raiseFlags', () => {
- describe('when called by the owner', () => {
- it('updates the warning flag', async () => {
- assert.equal(false, await flags.getFlag(consumer.address))
-
- await flags.connect(personas.Nelly).raiseFlags([consumer.address])
-
- assert.equal(true, await flags.getFlag(consumer.address))
- })
-
- it('emits an event log', async () => {
- await expect(
- flags.connect(personas.Nelly).raiseFlags([consumer.address]),
- )
- .to.emit(flags, 'FlagRaised')
- .withArgs(consumer.address)
- })
-
- describe('if a flag has already been raised', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).raiseFlags([consumer.address])
- })
-
- it('emits an event log', async () => {
- const tx = await flags
- .connect(personas.Nelly)
- .raiseFlags([consumer.address])
- const receipt = await tx.wait()
- assert.equal(0, receipt.events?.length)
- })
- })
- })
-
- describe('when called by an enabled setter', () => {
- beforeEach(async () => {
- await controller
- .connect(personas.Nelly)
- .addAccess(await personas.Neil.getAddress())
- })
-
- it('sets the flags', async () => {
- await flags.connect(personas.Neil).raiseFlags([consumer.address]),
- assert.equal(true, await flags.getFlag(consumer.address))
- })
- })
-
- describe('when called by a non-enabled setter', () => {
- it('reverts', async () => {
- await expect(
- flags.connect(personas.Neil).raiseFlags([consumer.address]),
- ).to.be.revertedWith('Not allowed to raise flags')
- })
- })
-
- describe('when called when there is no raisingAccessController', () => {
- beforeEach(async () => {
- await expect(
- flags
- .connect(personas.Nelly)
- .setRaisingAccessController(
- '0x0000000000000000000000000000000000000000',
- ),
- ).to.emit(flags, 'RaisingAccessControllerUpdated')
-
- assert.equal(
- '0x0000000000000000000000000000000000000000',
- await flags.raisingAccessController(),
- )
- })
-
- it('succeeds for the owner', async () => {
- await flags.connect(personas.Nelly).raiseFlags([consumer.address])
- assert.equal(true, await flags.getFlag(consumer.address))
- })
-
- it('reverts for non-owners', async () => {
- await expect(
- flags.connect(personas.Neil).raiseFlags([consumer.address]),
- ).to.be.reverted
- })
- })
- })
-
- describe('#lowerFlags', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).raiseFlags([consumer.address])
- })
-
- describe('when called by the owner', () => {
- it('updates the warning flag', async () => {
- assert.equal(true, await flags.getFlag(consumer.address))
-
- await flags.connect(personas.Nelly).lowerFlags([consumer.address])
-
- assert.equal(false, await flags.getFlag(consumer.address))
- })
-
- it('emits an event log', async () => {
- await expect(
- flags.connect(personas.Nelly).lowerFlags([consumer.address]),
- )
- .to.emit(flags, 'FlagLowered')
- .withArgs(consumer.address)
- })
-
- describe('if a flag has already been raised', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).lowerFlags([consumer.address])
- })
-
- it('emits an event log', async () => {
- const tx = await flags
- .connect(personas.Nelly)
- .lowerFlags([consumer.address])
- const receipt = await tx.wait()
- assert.equal(0, receipt.events?.length)
- })
- })
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- flags.connect(personas.Neil).lowerFlags([consumer.address]),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
- })
-
- describe('#getFlag', () => {
- describe('if the access control is turned on', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).enableAccessCheck()
- })
-
- it('reverts', async () => {
- await expect(consumer.getFlag(consumer.address)).to.be.revertedWith(
- 'No access',
- )
- })
-
- describe('if access is granted to the address', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).addAccess(consumer.address)
- })
-
- it('does not revert', async () => {
- await consumer.getFlag(consumer.address)
- })
- })
- })
-
- describe('if the access control is turned off', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).disableAccessCheck()
- })
-
- it('does not revert', async () => {
- await consumer.getFlag(consumer.address)
- })
-
- describe('if access is granted to the address', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).addAccess(consumer.address)
- })
-
- it('does not revert', async () => {
- await consumer.getFlag(consumer.address)
- })
- })
- })
- })
-
- describe('#getFlags', () => {
- beforeEach(async () => {
- await flags.connect(personas.Nelly).disableAccessCheck()
- await flags
- .connect(personas.Nelly)
- .raiseFlags([
- await personas.Neil.getAddress(),
- await personas.Norbert.getAddress(),
- ])
- })
-
- it('respects the access controls of #getFlag', async () => {
- await flags.connect(personas.Nelly).enableAccessCheck()
-
- await expect(consumer.getFlag(consumer.address)).to.be.revertedWith(
- 'No access',
- )
-
- await flags.connect(personas.Nelly).addAccess(consumer.address)
-
- await consumer.getFlag(consumer.address)
- })
-
- it('returns the flags in the order they are requested', async () => {
- const response = await consumer.getFlags([
- await personas.Nelly.getAddress(),
- await personas.Neil.getAddress(),
- await personas.Ned.getAddress(),
- await personas.Norbert.getAddress(),
- ])
-
- assert.deepEqual([false, true, false, true], response)
- })
- })
-
- describe('#setRaisingAccessController', () => {
- let controller2: Contract
-
- beforeEach(async () => {
- controller2 = await controllerFactory.connect(personas.Nelly).deploy()
- await controller2.connect(personas.Nelly).enableAccessCheck()
- })
-
- it('updates access control rules', async () => {
- const neilAddress = await personas.Neil.getAddress()
- await controller.connect(personas.Nelly).addAccess(neilAddress)
- await flags.connect(personas.Neil).raiseFlags([consumer.address]) // doesn't raise
-
- await flags
- .connect(personas.Nelly)
- .setRaisingAccessController(controller2.address)
-
- await expect(
- flags.connect(personas.Neil).raiseFlags([consumer.address]),
- ).to.be.revertedWith('Not allowed to raise flags')
- })
-
- it('emits a log announcing the change', async () => {
- await expect(
- flags
- .connect(personas.Nelly)
- .setRaisingAccessController(controller2.address),
- )
- .to.emit(flags, 'RaisingAccessControllerUpdated')
- .withArgs(controller.address, controller2.address)
- })
-
- it('does not emit a log when there is no change', async () => {
- await flags
- .connect(personas.Nelly)
- .setRaisingAccessController(controller2.address)
-
- await expect(
- flags
- .connect(personas.Nelly)
- .setRaisingAccessController(controller2.address),
- ).to.not.emit(flags, 'RaisingAccessControllerUpdated')
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- flags
- .connect(personas.Neil)
- .setRaisingAccessController(controller2.address),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
- })
-})
diff --git a/contracts/test/v0.6/FluxAggregator.test.ts b/contracts/test/v0.6/FluxAggregator.test.ts
deleted file mode 100644
index 5a268ceebe..0000000000
--- a/contracts/test/v0.6/FluxAggregator.test.ts
+++ /dev/null
@@ -1,3252 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert, expect } from 'chai'
-import {
- Signer,
- Contract,
- ContractFactory,
- BigNumber,
- BigNumberish,
- ContractTransaction,
- constants,
-} from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { bigNumEquals, evmRevert } from '../test-helpers/matchers'
-import {
- publicAbi,
- toWei,
- increaseTimeBy,
- mineBlock,
- evmWordToAddress,
-} from '../test-helpers/helpers'
-import { randomBytes } from '@ethersproject/random'
-import { fail } from 'assert'
-
-let personas: Personas
-let linkTokenFactory: ContractFactory
-let fluxAggregatorFactory: ContractFactory
-let validatorMockFactory: ContractFactory
-let testHelperFactory: ContractFactory
-let validatorFactory: ContractFactory
-let flagsFactory: ContractFactory
-let acFactory: ContractFactory
-let gasGuzzlerFactory: ContractFactory
-let emptyAddress: string
-
-before(async () => {
- personas = (await getUsers()).personas
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- )
- fluxAggregatorFactory = await ethers.getContractFactory(
- 'src/v0.6/FluxAggregator.sol:FluxAggregator',
- )
- validatorMockFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/AggregatorValidatorMock.sol:AggregatorValidatorMock',
- )
- testHelperFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/FluxAggregatorTestHelper.sol:FluxAggregatorTestHelper',
- )
- validatorFactory = await ethers.getContractFactory(
- 'src/v0.6/DeviationFlaggingValidator.sol:DeviationFlaggingValidator',
- )
- flagsFactory = await ethers.getContractFactory('src/v0.6/Flags.sol:Flags')
- acFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleWriteAccessController.sol:SimpleWriteAccessController',
- )
- gasGuzzlerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/GasGuzzler.sol:GasGuzzler',
- )
- emptyAddress = constants.AddressZero
-})
-
-describe('FluxAggregator', () => {
- const paymentAmount = toWei('3')
- const deposit = toWei('100')
- const answer = 100
- const minAns = 1
- const maxAns = 1
- const rrDelay = 0
- const timeout = 1800
- const decimals = 18
- const description = 'LINK/USD'
- const reserveRounds = 2
- const minSubmissionValue = BigNumber.from('1')
- const maxSubmissionValue = BigNumber.from('100000000000000000000')
-
- let aggregator: Contract
- let link: Contract
- let testHelper: Contract
- let validator: Contract
- let gasGuzzler: Contract
- let nextRound: number
- let oracles: Signer[]
-
- async function updateFutureRounds(
- aggregator: Contract,
- overrides: {
- minAnswers?: BigNumberish
- maxAnswers?: BigNumberish
- payment?: BigNumberish
- restartDelay?: BigNumberish
- timeout?: BigNumberish
- } = {},
- ) {
- overrides = overrides || {}
- const round = {
- payment: overrides.payment || paymentAmount,
- minAnswers: overrides.minAnswers || minAns,
- maxAnswers: overrides.maxAnswers || maxAns,
- restartDelay: overrides.restartDelay || rrDelay,
- timeout: overrides.timeout || timeout,
- }
-
- return aggregator.updateFutureRounds(
- round.payment,
- round.minAnswers,
- round.maxAnswers,
- round.restartDelay,
- round.timeout,
- )
- }
-
- async function addOracles(
- aggregator: Contract,
- oraclesAndAdmin: Signer[],
- minAnswers: number,
- maxAnswers: number,
- restartDelay: number,
- ): Promise {
- return aggregator.connect(personas.Carol).changeOracles(
- [],
- oraclesAndAdmin.map(async (oracle) => await oracle.getAddress()),
- oraclesAndAdmin.map(async (admin) => await admin.getAddress()),
- minAnswers,
- maxAnswers,
- restartDelay,
- )
- }
-
- async function advanceRound(
- aggregator: Contract,
- submitters: Signer[],
- currentSubmission: number = answer,
- ): Promise {
- for (const submitter of submitters) {
- await aggregator.connect(submitter).submit(nextRound, currentSubmission)
- }
- nextRound++
- return nextRound
- }
-
- const ShouldBeSet = 'expects it to be different'
- const ShouldNotBeSet = 'expects it to equal'
- let startingState: any
-
- async function checkOracleRoundState(
- state: any,
- want: {
- eligibleToSubmit: boolean
- roundId: BigNumberish
- latestSubmission: BigNumberish
- startedAt: string
- timeout: BigNumberish
- availableFunds: BigNumberish
- oracleCount: BigNumberish
- paymentAmount: BigNumberish
- },
- ) {
- assert.equal(
- want.eligibleToSubmit,
- state._eligibleToSubmit,
- 'round state: unexecpted eligibility',
- )
- bigNumEquals(
- want.roundId,
- state._roundId,
- 'round state: unexpected Round ID',
- )
- bigNumEquals(
- want.latestSubmission,
- state._latestSubmission,
- 'round state: unexpected latest submission',
- )
- if (want.startedAt === ShouldBeSet) {
- assert.isAbove(
- state._startedAt.toNumber(),
- startingState._startedAt.toNumber(),
- 'round state: expected the started at to be the same as previous',
- )
- } else {
- bigNumEquals(
- 0,
- state._startedAt,
- 'round state: expected the started at not to be updated',
- )
- }
- bigNumEquals(
- want.timeout,
- state._timeout.toNumber(),
- 'round state: unexepcted timeout',
- )
- bigNumEquals(
- want.availableFunds,
- state._availableFunds,
- 'round state: unexepected funds',
- )
- bigNumEquals(
- want.oracleCount,
- state._oracleCount,
- 'round state: unexpected oracle count',
- )
- bigNumEquals(
- want.paymentAmount,
- state._paymentAmount,
- 'round state: unexpected paymentamount',
- )
- }
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(personas.Default).deploy()
- aggregator = await fluxAggregatorFactory
- .connect(personas.Carol)
- .deploy(
- link.address,
- paymentAmount,
- timeout,
- emptyAddress,
- minSubmissionValue,
- maxSubmissionValue,
- decimals,
- ethers.utils.formatBytes32String(description),
- )
- await link.transfer(aggregator.address, deposit)
- await aggregator.updateAvailableFunds()
- bigNumEquals(deposit, await link.balanceOf(aggregator.address))
- nextRound = 1
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(aggregator, [
- 'acceptAdmin',
- 'allocatedFunds',
- 'availableFunds',
- 'changeOracles',
- 'decimals',
- 'description',
- 'getAdmin',
- 'getAnswer',
- 'getOracles',
- 'getRoundData',
- 'getTimestamp',
- 'latestAnswer',
- 'latestRound',
- 'latestRoundData',
- 'latestTimestamp',
- 'linkToken',
- 'maxSubmissionCount',
- 'maxSubmissionValue',
- 'minSubmissionCount',
- 'minSubmissionValue',
- 'onTokenTransfer',
- 'oracleCount',
- 'oracleRoundState',
- 'paymentAmount',
- 'requestNewRound',
- 'restartDelay',
- 'setRequesterPermissions',
- 'setValidator',
- 'submit',
- 'timeout',
- 'transferAdmin',
- 'updateAvailableFunds',
- 'updateFutureRounds',
- 'withdrawFunds',
- 'withdrawPayment',
- 'withdrawablePayment',
- 'validator',
- 'version',
- // Owned methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#constructor', () => {
- it('sets the paymentAmount', async () => {
- bigNumEquals(
- BigNumber.from(paymentAmount),
- await aggregator.paymentAmount(),
- )
- })
-
- it('sets the timeout', async () => {
- bigNumEquals(BigNumber.from(timeout), await aggregator.timeout())
- })
-
- it('sets the decimals', async () => {
- bigNumEquals(BigNumber.from(decimals), await aggregator.decimals())
- })
-
- it('sets the description', async () => {
- assert.equal(
- ethers.utils.formatBytes32String(description),
- await aggregator.description(),
- )
- })
-
- it('sets the version to 3', async () => {
- bigNumEquals(3, await aggregator.version())
- })
-
- it('sets the validator', async () => {
- assert.equal(emptyAddress, await aggregator.validator())
- })
- })
-
- describe('#submit', () => {
- let minMax
-
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Ned, personas.Nelly]
- minMax = oracles.length
- await addOracles(aggregator, oracles, minMax, minMax, rrDelay)
- })
-
- it('updates the allocated and available funds counters', async () => {
- bigNumEquals(0, await aggregator.allocatedFunds())
-
- const tx = await aggregator
- .connect(personas.Neil)
- .submit(nextRound, answer)
- const receipt = await tx.wait()
-
- bigNumEquals(paymentAmount, await aggregator.allocatedFunds())
- const expectedAvailable = deposit.sub(paymentAmount)
- bigNumEquals(expectedAvailable, await aggregator.availableFunds())
- const logged = BigNumber.from(
- receipt.logs?.[2].topics[1] ?? BigNumber.from(-1),
- )
- bigNumEquals(expectedAvailable, logged)
- })
-
- it('emits a log event announcing submission details', async () => {
- await expect(aggregator.connect(personas.Nelly).submit(nextRound, answer))
- .to.emit(aggregator, 'SubmissionReceived')
- .withArgs(answer, nextRound, await personas.Nelly.getAddress())
- })
-
- describe('when the minimum oracles have not reported', () => {
- it('pays the oracles that have reported', async () => {
- bigNumEquals(
- 0,
- await aggregator
- .connect(personas.Neil)
- .withdrawablePayment(await personas.Neil.getAddress()),
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- bigNumEquals(
- paymentAmount,
- await aggregator
- .connect(personas.Neil)
- .withdrawablePayment(await personas.Neil.getAddress()),
- )
- bigNumEquals(
- 0,
- await aggregator
- .connect(personas.Ned)
- .withdrawablePayment(await personas.Ned.getAddress()),
- )
- bigNumEquals(
- 0,
- await aggregator
- .connect(personas.Nelly)
- .withdrawablePayment(await personas.Nelly.getAddress()),
- )
- })
-
- it('does not update the answer', async () => {
- bigNumEquals(ethers.constants.Zero, await aggregator.latestAnswer())
-
- // Not updated because of changes by the owner setting minSubmissionCount to 3
- await aggregator.connect(personas.Ned).submit(nextRound, answer)
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- bigNumEquals(ethers.constants.Zero, await aggregator.latestAnswer())
- })
- })
-
- describe('when an oracle prematurely bumps the round', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, { minAnswers: 2, maxAnswers: 3 })
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
-
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Neil).submit(nextRound + 1, answer),
- 'previous round not supersedable',
- )
- })
- })
-
- describe('when the minimum number of oracles have reported', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, { minAnswers: 2, maxAnswers: 3 })
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
-
- it('updates the answer with the median', async () => {
- bigNumEquals(0, await aggregator.latestAnswer())
-
- await aggregator.connect(personas.Ned).submit(nextRound, 99)
- bigNumEquals(99, await aggregator.latestAnswer()) // ((100+99) / 2).to_i
-
- await aggregator.connect(personas.Nelly).submit(nextRound, 101)
-
- bigNumEquals(100, await aggregator.latestAnswer())
- })
-
- it('updates the updated timestamp', async () => {
- const originalTimestamp = await aggregator.latestTimestamp()
- assert.isAbove(originalTimestamp.toNumber(), 0)
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- const currentTimestamp = await aggregator.latestTimestamp()
- assert.isAbove(
- currentTimestamp.toNumber(),
- originalTimestamp.toNumber(),
- )
- })
-
- it('announces the new answer with a log event', async () => {
- const tx = await aggregator
- .connect(personas.Nelly)
- .submit(nextRound, answer)
- const receipt = await tx.wait()
-
- const newAnswer = BigNumber.from(
- receipt.logs?.[0].topics[1] ?? ethers.constants.Zero,
- )
-
- assert.equal(answer, newAnswer.toNumber())
- })
-
- it('does not set the timedout flag', async () => {
- evmRevert(aggregator.getRoundData(nextRound), 'No data present')
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- const round = await aggregator.getRoundData(nextRound)
- assert.equal(nextRound, round.answeredInRound.toNumber())
- })
-
- it('updates the round details', async () => {
- evmRevert(aggregator.latestRoundData(), 'No data present')
-
- increaseTimeBy(15, ethers.provider)
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- const roundAfter = await aggregator.getRoundData(nextRound)
- bigNumEquals(nextRound, roundAfter.roundId)
- bigNumEquals(answer, roundAfter.answer)
- assert.isFalse(roundAfter.startedAt.isZero())
- bigNumEquals(
- await aggregator.getTimestamp(nextRound),
- roundAfter.updatedAt,
- )
- bigNumEquals(nextRound, roundAfter.answeredInRound)
-
- assert.isBelow(
- roundAfter.startedAt.toNumber(),
- roundAfter.updatedAt.toNumber(),
- )
-
- const roundAfterLatest = await aggregator.latestRoundData()
- bigNumEquals(roundAfter.roundId, roundAfterLatest.roundId)
- bigNumEquals(roundAfter.answer, roundAfterLatest.answer)
- bigNumEquals(roundAfter.startedAt, roundAfterLatest.startedAt)
- bigNumEquals(roundAfter.updatedAt, roundAfterLatest.updatedAt)
- bigNumEquals(
- roundAfter.answeredInRound,
- roundAfterLatest.answeredInRound,
- )
- })
- })
-
- describe('when an oracle submits for a round twice', () => {
- it('reverts', async () => {
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- await evmRevert(
- aggregator.connect(personas.Neil).submit(nextRound, answer),
- 'cannot report on previous rounds',
- )
- })
- })
-
- describe('when updated after the max answers submitted', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator)
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
-
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Ned).submit(nextRound, answer),
- 'round not accepting submissions',
- )
- })
- })
-
- describe('when a new highest round number is passed in', () => {
- it('increments the answer round', async () => {
- const startingState = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
- bigNumEquals(1, startingState._roundId)
-
- await advanceRound(aggregator, oracles)
-
- const updatedState = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
- bigNumEquals(2, updatedState._roundId)
- })
-
- it('sets the startedAt time for the reporting round', async () => {
- evmRevert(aggregator.getRoundData(nextRound), 'No data present')
-
- const tx = await aggregator
- .connect(oracles[0])
- .submit(nextRound, answer)
- await aggregator.connect(oracles[1]).submit(nextRound, answer)
- await aggregator.connect(oracles[2]).submit(nextRound, answer)
- const receipt = await tx.wait()
- const block = await ethers.provider.getBlock(receipt.blockHash ?? '')
-
- const round = await aggregator.getRoundData(nextRound)
- bigNumEquals(BigNumber.from(block.timestamp), round.startedAt)
- })
-
- it('announces a new round by emitting a log', async () => {
- const tx = await aggregator
- .connect(personas.Neil)
- .submit(nextRound, answer)
- const receipt = await tx.wait()
-
- const topics = receipt.logs?.[0].topics ?? []
- const roundNumber = BigNumber.from(topics[1])
- const startedBy = evmWordToAddress(topics[2])
-
- bigNumEquals(nextRound, roundNumber.toNumber())
- bigNumEquals(startedBy, await personas.Neil.getAddress())
- })
- })
-
- describe('when a round is passed in higher than expected', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Neil).submit(nextRound + 1, answer),
- 'invalid round to report',
- )
- })
- })
-
- describe('when called by a non-oracle', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Carol).submit(nextRound, answer),
- 'not enabled oracle',
- )
- })
- })
-
- describe('when there are not sufficient available funds', () => {
- beforeEach(async () => {
- await aggregator
- .connect(personas.Carol)
- .withdrawFunds(
- await personas.Carol.getAddress(),
- deposit.sub(paymentAmount.mul(oracles.length).mul(reserveRounds)),
- )
-
- // drain remaining funds
- await advanceRound(aggregator, oracles)
- await advanceRound(aggregator, oracles)
- })
-
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Neil).submit(nextRound, answer),
- 'SafeMath: subtraction overflow',
- )
- })
- })
-
- describe('when a new round opens before the previous rounds closes', () => {
- beforeEach(async () => {
- oracles = [personas.Nancy, personas.Norbert]
- await addOracles(aggregator, oracles, 3, 4, rrDelay)
- await advanceRound(aggregator, [
- personas.Nelly,
- personas.Neil,
- personas.Nancy,
- ])
-
- // start the next round
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- })
-
- it('still allows the previous round to be answered', async () => {
- await aggregator.connect(personas.Ned).submit(nextRound - 1, answer)
- })
-
- describe('once the current round is answered', () => {
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Nancy]
- for (let i = 0; i < oracles.length; i++) {
- await aggregator.connect(oracles[i]).submit(nextRound, answer)
- }
- })
-
- it('does not allow reports for the previous round', async () => {
- await evmRevert(
- aggregator.connect(personas.Ned).submit(nextRound - 1, answer),
- 'invalid round to report',
- )
- })
- })
-
- describe('when the previous round has finished', () => {
- beforeEach(async () => {
- await aggregator
- .connect(personas.Norbert)
- .submit(nextRound - 1, answer)
- })
-
- it('does not allow reports for the previous round', async () => {
- await evmRevert(
- aggregator.connect(personas.Ned).submit(nextRound - 1, answer),
- 'round not accepting submissions',
- )
- })
- })
- })
-
- describe('when price is updated mid-round', () => {
- const newAmount = toWei('50')
-
- it('pays the same amount to all oracles per round', async () => {
- await link.transfer(
- aggregator.address,
- newAmount.mul(oracles.length).mul(reserveRounds),
- )
- await aggregator.updateAvailableFunds()
-
- bigNumEquals(
- 0,
- await aggregator
- .connect(personas.Neil)
- .withdrawablePayment(await personas.Neil.getAddress()),
- )
- bigNumEquals(
- 0,
- await aggregator
- .connect(personas.Nelly)
- .withdrawablePayment(await personas.Nelly.getAddress()),
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- await updateFutureRounds(aggregator, { payment: newAmount })
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- bigNumEquals(
- paymentAmount,
- await aggregator
- .connect(personas.Neil)
- .withdrawablePayment(await personas.Neil.getAddress()),
- )
- bigNumEquals(
- paymentAmount,
- await aggregator
- .connect(personas.Nelly)
- .withdrawablePayment(await personas.Nelly.getAddress()),
- )
- })
- })
-
- describe('when delay is on', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, {
- minAnswers: oracles.length,
- maxAnswers: oracles.length,
- restartDelay: 1,
- })
- })
-
- it("does not revert on the oracle's first round", async () => {
- // Since lastUpdatedRound defaults to zero and that's the only
- // indication that an oracle hasn't responded, this test guards against
- // the situation where we don't check that and no one can start a round.
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
-
- it('does revert before the delay', async () => {
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- nextRound++
-
- await evmRevert(
- aggregator.connect(personas.Neil).submit(nextRound, answer),
- 'previous round not supersedable',
- )
- })
- })
-
- describe('when an oracle starts a round before the restart delay is over', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator.connect(personas.Carol), {
- minAnswers: 1,
- maxAnswers: 1,
- })
-
- oracles = [personas.Neil, personas.Ned, personas.Nelly]
- for (let i = 0; i < oracles.length; i++) {
- await aggregator.connect(oracles[i]).submit(nextRound, answer)
- nextRound++
- }
-
- const newDelay = 2
- // Since Ned and Nelly have answered recently, and we set the delay
- // to 2, only Nelly can answer as she is the only oracle that hasn't
- // started the last two rounds.
- await updateFutureRounds(aggregator, {
- maxAnswers: oracles.length,
- restartDelay: newDelay,
- })
- })
-
- describe('when called by an oracle who has not answered recently', () => {
- it('does not revert', async () => {
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
- })
-
- describe('when called by an oracle who answered recently', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Ned).submit(nextRound, answer),
- 'round not accepting submissions',
- )
-
- await evmRevert(
- aggregator.connect(personas.Nelly).submit(nextRound, answer),
- 'round not accepting submissions',
- )
- })
- })
- })
-
- describe('when the price is not updated for a round', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, {
- minAnswers: oracles.length,
- maxAnswers: oracles.length,
- restartDelay: 1,
- })
-
- for (const oracle of oracles) {
- await aggregator.connect(oracle).submit(nextRound, answer)
- }
- nextRound++
-
- await aggregator.connect(personas.Ned).submit(nextRound, answer)
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- await increaseTimeBy(timeout + 1, ethers.provider)
- nextRound++
- })
-
- it('allows a new round to be started', async () => {
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- })
-
- it('sets the info for the previous round', async () => {
- const previousRound = nextRound - 1
- let updated = await aggregator.getTimestamp(previousRound)
- let ans = await aggregator.getAnswer(previousRound)
- assert.equal(0, updated.toNumber())
- assert.equal(0, ans.toNumber())
-
- const tx = await aggregator
- .connect(personas.Nelly)
- .submit(nextRound, answer)
- const receipt = await tx.wait()
-
- const block = await ethers.provider.getBlock(receipt.blockHash ?? '')
-
- updated = await aggregator.getTimestamp(previousRound)
- ans = await aggregator.getAnswer(previousRound)
- bigNumEquals(BigNumber.from(block.timestamp), updated)
- assert.equal(answer, ans.toNumber())
-
- const round = await aggregator.getRoundData(previousRound)
- bigNumEquals(previousRound, round.roundId)
- bigNumEquals(ans, round.answer)
- bigNumEquals(updated, round.updatedAt)
- bigNumEquals(previousRound - 1, round.answeredInRound)
- })
-
- it('sets the previous round as timed out', async () => {
- const previousRound = nextRound - 1
- evmRevert(aggregator.getRoundData(previousRound), 'No data present')
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
-
- const round = await aggregator.getRoundData(previousRound)
- assert.notEqual(round.roundId, round.answeredInRound)
- bigNumEquals(previousRound - 1, round.answeredInRound)
- })
-
- it('still respects the delay restriction', async () => {
- // expected to revert because the sender started the last round
- await evmRevert(
- aggregator.connect(personas.Ned).submit(nextRound, answer),
- )
- })
-
- it('uses the timeout set at the beginning of the round', async () => {
- await updateFutureRounds(aggregator, {
- timeout: timeout + 100000,
- })
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- })
- })
-
- describe('submitting values near the edges of allowed values', () => {
- it('rejects values below the submission value range', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Neil)
- .submit(nextRound, minSubmissionValue.sub(1)),
- 'value below minSubmissionValue',
- )
- })
-
- it('accepts submissions equal to the min submission value', async () => {
- await aggregator
- .connect(personas.Neil)
- .submit(nextRound, minSubmissionValue)
- })
-
- it('accepts submissions equal to the max submission value', async () => {
- await aggregator
- .connect(personas.Neil)
- .submit(nextRound, maxSubmissionValue)
- })
-
- it('rejects submissions equal to the max submission value', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Neil)
- .submit(nextRound, maxSubmissionValue.add(1)),
- 'value above maxSubmissionValue',
- )
- })
- })
-
- describe('when a validator is set', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, { minAnswers: 1, maxAnswers: 1 })
- oracles = [personas.Nelly]
-
- validator = await validatorMockFactory.connect(personas.Carol).deploy()
- await aggregator.connect(personas.Carol).setValidator(validator.address)
- })
-
- it('calls out to the validator', async () => {
- await expect(
- aggregator.connect(personas.Nelly).submit(nextRound, answer),
- )
- .to.emit(validator, 'Validated')
- .withArgs(0, 0, nextRound, answer)
- })
- })
-
- describe('when the answer validator eats all gas', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, { minAnswers: 1, maxAnswers: 1 })
- oracles = [personas.Nelly]
-
- gasGuzzler = await gasGuzzlerFactory.connect(personas.Carol).deploy()
- await aggregator
- .connect(personas.Carol)
- .setValidator(gasGuzzler.address)
- assert.equal(gasGuzzler.address, await aggregator.validator())
- })
-
- it('still updates', async () => {
- bigNumEquals(0, await aggregator.latestAnswer())
-
- await aggregator
- .connect(personas.Nelly)
- .submit(nextRound, answer, { gasLimit: 500000 })
-
- bigNumEquals(answer, await aggregator.latestAnswer())
- })
- })
- })
-
- describe('#getAnswer', () => {
- const answers = [1, 10, 101, 1010, 10101, 101010, 1010101]
-
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
-
- for (const answer of answers) {
- await aggregator.connect(personas.Neil).submit(nextRound++, answer)
- }
- })
-
- it('retrieves the answer recorded for past rounds', async () => {
- for (let i = nextRound; i < nextRound; i++) {
- const answer = await aggregator.getAnswer(i)
- bigNumEquals(BigNumber.from(answers[i - 1]), answer)
- }
- })
-
- it("returns 0 for answers greater than uint32's max", async () => {
- const overflowedId = BigNumber.from(2).pow(32).add(1)
- const answer = await aggregator.getAnswer(overflowedId)
- bigNumEquals(0, answer)
- })
- })
-
- describe('#getTimestamp', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
-
- for (let i = 0; i < 10; i++) {
- await aggregator.connect(personas.Neil).submit(nextRound++, i + 1)
- }
- })
-
- it('retrieves the answer recorded for past rounds', async () => {
- let lastTimestamp = ethers.constants.Zero
-
- for (let i = 1; i < nextRound; i++) {
- const currentTimestamp = await aggregator.getTimestamp(i)
- assert.isAtLeast(currentTimestamp.toNumber(), lastTimestamp.toNumber())
- lastTimestamp = currentTimestamp
- }
- })
-
- it("returns 0 for answers greater than uint32's max", async () => {
- const overflowedId = BigNumber.from(2).pow(32).add(1)
- const answer = await aggregator.getTimestamp(overflowedId)
- bigNumEquals(0, answer)
- })
- })
-
- describe('#changeOracles', () => {
- describe('adding oracles', () => {
- it('increases the oracle count', async () => {
- const pastCount = await aggregator.oracleCount()
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
- const currentCount = await aggregator.oracleCount()
-
- bigNumEquals(currentCount, pastCount + 1)
- })
-
- it('adds the address in getOracles', async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
- assert.deepEqual(
- [await personas.Neil.getAddress()],
- await aggregator.getOracles(),
- )
- })
-
- it('updates the round details', async () => {
- await addOracles(
- aggregator,
- [personas.Neil, personas.Ned, personas.Nelly],
- 1,
- 3,
- 2,
- )
- bigNumEquals(1, await aggregator.minSubmissionCount())
- bigNumEquals(3, await aggregator.maxSubmissionCount())
- bigNumEquals(2, await aggregator.restartDelay())
- })
-
- it('emits a log', async () => {
- const tx = await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [],
- [await personas.Ned.getAddress()],
- [await personas.Neil.getAddress()],
- 1,
- 1,
- 0,
- )
- expect(tx)
- .to.emit(aggregator, 'OraclePermissionsUpdated')
- .withArgs(await personas.Ned.getAddress(), true)
-
- expect(tx)
- .to.emit(aggregator, 'OracleAdminUpdated')
- .withArgs(
- await personas.Ned.getAddress(),
- await personas.Neil.getAddress(),
- )
- })
-
- describe('when the oracle has already been added', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
- })
-
- it('reverts', async () => {
- await evmRevert(
- addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay),
- 'oracle already enabled',
- )
- })
- })
-
- describe('when called by anyone but the owner', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Neil)
- .changeOracles(
- [],
- [await personas.Neil.getAddress()],
- [await personas.Neil.getAddress()],
- minAns,
- maxAns,
- rrDelay,
- ),
- 'Only callable by owner',
- )
- })
- })
-
- describe('when an oracle gets added mid-round', () => {
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Ned]
- await addOracles(
- aggregator,
- oracles,
- oracles.length,
- oracles.length,
- rrDelay,
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- await addOracles(
- aggregator,
- [personas.Nelly],
- oracles.length + 1,
- oracles.length + 1,
- rrDelay,
- )
- })
-
- it('does not allow the oracle to update the round', async () => {
- await evmRevert(
- aggregator.connect(personas.Nelly).submit(nextRound, answer),
- 'not yet enabled oracle',
- )
- })
-
- it('does allow the oracle to update future rounds', async () => {
- // complete round
- await aggregator.connect(personas.Ned).submit(nextRound, answer)
-
- // now can participate in new rounds
- await aggregator.connect(personas.Nelly).submit(nextRound + 1, answer)
- })
- })
-
- describe('when an oracle is added after removed for a round', () => {
- it('allows the oracle to update', async () => {
- oracles = [personas.Neil, personas.Nelly]
- await addOracles(
- aggregator,
- oracles,
- oracles.length,
- oracles.length,
- rrDelay,
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- nextRound++
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- 1,
- 1,
- rrDelay,
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- nextRound++
-
- await addOracles(aggregator, [personas.Nelly], 1, 1, rrDelay)
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- })
- })
-
- describe('when an oracle is added and immediately removed mid-round', () => {
- it('allows the oracle to update', async () => {
- await addOracles(
- aggregator,
- oracles,
- oracles.length,
- oracles.length,
- rrDelay,
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- nextRound++
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- 1,
- 1,
- rrDelay,
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- nextRound++
-
- await addOracles(aggregator, [personas.Nelly], 1, 1, rrDelay)
-
- await aggregator.connect(personas.Nelly).submit(nextRound, answer)
- })
- })
-
- describe('when an oracle is re-added with a different admin address', () => {
- it('reverts', async () => {
- await addOracles(
- aggregator,
- oracles,
- oracles.length,
- oracles.length,
- rrDelay,
- )
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- 1,
- 1,
- rrDelay,
- )
-
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .changeOracles(
- [],
- [await personas.Nelly.getAddress()],
- [await personas.Carol.getAddress()],
- 1,
- 1,
- rrDelay,
- ),
- 'owner cannot overwrite admin',
- )
- })
- })
-
- const limit = 77
- describe(`when adding more than ${limit} oracles`, () => {
- let oracles: Signer[]
-
- beforeEach(async () => {
- oracles = []
- for (let i = 0; i < limit; i++) {
- const account = await new ethers.Wallet(
- randomBytes(32),
- ethers.provider,
- )
- await personas.Default.sendTransaction({
- to: account.address,
- value: toWei('0.1'),
- })
-
- oracles.push(account)
- }
-
- await link.transfer(
- aggregator.address,
- paymentAmount.mul(limit).mul(reserveRounds),
- )
- await aggregator.updateAvailableFunds()
-
- let addresses = oracles.slice(0, 50).map(async (o) => o.getAddress())
- await aggregator
- .connect(personas.Carol)
- .changeOracles([], addresses, addresses, 1, 50, rrDelay)
- // add in two transactions to avoid gas limit issues
- addresses = oracles.slice(50, 100).map(async (o) => o.getAddress())
- await aggregator
- .connect(personas.Carol)
- .changeOracles([], addresses, addresses, 1, oracles.length, rrDelay)
- })
-
- it('not use too much gas [ @skip-coverage ]', async () => {
- let tx: any
- assert.deepEqual(
- // test adveserial quickselect algo
- [2, 4, 6, 8, 10, 12, 14, 16, 1, 9, 5, 11, 3, 13, 7, 15],
- adverserialQuickselectList(16),
- )
- const inputs = adverserialQuickselectList(limit)
- for (let i = 0; i < limit; i++) {
- tx = await aggregator
- .connect(oracles[i])
- .submit(nextRound, inputs[i])
- }
- assert.isTrue(!!tx)
- if (tx) {
- const receipt = await tx.wait()
- assert.isBelow(receipt.gasUsed.toNumber(), 600_000)
- }
- })
-
- function adverserialQuickselectList(len: number): number[] {
- const xs: number[] = []
- const pi: number[] = []
- for (let i = 0; i < len; i++) {
- pi[i] = i
- xs[i] = 0
- }
-
- for (let l = len; l > 0; l--) {
- const pivot = Math.floor((l - 1) / 2)
- xs[pi[pivot]] = l
- const temp = pi[l - 1]
- pi[l - 1] = pi[pivot]
- pi[pivot] = temp
- }
- return xs
- }
-
- it('reverts when another oracle is added', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .changeOracles(
- [],
- [await personas.Neil.getAddress()],
- [await personas.Neil.getAddress()],
- limit + 1,
- limit + 1,
- rrDelay,
- ),
- 'max oracles allowed',
- )
- })
- })
-
- it('reverts when minSubmissions is set to 0', async () => {
- await evmRevert(
- addOracles(aggregator, [personas.Neil], 0, 0, 0),
- 'min must be greater than 0',
- )
- })
- })
-
- describe('removing oracles', () => {
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Nelly]
- await addOracles(
- aggregator,
- oracles,
- oracles.length,
- oracles.length,
- rrDelay,
- )
- })
-
- it('decreases the oracle count', async () => {
- const pastCount = await aggregator.oracleCount()
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
- const currentCount = await aggregator.oracleCount()
-
- expect(currentCount).to.equal(pastCount - 1)
- })
-
- it('updates the round details', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles([await personas.Neil.getAddress()], [], [], 1, 1, 0)
-
- bigNumEquals(1, await aggregator.minSubmissionCount())
- bigNumEquals(1, await aggregator.maxSubmissionCount())
- bigNumEquals(ethers.constants.Zero, await aggregator.restartDelay())
- })
-
- it('emits a log', async () => {
- await expect(
- aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- ),
- )
- .to.emit(aggregator, 'OraclePermissionsUpdated')
- .withArgs(await personas.Neil.getAddress(), false)
- })
-
- it('removes the address in getOracles', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
- assert.deepEqual(
- [await personas.Nelly.getAddress()],
- await aggregator.getOracles(),
- )
- })
-
- describe('when the oracle is not currently added', () => {
- beforeEach(async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
- })
-
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- ),
- 'oracle not enabled',
- )
- })
- })
-
- describe('when removing the last oracle', () => {
- it('does not revert', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles([await personas.Nelly.getAddress()], [], [], 0, 0, 0)
- })
- })
-
- describe('when called by anyone but the owner', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Ned)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- 0,
- 0,
- rrDelay,
- ),
- 'Only callable by owner',
- )
- })
- })
-
- describe('when an oracle gets removed', () => {
- beforeEach(async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- 1,
- 1,
- rrDelay,
- )
- })
-
- it('is allowed to report on one more round', async () => {
- // next round
- await advanceRound(aggregator, [personas.Nelly])
- // finish round
- await advanceRound(aggregator, [personas.Neil])
-
- // cannot participate in future rounds
- await evmRevert(
- aggregator.connect(personas.Nelly).submit(nextRound, answer),
- 'no longer allowed oracle',
- )
- })
- })
-
- describe('when an oracle gets removed mid-round', () => {
- beforeEach(async () => {
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- 1,
- 1,
- rrDelay,
- )
- })
-
- it('is allowed to finish that round and one more round', async () => {
- await advanceRound(aggregator, [personas.Nelly]) // finish round
-
- await advanceRound(aggregator, [personas.Nelly]) // next round
-
- // cannot participate in future rounds
- await evmRevert(
- aggregator.connect(personas.Nelly).submit(nextRound, answer),
- 'no longer allowed oracle',
- )
- })
- })
-
- it('reverts when minSubmissions is set to 0', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- 0,
- 0,
- 0,
- ),
- 'min must be greater than 0',
- )
- })
- })
-
- describe('adding and removing oracles at once', () => {
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Ned]
- await addOracles(aggregator, oracles, 1, 1, rrDelay)
- })
-
- it('can swap out oracles', async () => {
- assert.include(
- await aggregator.getOracles(),
- await personas.Ned.getAddress(),
- )
- assert.notInclude(
- await aggregator.getOracles(),
- await personas.Nelly.getAddress(),
- )
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Ned.getAddress()],
- [await personas.Nelly.getAddress()],
- [await personas.Nelly.getAddress()],
- 1,
- 1,
- rrDelay,
- )
-
- assert.notInclude(
- await aggregator.getOracles(),
- await personas.Ned.getAddress(),
- )
- assert.include(
- await aggregator.getOracles(),
- await personas.Nelly.getAddress(),
- )
- })
-
- it('is possible to remove and add the same address', async () => {
- assert.include(
- await aggregator.getOracles(),
- await personas.Ned.getAddress(),
- )
-
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Ned.getAddress()],
- [await personas.Ned.getAddress()],
- [await personas.Ned.getAddress()],
- 1,
- 1,
- rrDelay,
- )
-
- assert.include(
- await aggregator.getOracles(),
- await personas.Ned.getAddress(),
- )
- })
- })
- })
-
- describe('#getOracles', () => {
- describe('after adding oracles', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
-
- assert.deepEqual(
- [await personas.Neil.getAddress()],
- await aggregator.getOracles(),
- )
- })
-
- it('returns the addresses of added oracles', async () => {
- await addOracles(aggregator, [personas.Ned], minAns, maxAns, rrDelay)
-
- assert.deepEqual(
- [await personas.Neil.getAddress(), await personas.Ned.getAddress()],
- await aggregator.getOracles(),
- )
-
- await addOracles(aggregator, [personas.Nelly], minAns, maxAns, rrDelay)
- assert.deepEqual(
- [
- await personas.Neil.getAddress(),
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- ],
- await aggregator.getOracles(),
- )
- })
- })
-
- describe('after removing oracles', () => {
- beforeEach(async () => {
- await addOracles(
- aggregator,
- [personas.Neil, personas.Ned, personas.Nelly],
- minAns,
- maxAns,
- rrDelay,
- )
-
- assert.deepEqual(
- [
- await personas.Neil.getAddress(),
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- ],
- await aggregator.getOracles(),
- )
- })
-
- it('reorders when removing from the beginning', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Neil.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
- assert.deepEqual(
- [await personas.Nelly.getAddress(), await personas.Ned.getAddress()],
- await aggregator.getOracles(),
- )
- })
-
- it('reorders when removing from the middle', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Ned.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
- assert.deepEqual(
- [await personas.Neil.getAddress(), await personas.Nelly.getAddress()],
- await aggregator.getOracles(),
- )
- })
-
- it('pops the last node off at the end', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [await personas.Nelly.getAddress()],
- [],
- [],
- minAns,
- maxAns,
- rrDelay,
- )
- assert.deepEqual(
- [await personas.Neil.getAddress(), await personas.Ned.getAddress()],
- await aggregator.getOracles(),
- )
- })
- })
- })
-
- describe('#withdrawFunds', () => {
- it('succeeds', async () => {
- await aggregator
- .connect(personas.Carol)
- .withdrawFunds(await personas.Carol.getAddress(), deposit)
-
- bigNumEquals(0, await aggregator.availableFunds())
- bigNumEquals(
- deposit,
- await link.balanceOf(await personas.Carol.getAddress()),
- )
- })
-
- it('does not let withdrawals happen multiple times', async () => {
- await aggregator
- .connect(personas.Carol)
- .withdrawFunds(await personas.Carol.getAddress(), deposit)
-
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .withdrawFunds(await personas.Carol.getAddress(), deposit),
- 'insufficient reserve funds',
- )
- })
-
- describe('with a number higher than the available LINK balance', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
-
- it('fails', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .withdrawFunds(await personas.Carol.getAddress(), deposit),
- 'insufficient reserve funds',
- )
-
- bigNumEquals(
- deposit.sub(paymentAmount),
- await aggregator.availableFunds(),
- )
- })
- })
-
- describe('with oracles still present', () => {
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Ned, personas.Nelly]
- await addOracles(aggregator, oracles, 1, 1, rrDelay)
-
- bigNumEquals(deposit, await aggregator.availableFunds())
- })
-
- it('does not allow withdrawal with less than 2x rounds of payments', async () => {
- const oracleReserve = paymentAmount
- .mul(oracles.length)
- .mul(reserveRounds)
- const allowed = deposit.sub(oracleReserve)
-
- //one more than the allowed amount cannot be withdrawn
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .withdrawFunds(await personas.Carol.getAddress(), allowed.add(1)),
- 'insufficient reserve funds',
- )
-
- // the allowed amount can be withdrawn
- await aggregator
- .connect(personas.Carol)
- .withdrawFunds(await personas.Carol.getAddress(), allowed)
- })
- })
-
- describe('when called by a non-owner', () => {
- it('fails', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Eddy)
- .withdrawFunds(await personas.Carol.getAddress(), deposit),
- 'Only callable by owner',
- )
-
- bigNumEquals(deposit, await aggregator.availableFunds())
- })
- })
- })
-
- describe('#updateFutureRounds', () => {
- let minSubmissionCount, maxSubmissionCount
- const newPaymentAmount = toWei('2')
- const newMin = 1
- const newMax = 3
- const newDelay = 2
-
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Ned, personas.Nelly]
- minSubmissionCount = oracles.length
- maxSubmissionCount = oracles.length
- await addOracles(
- aggregator,
- oracles,
- minSubmissionCount,
- maxSubmissionCount,
- rrDelay,
- )
-
- bigNumEquals(paymentAmount, await aggregator.paymentAmount())
- assert.equal(minSubmissionCount, await aggregator.minSubmissionCount())
- assert.equal(maxSubmissionCount, await aggregator.maxSubmissionCount())
- })
-
- it('updates the min and max answer counts', async () => {
- await updateFutureRounds(aggregator, {
- payment: newPaymentAmount,
- minAnswers: newMin,
- maxAnswers: newMax,
- restartDelay: newDelay,
- })
-
- bigNumEquals(newPaymentAmount, await aggregator.paymentAmount())
- bigNumEquals(
- BigNumber.from(newMin),
- await aggregator.minSubmissionCount(),
- )
- bigNumEquals(
- BigNumber.from(newMax),
- await aggregator.maxSubmissionCount(),
- )
- bigNumEquals(BigNumber.from(newDelay), await aggregator.restartDelay())
- })
-
- it('emits a log announcing the new round details', async () => {
- await expect(
- updateFutureRounds(aggregator, {
- payment: newPaymentAmount,
- minAnswers: newMin,
- maxAnswers: newMax,
- restartDelay: newDelay,
- timeout: timeout + 1,
- }),
- )
- .to.emit(aggregator, 'RoundDetailsUpdated')
- .withArgs(newPaymentAmount, newMin, newMax, newDelay, timeout + 1)
- })
-
- describe('when it is set to higher than the number or oracles', () => {
- it('reverts', async () => {
- await evmRevert(
- updateFutureRounds(aggregator, {
- maxAnswers: 4,
- }),
- 'max cannot exceed total',
- )
- })
- })
-
- describe('when it sets the min higher than the max', () => {
- it('reverts', async () => {
- await evmRevert(
- updateFutureRounds(aggregator, {
- minAnswers: 3,
- maxAnswers: 2,
- }),
- 'max must equal/exceed min',
- )
- })
- })
-
- describe('when delay equal or greater the oracle count', () => {
- it('reverts', async () => {
- await evmRevert(
- updateFutureRounds(aggregator, {
- restartDelay: 3,
- }),
- 'delay cannot exceed total',
- )
- })
- })
-
- describe('when the payment amount does not cover reserve rounds', () => {
- beforeEach(async () => {})
-
- it('reverts', async () => {
- const most = deposit.div(oracles.length * reserveRounds)
-
- // Relaxed check for the revert message due to a bug in ethers where any error message
- // that starts with insufficient funds will be incorrectly returned as 'insufficient funds for intrinsic transaction cost'
- await updateFutureRounds(aggregator, {
- payment: most.add(1),
- }).then(
- () => {
- // onFulfillment callback
- fail('expected to revert but did not')
- },
- (error: any) => {
- // onRejected callback
- const message =
- error instanceof Object && 'message' in error
- ? error.message
- : JSON.stringify(error)
- assert.isTrue(message.includes('insufficient funds'))
- },
- )
-
- await updateFutureRounds(aggregator, {
- payment: most,
- })
- })
- })
-
- describe('min oracles is set to 0', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator.updateFutureRounds(paymentAmount, 0, 0, rrDelay, timeout),
- 'min must be greater than 0',
- )
- })
- })
-
- describe('when called by anyone but the owner', () => {
- it('reverts', async () => {
- await evmRevert(
- updateFutureRounds(aggregator.connect(personas.Ned)),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('#updateAvailableFunds', () => {
- it('checks the LINK token to see if any additional funds are available', async () => {
- const originalBalance = await aggregator.availableFunds()
-
- await aggregator.updateAvailableFunds()
-
- bigNumEquals(originalBalance, await aggregator.availableFunds())
-
- await link.transfer(aggregator.address, deposit)
- await aggregator.updateAvailableFunds()
-
- const newBalance = await aggregator.availableFunds()
- bigNumEquals(originalBalance.add(deposit), newBalance)
- })
-
- it('removes allocated funds from the available balance', async () => {
- const originalBalance = await aggregator.availableFunds()
-
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- await link.transfer(aggregator.address, deposit)
- await aggregator.updateAvailableFunds()
-
- const expected = originalBalance.add(deposit).sub(paymentAmount)
- const newBalance = await aggregator.availableFunds()
- bigNumEquals(expected, newBalance)
- })
-
- it('emits a log', async () => {
- await link.transfer(aggregator.address, deposit)
-
- const tx = await aggregator.updateAvailableFunds()
- const receipt = await tx.wait()
-
- const reportedBalance = BigNumber.from(receipt.logs?.[0].topics[1] ?? -1)
- bigNumEquals(await aggregator.availableFunds(), reportedBalance)
- })
-
- describe('when the available funds have not changed', () => {
- it('does not emit a log', async () => {
- const tx = await aggregator.updateAvailableFunds()
- const receipt = await tx.wait()
-
- assert.equal(0, receipt.logs?.length)
- })
- })
- })
-
- describe('#withdrawPayment', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], minAns, maxAns, rrDelay)
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
-
- it('transfers LINK to the recipient', async () => {
- const originalBalance = await link.balanceOf(aggregator.address)
- bigNumEquals(0, await link.balanceOf(await personas.Neil.getAddress()))
-
- await aggregator
- .connect(personas.Neil)
- .withdrawPayment(
- await personas.Neil.getAddress(),
- await personas.Neil.getAddress(),
- paymentAmount,
- )
-
- bigNumEquals(
- originalBalance.sub(paymentAmount),
- await link.balanceOf(aggregator.address),
- )
- bigNumEquals(
- paymentAmount,
- await link.balanceOf(await personas.Neil.getAddress()),
- )
- })
-
- it('decrements the allocated funds counter', async () => {
- const originalAllocation = await aggregator.allocatedFunds()
-
- await aggregator
- .connect(personas.Neil)
- .withdrawPayment(
- await personas.Neil.getAddress(),
- await personas.Neil.getAddress(),
- paymentAmount,
- )
-
- bigNumEquals(
- originalAllocation.sub(paymentAmount),
- await aggregator.allocatedFunds(),
- )
- })
-
- describe('when the caller withdraws more than they have', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Neil)
- .withdrawPayment(
- await personas.Neil.getAddress(),
- await personas.Neil.getAddress(),
- paymentAmount.add(BigNumber.from(1)),
- ),
- 'insufficient withdrawable funds',
- )
- })
- })
-
- describe('when the caller is not the admin', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Nelly)
- .withdrawPayment(
- await personas.Neil.getAddress(),
- await personas.Nelly.getAddress(),
- BigNumber.from(1),
- ),
- 'only callable by admin',
- )
- })
- })
- })
-
- describe('#transferAdmin', () => {
- beforeEach(async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [],
- [await personas.Ned.getAddress()],
- [await personas.Neil.getAddress()],
- minAns,
- maxAns,
- rrDelay,
- )
- })
-
- describe('when the admin tries to transfer the admin', () => {
- it('works', async () => {
- await expect(
- aggregator
- .connect(personas.Neil)
- .transferAdmin(
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- ),
- )
- .to.emit(aggregator, 'OracleAdminUpdateRequested')
- .withArgs(
- await personas.Ned.getAddress(),
- await personas.Neil.getAddress(),
- await personas.Nelly.getAddress(),
- )
- assert.equal(
- await personas.Neil.getAddress(),
- await aggregator.getAdmin(await personas.Ned.getAddress()),
- )
- })
- })
-
- describe('when the non-admin owner tries to update the admin', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Carol)
- .transferAdmin(
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- ),
- 'only callable by admin',
- )
- })
- })
-
- describe('when the non-admin oracle tries to update the admin', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Ned)
- .transferAdmin(
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- ),
- 'only callable by admin',
- )
- })
- })
- })
-
- describe('#acceptAdmin', () => {
- beforeEach(async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles(
- [],
- [await personas.Ned.getAddress()],
- [await personas.Neil.getAddress()],
- minAns,
- maxAns,
- rrDelay,
- )
- const tx = await aggregator
- .connect(personas.Neil)
- .transferAdmin(
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- )
- await tx.wait()
- })
-
- describe('when the new admin tries to accept', () => {
- it('works', async () => {
- await expect(
- aggregator
- .connect(personas.Nelly)
- .acceptAdmin(await personas.Ned.getAddress()),
- )
- .to.emit(aggregator, 'OracleAdminUpdated')
- .withArgs(
- await personas.Ned.getAddress(),
- await personas.Nelly.getAddress(),
- )
- assert.equal(
- await personas.Nelly.getAddress(),
- await aggregator.getAdmin(await personas.Ned.getAddress()),
- )
- })
- })
-
- describe('when someone other than the new admin tries to accept', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Ned)
- .acceptAdmin(await personas.Ned.getAddress()),
- 'only callable by pending admin',
- )
- await evmRevert(
- aggregator
- .connect(personas.Neil)
- .acceptAdmin(await personas.Ned.getAddress()),
- 'only callable by pending admin',
- )
- })
- })
- })
-
- describe('#onTokenTransfer', () => {
- it('updates the available balance', async () => {
- const originalBalance = await aggregator.availableFunds()
-
- await aggregator.updateAvailableFunds()
-
- bigNumEquals(originalBalance, await aggregator.availableFunds())
-
- await link.transferAndCall(aggregator.address, deposit, '0x')
-
- const newBalance = await aggregator.availableFunds()
- bigNumEquals(originalBalance.add(deposit), newBalance)
- })
-
- it('reverts given calldata', async () => {
- await evmRevert(
- // error message is not bubbled up by link token
- link.transferAndCall(aggregator.address, deposit, '0x12345678'),
- )
- })
- })
-
- describe('#requestNewRound', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], 1, 1, 0)
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- nextRound = nextRound + 1
-
- await aggregator.setRequesterPermissions(
- await personas.Carol.getAddress(),
- true,
- 0,
- )
- })
-
- it('announces a new round via log event', async () => {
- await expect(aggregator.requestNewRound()).to.emit(aggregator, 'NewRound')
- })
-
- it('returns the new round ID', async () => {
- testHelper = await testHelperFactory.connect(personas.Carol).deploy()
- await aggregator.setRequesterPermissions(testHelper.address, true, 0)
- let roundId = await testHelper.requestedRoundId()
- assert.equal(roundId.toNumber(), 0)
-
- await testHelper.requestNewRound(aggregator.address)
-
- // return value captured by test helper
- roundId = await testHelper.requestedRoundId()
- assert.isAbove(roundId.toNumber(), 0)
- })
-
- describe('when there is a round in progress', () => {
- beforeEach(async () => {
- await aggregator.requestNewRound()
- })
-
- it('reverts', async () => {
- await evmRevert(
- aggregator.requestNewRound(),
- 'prev round must be supersedable',
- )
- })
-
- describe('when that round has timed out', () => {
- beforeEach(async () => {
- await increaseTimeBy(timeout + 1, ethers.provider)
- await mineBlock(ethers.provider)
- })
-
- it('starts a new round', async () => {
- await expect(aggregator.requestNewRound()).to.emit(
- aggregator,
- 'NewRound',
- )
- })
- })
- })
-
- describe('when there is a restart delay set', () => {
- beforeEach(async () => {
- await aggregator.setRequesterPermissions(
- await personas.Eddy.getAddress(),
- true,
- 1,
- )
- })
-
- it('reverts if a round is started before the delay', async () => {
- await aggregator.connect(personas.Eddy).requestNewRound()
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- nextRound = nextRound + 1
-
- // Eddy can't start because of the delay
- await evmRevert(
- aggregator.connect(personas.Eddy).requestNewRound(),
- 'must delay requests',
- )
- // Carol starts a new round instead
- await aggregator.connect(personas.Carol).requestNewRound()
-
- // round completes
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- nextRound = nextRound + 1
-
- // now Eddy can start again
- await aggregator.connect(personas.Eddy).requestNewRound()
- })
- })
-
- describe('when all oracles have been removed and then re-added', () => {
- it('does not get stuck', async () => {
- await aggregator
- .connect(personas.Carol)
- .changeOracles([await personas.Neil.getAddress()], [], [], 0, 0, 0)
-
- // advance a few rounds
- for (let i = 0; i < 7; i++) {
- await aggregator.requestNewRound()
- nextRound = nextRound + 1
- await increaseTimeBy(timeout + 1, ethers.provider)
- await mineBlock(ethers.provider)
- }
-
- await addOracles(aggregator, [personas.Neil], 1, 1, 0)
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- })
- })
- })
-
- describe('#setRequesterPermissions', () => {
- beforeEach(async () => {
- await addOracles(aggregator, [personas.Neil], 1, 1, 0)
-
- await aggregator.connect(personas.Neil).submit(nextRound, answer)
- nextRound = nextRound + 1
- })
-
- describe('when called by the owner', () => {
- it('allows the specified address to start new rounds', async () => {
- await aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- true,
- 0,
- )
-
- await aggregator.connect(personas.Neil).requestNewRound()
- })
-
- it('emits a log announcing the update', async () => {
- await expect(
- aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- true,
- 0,
- ),
- )
- .to.emit(aggregator, 'RequesterPermissionsSet')
- .withArgs(await personas.Neil.getAddress(), true, 0)
- })
-
- describe('when the address is already authorized', () => {
- beforeEach(async () => {
- await aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- true,
- 0,
- )
- })
-
- it('does not emit a log for already authorized accounts', async () => {
- const tx = await aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- true,
- 0,
- )
- const receipt = await tx.wait()
- assert.equal(0, receipt?.logs?.length)
- })
- })
-
- describe('when permission is removed by the owner', () => {
- beforeEach(async () => {
- await aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- true,
- 0,
- )
- })
-
- it('does not allow the specified address to start new rounds', async () => {
- await aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- false,
- 0,
- )
-
- await evmRevert(
- aggregator.connect(personas.Neil).requestNewRound(),
- 'not authorized requester',
- )
- })
-
- it('emits a log announcing the update', async () => {
- await expect(
- aggregator.setRequesterPermissions(
- await personas.Neil.getAddress(),
- false,
- 0,
- ),
- )
- .to.emit(aggregator, 'RequesterPermissionsSet')
- .withArgs(await personas.Neil.getAddress(), false, 0)
- })
-
- it('does not emit a log for accounts without authorization', async () => {
- const tx = await aggregator.setRequesterPermissions(
- await personas.Ned.getAddress(),
- false,
- 0,
- )
- const receipt = await tx.wait()
- assert.equal(0, receipt?.logs?.length)
- })
- })
- })
-
- describe('when called by a stranger', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator
- .connect(personas.Neil)
- .setRequesterPermissions(await personas.Neil.getAddress(), true, 0),
- 'Only callable by owner',
- )
-
- await evmRevert(
- aggregator.connect(personas.Neil).requestNewRound(),
- 'not authorized requester',
- )
- })
- })
- })
-
- describe('#oracleRoundState', () => {
- describe('when round ID 0 is passed in', () => {
- const previousSubmission = 42
- let baseFunds: any
- let minAnswers: number
- let maxAnswers: number
- let submitters: Signer[]
-
- beforeEach(async () => {
- oracles = [
- personas.Neil,
- personas.Ned,
- personas.Nelly,
- personas.Nancy,
- personas.Norbert,
- ]
- minAnswers = 3
- maxAnswers = 4
-
- await addOracles(aggregator, oracles, minAnswers, maxAnswers, rrDelay)
- submitters = [
- personas.Nelly,
- personas.Ned,
- personas.Neil,
- personas.Nancy,
- ]
- await advanceRound(aggregator, submitters, previousSubmission)
- baseFunds = BigNumber.from(deposit).sub(
- paymentAmount.mul(submitters.length),
- )
- startingState = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
- })
-
- it('returns all of the important round information', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 2,
- latestSubmission: previousSubmission,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds,
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- it('reverts if called by a contract', async () => {
- testHelper = await testHelperFactory.connect(personas.Carol).deploy()
- await evmRevert(
- testHelper.readOracleRoundState(
- aggregator.address,
- await personas.Neil.getAddress(),
- ),
- 'off-chain reading only',
- )
- })
-
- describe('when the restart delay is not enforced', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, {
- minAnswers,
- maxAnswers,
- restartDelay: 0,
- })
- })
-
- describe('< min submissions and oracle not included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [personas.Neil])
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 2,
- latestSubmission: previousSubmission,
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: baseFunds.sub(paymentAmount),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('< min submissions and oracle included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [personas.Nelly])
- })
-
- it('is not eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 2,
- latestSubmission: answer,
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: baseFunds.sub(paymentAmount),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- describe('and timed out', () => {
- beforeEach(async () => {
- await increaseTimeBy(timeout + 1, ethers.provider)
- await mineBlock(ethers.provider)
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- describe('>= min submissions and oracle not included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [
- personas.Neil,
- personas.Nancy,
- personas.Ned,
- ])
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 2,
- latestSubmission: previousSubmission,
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: baseFunds.sub(paymentAmount.mul(3)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('>= min submissions and oracle included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [
- personas.Neil,
- personas.Nelly,
- personas.Ned,
- ])
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(3)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- describe('and timed out', () => {
- beforeEach(async () => {
- await increaseTimeBy(timeout + 1, ethers.provider)
- await mineBlock(ethers.provider)
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(3)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- describe('max submissions and oracle not included', () => {
- beforeEach(async () => {
- submitters = [
- personas.Neil,
- personas.Ned,
- personas.Nancy,
- personas.Norbert,
- ]
- assert.equal(
- submitters.length,
- maxAnswers,
- 'precondition, please update submitters if maxAnswers changes',
- )
- await advanceRound(aggregator, submitters)
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 3,
- latestSubmission: previousSubmission,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(4)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('max submissions and oracle included', () => {
- beforeEach(async () => {
- submitters = [
- personas.Neil,
- personas.Ned,
- personas.Nelly,
- personas.Nancy,
- ]
- assert.equal(
- submitters.length,
- maxAnswers,
- 'precondition, please update submitters if maxAnswers changes',
- )
- await advanceRound(aggregator, submitters)
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(4)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- describe('when the restart delay is enforced', () => {
- beforeEach(async () => {
- await updateFutureRounds(aggregator, {
- minAnswers,
- maxAnswers,
- restartDelay: maxAnswers - 1,
- })
- })
-
- describe('< min submissions and oracle not included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [personas.Neil, personas.Ned])
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 2,
- latestSubmission: previousSubmission,
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: baseFunds.sub(paymentAmount.mul(2)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('< min submissions and oracle included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [personas.Neil, personas.Nelly])
- })
-
- it('is not eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 2,
- latestSubmission: answer,
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: baseFunds.sub(paymentAmount.mul(2)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- describe('and timed out', () => {
- beforeEach(async () => {
- await increaseTimeBy(timeout + 1, ethers.provider)
- await mineBlock(ethers.provider)
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(2)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- describe('>= min submissions and oracle not included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [
- personas.Neil,
- personas.Ned,
- personas.Nancy,
- ])
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 2,
- latestSubmission: previousSubmission,
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: baseFunds.sub(paymentAmount.mul(3)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('>= min submissions and oracle included', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, [
- personas.Neil,
- personas.Ned,
- personas.Nelly,
- ])
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(3)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- describe('and timed out', () => {
- beforeEach(async () => {
- await increaseTimeBy(timeout + 1, ethers.provider)
- await mineBlock(ethers.provider)
- })
-
- it('is eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false, // restart delay enforced
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(3)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- describe('max submissions and oracle not included', () => {
- beforeEach(async () => {
- submitters = [
- personas.Neil,
- personas.Ned,
- personas.Nancy,
- personas.Norbert,
- ]
- assert.equal(
- submitters.length,
- maxAnswers,
- 'precondition, please update submitters if maxAnswers changes',
- )
- await advanceRound(aggregator, submitters, answer)
- })
-
- it('is not eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 3,
- latestSubmission: previousSubmission,
- startedAt: ShouldNotBeSet,
- timeout: 0, // details have been deleted
- availableFunds: baseFunds.sub(paymentAmount.mul(4)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('max submissions and oracle included', () => {
- beforeEach(async () => {
- submitters = [
- personas.Neil,
- personas.Ned,
- personas.Nelly,
- personas.Nancy,
- ]
- assert.equal(
- submitters.length,
- maxAnswers,
- 'precondition, please update submitters if maxAnswers changes',
- )
- await advanceRound(aggregator, submitters, answer)
- })
-
- it('is not eligible to submit', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 3,
- latestSubmission: answer,
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: baseFunds.sub(paymentAmount.mul(4)),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
- })
-
- describe('when non-zero round ID 0 is passed in', () => {
- const answers = [0, 42, 47, 52, 57]
- let currentFunds: any
-
- beforeEach(async () => {
- oracles = [personas.Neil, personas.Ned, personas.Nelly]
-
- await addOracles(aggregator, oracles, 2, 3, rrDelay)
- startingState = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 0,
- )
- await advanceRound(aggregator, oracles, answers[1])
- await advanceRound(
- aggregator,
- [personas.Neil, personas.Ned],
- answers[2],
- )
- await advanceRound(aggregator, oracles, answers[3])
- await advanceRound(aggregator, [personas.Neil], answers[4])
- const submissionsSoFar = 9
- currentFunds = BigNumber.from(deposit).sub(
- paymentAmount.mul(submissionsSoFar),
- )
- })
-
- it('returns info about previous rounds', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 1,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 1,
- latestSubmission: answers[3],
- startedAt: ShouldBeSet,
- timeout: 0,
- availableFunds: currentFunds,
- oracleCount: oracles.length,
- paymentAmount: 0,
- })
- })
-
- it('returns info about previous rounds that were not submitted to', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 2,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 2,
- latestSubmission: answers[3],
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: currentFunds,
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- describe('for the current round', () => {
- describe('which has not been submitted to', () => {
- it("returns info about the current round that hasn't been submitted to", async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 4,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 4,
- latestSubmission: answers[3],
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: currentFunds,
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- it('returns info about the subsequent round', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 5,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 5,
- latestSubmission: answers[3],
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: currentFunds,
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
-
- describe('which has been submitted to', () => {
- beforeEach(async () => {
- await aggregator.connect(personas.Nelly).submit(4, answers[4])
- })
-
- it("returns info about the current round that hasn't been submitted to", async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 4,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 4,
- latestSubmission: answers[4],
- startedAt: ShouldBeSet,
- timeout,
- availableFunds: currentFunds.sub(paymentAmount),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
-
- it('returns info about the subsequent round', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 5,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: true,
- roundId: 5,
- latestSubmission: answers[4],
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: currentFunds.sub(paymentAmount),
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- it('returns speculative info about future rounds', async () => {
- const state = await aggregator.oracleRoundState(
- await personas.Nelly.getAddress(),
- 6,
- )
-
- await checkOracleRoundState(state, {
- eligibleToSubmit: false,
- roundId: 6,
- latestSubmission: answers[3],
- startedAt: ShouldNotBeSet,
- timeout: 0,
- availableFunds: currentFunds,
- oracleCount: oracles.length,
- paymentAmount,
- })
- })
- })
- })
-
- describe('#getRoundData', () => {
- let latestRoundId: any
- beforeEach(async () => {
- oracles = [personas.Nelly]
- const minMax = oracles.length
- await addOracles(aggregator, oracles, minMax, minMax, rrDelay)
- await advanceRound(aggregator, oracles, answer)
- latestRoundId = await aggregator.latestRound()
- })
-
- it('returns the relevant round information', async () => {
- const round = await aggregator.getRoundData(latestRoundId)
- bigNumEquals(latestRoundId, round.roundId)
- bigNumEquals(answer, round.answer)
- const nowSeconds = new Date().valueOf() / 1000
- assert.isAbove(round.updatedAt.toNumber(), nowSeconds - 120)
- bigNumEquals(round.updatedAt, round.startedAt)
- bigNumEquals(latestRoundId, round.answeredInRound)
- })
-
- it('reverts if a round is not present', async () => {
- await evmRevert(
- aggregator.getRoundData(latestRoundId.add(1)),
- 'No data present',
- )
- })
-
- it('reverts if a round ID is too big', async () => {
- const overflowedId = BigNumber.from(2).pow(32).add(1)
-
- await evmRevert(aggregator.getRoundData(overflowedId), 'No data present')
- })
- })
-
- describe('#latestRoundData', () => {
- beforeEach(async () => {
- oracles = [personas.Nelly]
- const minMax = oracles.length
- await addOracles(aggregator, oracles, minMax, minMax, rrDelay)
- })
-
- describe('when an answer has already been received', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, oracles, answer)
- })
-
- it('returns the relevant round info without reverting', async () => {
- const round = await aggregator.latestRoundData()
- const latestRoundId = await aggregator.latestRound()
-
- bigNumEquals(latestRoundId, round.roundId)
- bigNumEquals(answer, round.answer)
- const nowSeconds = new Date().valueOf() / 1000
- assert.isAbove(round.updatedAt.toNumber(), nowSeconds - 120)
- bigNumEquals(round.updatedAt, round.startedAt)
- bigNumEquals(latestRoundId, round.answeredInRound)
- })
- })
-
- it('reverts if a round is not present', async () => {
- await evmRevert(aggregator.latestRoundData(), 'No data present')
- })
- })
-
- describe('#latestAnswer', () => {
- beforeEach(async () => {
- oracles = [personas.Nelly]
- const minMax = oracles.length
- await addOracles(aggregator, oracles, minMax, minMax, rrDelay)
- })
-
- describe('when an answer has already been received', () => {
- beforeEach(async () => {
- await advanceRound(aggregator, oracles, answer)
- })
-
- it('returns the latest answer without reverting', async () => {
- bigNumEquals(answer, await aggregator.latestAnswer())
- })
- })
-
- it('returns zero', async () => {
- bigNumEquals(0, await aggregator.latestAnswer())
- })
- })
-
- describe('#setValidator', () => {
- beforeEach(async () => {
- validator = await validatorMockFactory.connect(personas.Carol).deploy()
- assert.equal(emptyAddress, await aggregator.validator())
- })
-
- it('emits a log event showing the validator was changed', async () => {
- await expect(
- aggregator.connect(personas.Carol).setValidator(validator.address),
- )
- .to.emit(aggregator, 'ValidatorUpdated')
- .withArgs(emptyAddress, validator.address)
- assert.equal(validator.address, await aggregator.validator())
-
- await expect(
- aggregator.connect(personas.Carol).setValidator(validator.address),
- ).to.not.emit(aggregator, 'ValidatorUpdated')
- assert.equal(validator.address, await aggregator.validator())
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- aggregator.connect(personas.Neil).setValidator(validator.address),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('integrating with historic deviation checker', () => {
- let validator: Contract
- let flags: Contract
- let ac: Contract
- const flaggingThreshold = 1000 // 1%
-
- beforeEach(async () => {
- ac = await acFactory.connect(personas.Carol).deploy()
- flags = await flagsFactory.connect(personas.Carol).deploy(ac.address)
- validator = await validatorFactory
- .connect(personas.Carol)
- .deploy(flags.address, flaggingThreshold)
- await ac.connect(personas.Carol).addAccess(validator.address)
-
- await aggregator.connect(personas.Carol).setValidator(validator.address)
-
- oracles = [personas.Nelly]
- const minMax = oracles.length
- await addOracles(aggregator, oracles, minMax, minMax, rrDelay)
- })
-
- it('raises a flag on with high enough deviation', async () => {
- await aggregator.connect(personas.Nelly).submit(nextRound, 100)
- nextRound++
-
- await expect(aggregator.connect(personas.Nelly).submit(nextRound, 102))
- .to.emit(flags, 'FlagRaised')
- .withArgs(aggregator.address)
- })
-
- it('does not raise a flag with low enough deviation', async () => {
- await aggregator.connect(personas.Nelly).submit(nextRound, 100)
- nextRound++
-
- await expect(
- aggregator.connect(personas.Nelly).submit(nextRound, 101),
- ).to.not.emit(flags, 'FlagRaised')
- })
- })
-})
diff --git a/contracts/test/v0.6/Median.test.ts b/contracts/test/v0.6/Median.test.ts
deleted file mode 100644
index 8aea4722b6..0000000000
--- a/contracts/test/v0.6/Median.test.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert } from 'chai'
-import { Signer, Contract, ContractFactory, BigNumber } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { bigNumEquals } from '../test-helpers/matchers'
-
-let defaultAccount: Signer
-let medianTestHelperFactory: ContractFactory
-before(async () => {
- const personas: Personas = (await getUsers()).personas
- defaultAccount = personas.Default
- medianTestHelperFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/MedianTestHelper.sol:MedianTestHelper',
- defaultAccount,
- )
-})
-
-describe('Median', () => {
- let median: Contract
-
- beforeEach(async () => {
- median = await medianTestHelperFactory.connect(defaultAccount).deploy()
- })
-
- describe('testing various lists', () => {
- const tests = [
- {
- name: 'ordered ascending',
- responses: [0, 1, 2, 3, 4, 5, 6, 7],
- want: 3,
- },
- {
- name: 'ordered descending',
- responses: [7, 6, 5, 4, 3, 2, 1, 0],
- want: 3,
- },
- {
- name: 'unordered length 1',
- responses: [20],
- want: 20,
- },
- {
- name: 'unordered length 2',
- responses: [20, 0],
- want: 10,
- },
- {
- name: 'unordered length 3',
- responses: [20, 0, 16],
- want: 16,
- },
- {
- name: 'unordered length 4',
- responses: [20, 0, 15, 16],
- want: 15,
- },
- {
- name: 'unordered length 7',
- responses: [1001, 1, 101, 10, 11, 0, 111],
- want: 11,
- },
- {
- name: 'unordered length 9',
- responses: [8, 8, 4, 5, 5, 7, 9, 5, 9],
- want: 7,
- },
- {
- name: 'unordered long',
- responses: [33, 44, 89, 101, 67, 7, 23, 55, 88, 324, 0, 88],
- want: 61, // 67 + 55 / 2
- },
- {
- name: 'unordered longer',
- responses: [
- 333121, 323453, 337654, 345363, 345363, 333456, 335477, 333323,
- 332352, 354648, 983260, 333856, 335468, 376987, 333253, 388867,
- 337879, 333324, 338678,
- ],
- want: 335477,
- },
- {
- name: 'overflowing numbers',
- responses: [
- BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819967',
- ),
- BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819967',
- ),
- ],
- want: BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819967',
- ),
- },
- {
- name: 'overflowing numbers',
- responses: [
- BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819967',
- ),
- BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819966',
- ),
- ],
- want: BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819966',
- ),
- },
- {
- name: 'really long',
- responses: [
- 56, 2, 31, 33, 55, 38, 35, 12, 41, 47, 21, 22, 40, 39, 10, 32, 49, 3,
- 54, 45, 53, 14, 20, 59, 1, 30, 24, 6, 5, 37, 58, 51, 46, 17, 29, 7,
- 27, 9, 43, 8, 34, 42, 28, 23, 57, 0, 11, 48, 52, 50, 15, 16, 26, 25,
- 4, 36, 19, 44, 18, 13,
- ],
- want: 29,
- },
- ]
-
- for (const test of tests) {
- it(test.name, async () => {
- bigNumEquals(test.want, await median.publicGet(test.responses))
- })
- }
- })
-
- // long running (minutes) exhaustive test.
- // skipped because very slow, but useful for thorough validation
- xit('permutations', async () => {
- const permutations = (list: number[]) => {
- const result: number[][] = []
- const used: number[] = []
-
- const permute = (unused: number[]) => {
- if (unused.length == 0) {
- result.push([...used])
- return
- }
-
- for (let i = 0; i < unused.length; i++) {
- const elem = unused.splice(i, 1)[0]
- used.push(elem)
- permute(unused)
- unused.splice(i, 0, elem)
- used.pop()
- }
- }
-
- permute(list)
- return result
- }
-
- {
- const list = [0, 2, 5, 7, 8, 10]
- for (const permuted of permutations(list)) {
- for (let i = 0; i < list.length; i++) {
- for (let j = 0; j < list.length; j++) {
- if (i < j) {
- const foo = await median.publicQuickselectTwo(permuted, i, j)
- bigNumEquals(list[i], foo[0])
- bigNumEquals(list[j], foo[1])
- }
- }
- }
- }
- }
-
- {
- const list = [0, 1, 1, 1, 2]
- for (const permuted of permutations(list)) {
- for (let i = 0; i < list.length; i++) {
- for (let j = 0; j < list.length; j++) {
- if (i < j) {
- const foo = await median.publicQuickselectTwo(permuted, i, j)
- bigNumEquals(list[i], foo[0])
- bigNumEquals(list[j], foo[1])
- }
- }
- }
- }
- }
- })
-
- // Checks the validity of the sorting network in `shortList`
- describe('validate sorting network', () => {
- const net = [
- [0, 1],
- [2, 3],
- [4, 5],
- [0, 2],
- [1, 3],
- [4, 6],
- [1, 2],
- [5, 6],
- [0, 4],
- [1, 5],
- [2, 6],
- [1, 4],
- [3, 6],
- [2, 4],
- [3, 5],
- [3, 4],
- ]
-
- // See: https://en.wikipedia.org/wiki/Sorting_network#Zero-one_principle
- xit('zero-one principle', async () => {
- const sortWithNet = (list: number[]) => {
- for (const [i, j] of net) {
- if (list[i] > list[j]) {
- ;[list[i], list[j]] = [list[j], list[i]]
- }
- }
- }
-
- for (let n = 0; n < (1 << 7) - 1; n++) {
- const list = [
- (n >> 6) & 1,
- (n >> 5) & 1,
- (n >> 4) & 1,
- (n >> 3) & 1,
- (n >> 2) & 1,
- (n >> 1) & 1,
- (n >> 0) & 1,
- ]
- const sum = list.reduce((a, b) => a + b, 0)
- sortWithNet(list)
- const sortedSum = list.reduce((a, b) => a + b, 0)
- assert.equal(sortedSum, sum, 'Number of zeros and ones changed')
- list.reduce((switched, i) => {
- assert.isTrue(!switched || i != 0, 'error at n=' + n.toString())
- return i != 0
- }, false)
- }
- })
- })
-})
diff --git a/contracts/test/v0.6/Owned.test.ts b/contracts/test/v0.6/Owned.test.ts
deleted file mode 100644
index f522b9c44c..0000000000
--- a/contracts/test/v0.6/Owned.test.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { Signer, Contract, ContractFactory } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-
-let personas: Personas
-
-let owner: Signer
-let nonOwner: Signer
-let newOwner: Signer
-
-let ownedFactory: ContractFactory
-let owned: Contract
-
-before(async () => {
- personas = (await getUsers()).personas
- owner = personas.Carol
- nonOwner = personas.Neil
- newOwner = personas.Ned
- ownedFactory = await ethers.getContractFactory(
- 'src/v0.6/Owned.sol:Owned',
- owner,
- )
-})
-
-describe('Owned', () => {
- beforeEach(async () => {
- owned = await ownedFactory.connect(owner).deploy()
- })
-
- it('has a limited public interface [ @skip-coverage ]', async () => {
- publicAbi(owned, ['acceptOwnership', 'owner', 'transferOwnership'])
- })
-
- describe('#constructor', () => {
- it('assigns ownership to the deployer', async () => {
- const [actual, expected] = await Promise.all([
- owner.getAddress(),
- owned.owner(),
- ])
-
- assert.equal(actual, expected)
- })
- })
-
- describe('#transferOwnership', () => {
- describe('when called by an owner', () => {
- it('emits a log', async () => {
- await expect(
- owned.connect(owner).transferOwnership(await newOwner.getAddress()),
- )
- .to.emit(owned, 'OwnershipTransferRequested')
- .withArgs(await owner.getAddress(), await newOwner.getAddress())
- })
- })
- })
-
- describe('when called by anyone but the owner', () => {
- it('reverts', async () =>
- await expect(
- owned.connect(nonOwner).transferOwnership(await newOwner.getAddress()),
- ).to.be.reverted)
- })
-
- describe('#acceptOwnership', () => {
- describe('after #transferOwnership has been called', () => {
- beforeEach(async () => {
- await owned
- .connect(owner)
- .transferOwnership(await newOwner.getAddress())
- })
-
- it('allows the recipient to call it', async () => {
- await expect(owned.connect(newOwner).acceptOwnership())
- .to.emit(owned, 'OwnershipTransferred')
- .withArgs(await owner.getAddress(), await newOwner.getAddress())
- })
-
- it('does not allow a non-recipient to call it', async () =>
- await expect(owned.connect(nonOwner).acceptOwnership()).to.be.reverted)
- })
- })
-})
diff --git a/contracts/test/v0.6/SignedSafeMath.test.ts b/contracts/test/v0.6/SignedSafeMath.test.ts
deleted file mode 100644
index e942f64d6b..0000000000
--- a/contracts/test/v0.6/SignedSafeMath.test.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-import { ethers } from 'hardhat'
-import { expect } from 'chai'
-import { Signer, Contract, ContractFactory, BigNumber } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { bigNumEquals } from '../test-helpers/matchers'
-
-let defaultAccount: Signer
-let concreteSignedSafeMathFactory: ContractFactory
-
-before(async () => {
- const personas: Personas = (await getUsers()).personas
- defaultAccount = personas.Default
- concreteSignedSafeMathFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/ConcreteSignedSafeMath.sol:ConcreteSignedSafeMath',
- defaultAccount,
- )
-})
-
-describe('SignedSafeMath', () => {
- // a version of the adder contract where we make all ABI exposed functions constant
- // TODO: submit upstream PR to support constant contract type generation
- let adder: Contract
- let response: BigNumber
-
- const INT256_MAX = BigNumber.from(
- '57896044618658097711785492504343953926634992332820282019728792003956564819967',
- )
- const INT256_MIN = BigNumber.from(
- '-57896044618658097711785492504343953926634992332820282019728792003956564819968',
- )
-
- beforeEach(async () => {
- adder = await concreteSignedSafeMathFactory.connect(defaultAccount).deploy()
- })
-
- describe('#add', () => {
- describe('given a positive and a positive', () => {
- it('works', async () => {
- response = await adder.testAdd(1, 2)
- bigNumEquals(3, response)
- })
-
- it('works with zero', async () => {
- response = await adder.testAdd(INT256_MAX, 0)
- bigNumEquals(INT256_MAX, response)
- })
-
- describe('when both are large enough to overflow', () => {
- it('throws', async () => {
- await expect(adder.testAdd(INT256_MAX, 1)).to.be.revertedWith(
- 'SignedSafeMath: addition overflow',
- )
- })
- })
- })
-
- describe('given a negative and a negative', () => {
- it('works', async () => {
- response = await adder.testAdd(-1, -2)
- bigNumEquals(-3, response)
- })
-
- it('works with zero', async () => {
- response = await adder.testAdd(INT256_MIN, 0)
- bigNumEquals(INT256_MIN, response)
- })
-
- describe('when both are large enough to overflow', () => {
- it('throws', async () => {
- await expect(adder.testAdd(INT256_MIN, -1)).to.be.revertedWith(
- 'SignedSafeMath: addition overflow',
- )
- })
- })
- })
-
- describe('given a positive and a negative', () => {
- it('works', async () => {
- response = await adder.testAdd(1, -2)
- bigNumEquals(-1, response)
- })
- })
-
- describe('given a negative and a positive', () => {
- it('works', async () => {
- response = await adder.testAdd(-1, 2)
- bigNumEquals(1, response)
- })
- })
- })
-
- describe('#avg', () => {
- describe('given a positive and a positive', () => {
- it('works', async () => {
- response = await adder.testAvg(2, 4)
- bigNumEquals(3, response)
- })
-
- it('works with zero', async () => {
- response = await adder.testAvg(0, 4)
- bigNumEquals(2, response)
- response = await adder.testAvg(4, 0)
- bigNumEquals(2, response)
- })
-
- it('works with large numbers', async () => {
- response = await adder.testAvg(INT256_MAX, INT256_MAX)
- bigNumEquals(INT256_MAX, response)
- })
-
- it('rounds towards zero', async () => {
- response = await adder.testAvg(1, 2)
- bigNumEquals(1, response)
- })
- })
-
- describe('given a negative and a negative', () => {
- it('works', async () => {
- response = await adder.testAvg(-2, -4)
- bigNumEquals(-3, response)
- })
-
- it('works with zero', async () => {
- response = await adder.testAvg(0, -4)
- bigNumEquals(-2, response)
- response = await adder.testAvg(-4, 0)
- bigNumEquals(-2, response)
- })
-
- it('works with large numbers', async () => {
- response = await adder.testAvg(INT256_MIN, INT256_MIN)
- bigNumEquals(INT256_MIN, response)
- })
-
- it('rounds towards zero', async () => {
- response = await adder.testAvg(-1, -2)
- bigNumEquals(-1, response)
- })
- })
-
- describe('given a positive and a negative', () => {
- it('works', async () => {
- response = await adder.testAvg(2, -4)
- bigNumEquals(-1, response)
- response = await adder.testAvg(4, -2)
- bigNumEquals(1, response)
- })
-
- it('works with large numbers', async () => {
- response = await adder.testAvg(INT256_MAX, -2)
- bigNumEquals(INT256_MAX.sub(2).div(2), response)
- response = await adder.testAvg(INT256_MAX, INT256_MIN)
- bigNumEquals(0, response)
- })
-
- it('rounds towards zero', async () => {
- response = await adder.testAvg(1, -4)
- bigNumEquals(-1, response)
- response = await adder.testAvg(4, -1)
- bigNumEquals(1, response)
- })
- })
-
- describe('given a negative and a positive', () => {
- it('works', async () => {
- response = await adder.testAvg(-2, 4)
- bigNumEquals(1, response)
- response = await adder.testAvg(-4, 2)
- bigNumEquals(-1, response)
- })
-
- it('works with large numbers', async () => {
- response = await adder.testAvg(INT256_MIN, 2)
- bigNumEquals(INT256_MIN.add(2).div(2), response)
- response = await adder.testAvg(INT256_MIN, INT256_MAX)
- bigNumEquals(0, response)
- })
-
- it('rounds towards zero', async () => {
- response = await adder.testAvg(-1, 4)
- bigNumEquals(1, response)
- response = await adder.testAvg(-4, 1)
- bigNumEquals(-1, response)
- })
- })
- })
-})
diff --git a/contracts/test/v0.6/SimpleReadAccessController.test.ts b/contracts/test/v0.6/SimpleReadAccessController.test.ts
deleted file mode 100644
index 7b76bc38ca..0000000000
--- a/contracts/test/v0.6/SimpleReadAccessController.test.ts
+++ /dev/null
@@ -1,250 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { Contract, ContractFactory, Transaction } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-
-let personas: Personas
-
-let controllerFactory: ContractFactory
-let controller: Contract
-
-before(async () => {
- personas = (await getUsers()).personas
- controllerFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleReadAccessController.sol:SimpleReadAccessController',
- personas.Carol,
- )
-})
-
-describe('SimpleReadAccessController', () => {
- beforeEach(async () => {
- controller = await controllerFactory.connect(personas.Carol).deploy()
- })
-
- it('has a limited public interface [ @skip-coverage ]', async () => {
- publicAbi(controller, [
- 'hasAccess',
- 'addAccess',
- 'disableAccessCheck',
- 'enableAccessCheck',
- 'removeAccess',
- 'checkEnabled',
- // Owned
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#constructor', () => {
- it('defaults checkEnabled to true', async () => {
- assert(await controller.checkEnabled())
- })
- })
-
- describe('#hasAccess', () => {
- it('allows unauthorized calls originating from the same account', async () => {
- assert.isTrue(
- await controller
- .connect(personas.Eddy)
- .hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('blocks unauthorized calls originating from different accounts', async () => {
- assert.isFalse(
- await controller
- .connect(personas.Carol)
- .hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- assert.isFalse(
- await controller
- .connect(personas.Eddy)
- .hasAccess(await personas.Carol.getAddress(), '0x00'),
- )
- })
- })
-
- describe('#addAccess', () => {
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller
- .connect(personas.Eddy)
- .addAccess(await personas.Eddy.getAddress()),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- assert.isFalse(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- tx = await controller.addAccess(await personas.Eddy.getAddress())
- })
-
- it('adds the address to the controller', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- await expect(tx)
- .to.emit(controller, 'AddedAccess')
- .withArgs(await personas.Eddy.getAddress())
- })
-
- describe('when called twice', () => {
- it('does not emit a log', async () => {
- const tx2 = await controller.addAccess(
- await personas.Eddy.getAddress(),
- )
- const receipt = await tx2.wait()
- assert.equal(receipt.events?.length, 0)
- })
- })
- })
- })
-
- describe('#removeAccess', () => {
- beforeEach(async () => {
- await controller.addAccess(await personas.Eddy.getAddress())
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller
- .connect(personas.Eddy)
- .removeAccess(await personas.Eddy.getAddress()),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- tx = await controller.removeAccess(await personas.Eddy.getAddress())
- })
-
- it('removes the address from the controller', async () => {
- assert.isFalse(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- await expect(tx)
- .to.emit(controller, 'RemovedAccess')
- .withArgs(await personas.Eddy.getAddress())
- })
-
- describe('when called twice', () => {
- it('does not emit a log', async () => {
- const tx2 = await controller.removeAccess(
- await personas.Eddy.getAddress(),
- )
- const receipt = await tx2.wait()
- assert.equal(receipt.events?.length, 0)
- })
- })
- })
- })
-
- describe('#disableAccessCheck', () => {
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller.connect(personas.Eddy).disableAccessCheck(),
- ).to.be.revertedWith('Only callable by owner')
- assert.isTrue(await controller.checkEnabled())
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- await controller.addAccess(await personas.Eddy.getAddress())
- tx = await controller.disableAccessCheck()
- })
-
- it('sets checkEnabled to false', async () => {
- assert.isFalse(await controller.checkEnabled())
- })
-
- it('allows users with access', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('allows users without access', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Ned.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- await expect(tx).to.emit(controller, 'CheckAccessDisabled')
- })
-
- describe('when called twice', () => {
- it('does not emit a log', async () => {
- const tx2 = await controller.disableAccessCheck()
- const receipt = await tx2.wait()
- assert.equal(receipt.events?.length, 0)
- })
- })
- })
- })
-
- describe('#enableAccessCheck', () => {
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller.connect(personas.Eddy).enableAccessCheck(),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- await controller.disableAccessCheck()
- await controller.addAccess(await personas.Eddy.getAddress())
- tx = await controller.enableAccessCheck()
- })
-
- it('allows users with access', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('does not allow users without access', async () => {
- assert.isFalse(
- await controller.hasAccess(await personas.Ned.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- expect(tx).to.emit(controller, 'CheckAccessEnabled')
- })
-
- describe('when called twice', () => {
- it('does not emit a log', async () => {
- const tx2 = await controller.enableAccessCheck()
- const receipt = await tx2.wait()
- assert.equal(receipt.events?.length, 0)
- })
- })
- })
- })
-})
diff --git a/contracts/test/v0.6/SimpleWriteAccessController.test.ts b/contracts/test/v0.6/SimpleWriteAccessController.test.ts
deleted file mode 100644
index ae6c1691f9..0000000000
--- a/contracts/test/v0.6/SimpleWriteAccessController.test.ts
+++ /dev/null
@@ -1,214 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { Contract, ContractFactory, Transaction } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-
-let personas: Personas
-
-let controllerFactory: ContractFactory
-let controller: Contract
-
-before(async () => {
- personas = (await getUsers()).personas
- controllerFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleWriteAccessController.sol:SimpleWriteAccessController',
- personas.Carol,
- )
-})
-
-describe('SimpleWriteAccessController', () => {
- beforeEach(async () => {
- controller = await controllerFactory.connect(personas.Carol).deploy()
- })
-
- it('has a limited public interface [ @skip-coverage ]', async () => {
- publicAbi(controller, [
- 'hasAccess',
- 'addAccess',
- 'disableAccessCheck',
- 'enableAccessCheck',
- 'removeAccess',
- 'checkEnabled',
- // Owned
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#constructor', () => {
- it('defaults checkEnabled to true', async () => {
- assert(await controller.checkEnabled())
- })
- })
-
- describe('#hasAccess', () => {
- it('allows unauthorized calls originating from the same account', async () => {
- assert.isFalse(
- await controller
- .connect(personas.Eddy)
- .hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('blocks unauthorized calls originating from different accounts', async () => {
- assert.isFalse(
- await controller
- .connect(personas.Carol)
- .hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- assert.isFalse(
- await controller
- .connect(personas.Eddy)
- .hasAccess(await personas.Carol.getAddress(), '0x00'),
- )
- })
- })
-
- describe('#addAccess', () => {
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller
- .connect(personas.Eddy)
- .addAccess(await personas.Eddy.getAddress()),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- assert.isFalse(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- tx = await controller.addAccess(await personas.Eddy.getAddress())
- })
-
- it('adds the address to the controller', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- expect(tx)
- .to.emit(controller, 'AddedAccess')
- .withArgs(await personas.Eddy.getAddress())
- })
- })
- })
-
- describe('#removeAccess', () => {
- beforeEach(async () => {
- await controller.addAccess(await personas.Eddy.getAddress())
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller
- .connect(personas.Eddy)
- .removeAccess(await personas.Eddy.getAddress()),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- tx = await controller.removeAccess(await personas.Eddy.getAddress())
- })
-
- it('removes the address from the controller', async () => {
- assert.isFalse(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- expect(tx)
- .to.emit(controller, 'RemovedAccess')
- .withArgs(await personas.Eddy.getAddress())
- })
- })
- })
-
- describe('#disableAccessCheck', () => {
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller.connect(personas.Eddy).disableAccessCheck(),
- ).to.be.revertedWith('Only callable by owner')
- assert.isTrue(await controller.checkEnabled())
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- await controller.addAccess(await personas.Eddy.getAddress())
- tx = await controller.disableAccessCheck()
- })
-
- it('sets checkEnabled to false', async () => {
- assert.isFalse(await controller.checkEnabled())
- })
-
- it('allows users with access', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('allows users without access', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Ned.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- await expect(tx).to.emit(controller, 'CheckAccessDisabled')
- })
- })
- })
-
- describe('#enableAccessCheck', () => {
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await expect(
- controller.connect(personas.Eddy).enableAccessCheck(),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('when called by the owner', () => {
- let tx: Transaction
- beforeEach(async () => {
- await controller.disableAccessCheck()
- await controller.addAccess(await personas.Eddy.getAddress())
- tx = await controller.enableAccessCheck()
- })
-
- it('allows users with access', async () => {
- assert.isTrue(
- await controller.hasAccess(await personas.Eddy.getAddress(), '0x00'),
- )
- })
-
- it('does not allow users without access', async () => {
- assert.isFalse(
- await controller.hasAccess(await personas.Ned.getAddress(), '0x00'),
- )
- })
-
- it('announces the change via a log', async () => {
- await expect(tx).to.emit(controller, 'CheckAccessEnabled')
- })
- })
- })
-})
diff --git a/contracts/test/v0.6/VRFD20.test.ts b/contracts/test/v0.6/VRFD20.test.ts
deleted file mode 100644
index 77141be623..0000000000
--- a/contracts/test/v0.6/VRFD20.test.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert, expect } from 'chai'
-import {
- BigNumber,
- constants,
- Contract,
- ContractFactory,
- ContractTransaction,
-} from 'ethers'
-import { getUsers, Personas, Roles } from '../test-helpers/setup'
-import {
- evmWordToAddress,
- getLog,
- publicAbi,
- toBytes32String,
- toWei,
- numToBytes32,
- getLogs,
-} from '../test-helpers/helpers'
-
-let roles: Roles
-let personas: Personas
-let linkTokenFactory: ContractFactory
-let vrfCoordinatorMockFactory: ContractFactory
-let vrfD20Factory: ContractFactory
-
-before(async () => {
- const users = await getUsers()
-
- roles = users.roles
- personas = users.personas
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
- vrfCoordinatorMockFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/VRFCoordinatorMock.sol:VRFCoordinatorMock',
- roles.defaultAccount,
- )
- vrfD20Factory = await ethers.getContractFactory(
- 'src/v0.6/examples/VRFD20.sol:VRFD20',
- roles.defaultAccount,
- )
-})
-
-describe('VRFD20', () => {
- const deposit = toWei('1')
- const fee = toWei('0.1')
- const keyHash = toBytes32String('keyHash')
-
- let link: Contract
- let vrfCoordinator: Contract
- let vrfD20: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- vrfCoordinator = await vrfCoordinatorMockFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
- vrfD20 = await vrfD20Factory
- .connect(roles.defaultAccount)
- .deploy(vrfCoordinator.address, link.address, keyHash, fee)
- await link.transfer(vrfD20.address, deposit)
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(vrfD20, [
- // Owned
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- //VRFConsumerBase
- 'rawFulfillRandomness',
- // VRFD20
- 'rollDice',
- 'house',
- 'withdrawLINK',
- 'keyHash',
- 'fee',
- 'setKeyHash',
- 'setFee',
- ])
- })
-
- describe('#withdrawLINK', () => {
- describe('failure', () => {
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20
- .connect(roles.stranger)
- .withdrawLINK(await roles.stranger.getAddress(), deposit),
- ).to.be.revertedWith('Only callable by owner')
- })
-
- it('reverts when not enough LINK in the contract', async () => {
- const withdrawAmount = deposit.mul(2)
- await expect(
- vrfD20
- .connect(roles.defaultAccount)
- .withdrawLINK(
- await roles.defaultAccount.getAddress(),
- withdrawAmount,
- ),
- ).to.be.reverted
- })
- })
-
- describe('success', () => {
- it('withdraws LINK', async () => {
- const startingAmount = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
- const expectedAmount = BigNumber.from(startingAmount).add(deposit)
- await vrfD20
- .connect(roles.defaultAccount)
- .withdrawLINK(await roles.defaultAccount.getAddress(), deposit)
- const actualAmount = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
- assert.equal(actualAmount.toString(), expectedAmount.toString())
- })
- })
- })
-
- describe('#setKeyHash', () => {
- const newHash = toBytes32String('newhash')
-
- describe('failure', () => {
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20.connect(roles.stranger).setKeyHash(newHash),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('success', () => {
- it('sets the key hash', async () => {
- await vrfD20.setKeyHash(newHash)
- const actualHash = await vrfD20.keyHash()
- assert.equal(actualHash, newHash)
- })
- })
- })
-
- describe('#setFee', () => {
- const newFee = 1234
-
- describe('failure', () => {
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20.connect(roles.stranger).setFee(newFee),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('success', () => {
- it('sets the fee', async () => {
- await vrfD20.setFee(newFee)
- const actualFee = await vrfD20.fee()
- assert.equal(actualFee.toString(), newFee.toString())
- })
- })
- })
-
- describe('#house', () => {
- describe('failure', () => {
- it('reverts when dice not rolled', async () => {
- await expect(
- vrfD20.house(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Dice not rolled')
- })
-
- it('reverts when dice roll is in progress', async () => {
- await vrfD20.rollDice(await personas.Nancy.getAddress())
- await expect(
- vrfD20.house(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Roll in progress')
- })
- })
-
- describe('success', () => {
- it('returns the correct house', async () => {
- const randomness = 98765
- const expectedHouse = 'Martell'
- const tx = await vrfD20.rollDice(await personas.Nancy.getAddress())
- const log = await getLog(tx, 3)
- const eventRequestId = log?.topics?.[1]
- await vrfCoordinator.callBackWithRandomness(
- eventRequestId,
- randomness,
- vrfD20.address,
- )
- const response = await vrfD20.house(await personas.Nancy.getAddress())
- assert.equal(response.toString(), expectedHouse)
- })
- })
- })
-
- describe('#rollDice', () => {
- describe('success', () => {
- let tx: ContractTransaction
- beforeEach(async () => {
- tx = await vrfD20.rollDice(await personas.Nancy.getAddress())
- })
-
- it('emits a RandomnessRequest event from the VRFCoordinator', async () => {
- const log = await getLog(tx, 2)
- const topics = log?.topics
- assert.equal(evmWordToAddress(topics?.[1]), vrfD20.address)
- assert.equal(topics?.[2], keyHash)
- assert.equal(topics?.[3], constants.HashZero)
- })
- })
-
- describe('failure', () => {
- it('reverts when LINK balance is zero', async () => {
- const vrfD202 = await vrfD20Factory
- .connect(roles.defaultAccount)
- .deploy(vrfCoordinator.address, link.address, keyHash, fee)
- await expect(
- vrfD202.rollDice(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Not enough LINK to pay fee')
- })
-
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20
- .connect(roles.stranger)
- .rollDice(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Only callable by owner')
- })
-
- it('reverts when the roller rolls more than once', async () => {
- await vrfD20.rollDice(await personas.Nancy.getAddress())
- await expect(
- vrfD20.rollDice(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Already rolled')
- })
- })
- })
-
- describe('#fulfillRandomness', () => {
- const randomness = 98765
- const expectedModResult = (randomness % 20) + 1
- const expectedHouse = 'Martell'
- let eventRequestId: string
- beforeEach(async () => {
- const tx = await vrfD20.rollDice(await personas.Nancy.getAddress())
- const log = await getLog(tx, 3)
- eventRequestId = log?.topics?.[1]
- })
-
- describe('success', () => {
- let tx: ContractTransaction
- beforeEach(async () => {
- tx = await vrfCoordinator.callBackWithRandomness(
- eventRequestId,
- randomness,
- vrfD20.address,
- )
- })
-
- it('emits a DiceLanded event', async () => {
- const log = await getLog(tx, 0)
- assert.equal(log?.topics[1], eventRequestId)
- assert.equal(log?.topics[2], numToBytes32(expectedModResult))
- })
-
- it('sets the correct dice roll result', async () => {
- const response = await vrfD20.house(await personas.Nancy.getAddress())
- assert.equal(response.toString(), expectedHouse)
- })
-
- it('allows someone else to roll', async () => {
- const secondRandomness = 55555
- tx = await vrfD20.rollDice(await personas.Ned.getAddress())
- const log = await getLog(tx, 3)
- eventRequestId = log?.topics?.[1]
- tx = await vrfCoordinator.callBackWithRandomness(
- eventRequestId,
- secondRandomness,
- vrfD20.address,
- )
- })
- })
-
- describe('failure', () => {
- it('does not fulfill when fulfilled by the wrong VRFcoordinator', async () => {
- const vrfCoordinator2 = await vrfCoordinatorMockFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
-
- const tx = await vrfCoordinator2.callBackWithRandomness(
- eventRequestId,
- randomness,
- vrfD20.address,
- )
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/AggregatorProxy.test.ts b/contracts/test/v0.7/AggregatorProxy.test.ts
deleted file mode 100644
index 6e8ee41983..0000000000
--- a/contracts/test/v0.7/AggregatorProxy.test.ts
+++ /dev/null
@@ -1,743 +0,0 @@
-import { ethers } from 'hardhat'
-import {
- increaseTimeBy,
- numToBytes32,
- publicAbi,
- toWei,
-} from '../test-helpers/helpers'
-import { assert } from 'chai'
-import { BigNumber, constants, Contract, ContractFactory, Signer } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { bigNumEquals, evmRevert } from '../test-helpers/matchers'
-
-let personas: Personas
-let defaultAccount: Signer
-
-let linkTokenFactory: ContractFactory
-let aggregatorFactory: ContractFactory
-let historicAggregatorFactory: ContractFactory
-let aggregatorFacadeFactory: ContractFactory
-let aggregatorProxyFactory: ContractFactory
-let fluxAggregatorFactory: ContractFactory
-let reverterFactory: ContractFactory
-
-before(async () => {
- const users = await getUsers()
-
- personas = users.personas
- defaultAccount = users.roles.defaultAccount
-
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- defaultAccount,
- )
- aggregatorFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator',
- defaultAccount,
- )
- historicAggregatorFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MockV2Aggregator.sol:MockV2Aggregator',
- defaultAccount,
- )
- aggregatorFacadeFactory = await ethers.getContractFactory(
- 'src/v0.6/AggregatorFacade.sol:AggregatorFacade',
- defaultAccount,
- )
- historicAggregatorFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MockV2Aggregator.sol:MockV2Aggregator',
- defaultAccount,
- )
- aggregatorFacadeFactory = await ethers.getContractFactory(
- 'src/v0.6/AggregatorFacade.sol:AggregatorFacade',
- defaultAccount,
- )
- aggregatorProxyFactory = await ethers.getContractFactory(
- 'src/v0.7/dev/AggregatorProxy.sol:AggregatorProxy',
- defaultAccount,
- )
- fluxAggregatorFactory = await ethers.getContractFactory(
- 'src/v0.6/FluxAggregator.sol:FluxAggregator',
- defaultAccount,
- )
- reverterFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/Reverter.sol:Reverter',
- defaultAccount,
- )
-})
-
-describe('AggregatorProxy', () => {
- const deposit = toWei('100')
- const response = numToBytes32(54321)
- const response2 = numToBytes32(67890)
- const decimals = 18
- const phaseBase = BigNumber.from(2).pow(64)
-
- let link: Contract
- let aggregator: Contract
- let aggregator2: Contract
- let historicAggregator: Contract
- let proxy: Contract
- let flux: Contract
- let reverter: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(defaultAccount).deploy()
- aggregator = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response)
- await link.transfer(aggregator.address, deposit)
- proxy = await aggregatorProxyFactory
- .connect(defaultAccount)
- .deploy(aggregator.address)
- const emptyAddress = constants.AddressZero
- flux = await fluxAggregatorFactory
- .connect(personas.Carol)
- .deploy(link.address, 0, 0, emptyAddress, 0, 0, 18, 'TEST / LINK')
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(proxy, [
- 'aggregator',
- 'confirmAggregator',
- 'decimals',
- 'description',
- 'getAnswer',
- 'getRoundData',
- 'getTimestamp',
- 'latestAnswer',
- 'latestRound',
- 'latestRoundData',
- 'latestTimestamp',
- 'phaseAggregators',
- 'phaseId',
- 'proposeAggregator',
- 'proposedAggregator',
- 'proposedGetRoundData',
- 'proposedLatestRoundData',
- 'version',
- // Ownable methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('constructor', () => {
- it('sets the proxy phase and aggregator', async () => {
- bigNumEquals(1, await proxy.phaseId())
- assert.equal(aggregator.address, await proxy.phaseAggregators(1))
- })
- })
-
- describe('#latestRound', () => {
- it('pulls the rate from the aggregator', async () => {
- bigNumEquals(phaseBase.add(1), await proxy.latestRound())
- })
- })
-
- describe('#latestAnswer', () => {
- it('pulls the rate from the aggregator', async () => {
- bigNumEquals(response, await proxy.latestAnswer())
- const latestRound = await proxy.latestRound()
- bigNumEquals(response, await proxy.getAnswer(latestRound))
- })
-
- describe('after being updated to another contract', () => {
- beforeEach(async () => {
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
- await link.transfer(aggregator2.address, deposit)
- bigNumEquals(response2, await aggregator2.latestAnswer())
-
- await proxy.proposeAggregator(aggregator2.address)
- await proxy.confirmAggregator(aggregator2.address)
- })
-
- it('pulls the rate from the new aggregator', async () => {
- bigNumEquals(response2, await proxy.latestAnswer())
- const latestRound = await proxy.latestRound()
- bigNumEquals(response2, await proxy.getAnswer(latestRound))
- })
- })
-
- describe('when the relevant info is not available', () => {
- beforeEach(async () => {
- await proxy.proposeAggregator(flux.address)
- await proxy.confirmAggregator(flux.address)
- })
-
- it('does not revert when called with a non existent ID', async () => {
- const actual = await proxy.latestAnswer()
- bigNumEquals(0, actual)
- })
- })
- })
-
- describe('#getAnswer', () => {
- describe('when the relevant round is not available', () => {
- beforeEach(async () => {
- await proxy.proposeAggregator(flux.address)
- await proxy.confirmAggregator(flux.address)
- })
-
- it('does not revert when called with a non existent ID', async () => {
- const proxyId = phaseBase.mul(await proxy.phaseId()).add(1)
- const actual = await proxy.getAnswer(proxyId)
- bigNumEquals(0, actual)
- })
- })
-
- describe('when the answer reverts in a non-predicted way', () => {
- it('reverts', async () => {
- reverter = await reverterFactory.connect(defaultAccount).deploy()
- await proxy.proposeAggregator(reverter.address)
- await proxy.confirmAggregator(reverter.address)
- assert.equal(reverter.address, await proxy.aggregator())
-
- const proxyId = phaseBase.mul(await proxy.phaseId())
-
- await evmRevert(proxy.getAnswer(proxyId), 'Raised by Reverter.sol')
- })
- })
-
- describe('after being updated to another contract', () => {
- let preUpdateRoundId: BigNumber
- let preUpdateAnswer: BigNumber
-
- beforeEach(async () => {
- preUpdateRoundId = await proxy.latestRound()
- preUpdateAnswer = await proxy.latestAnswer()
-
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
- await link.transfer(aggregator2.address, deposit)
- bigNumEquals(response2, await aggregator2.latestAnswer())
-
- await proxy.proposeAggregator(aggregator2.address)
- await proxy.confirmAggregator(aggregator2.address)
- })
-
- it('reports answers for previous phases', async () => {
- const actualAnswer = await proxy.getAnswer(preUpdateRoundId)
- bigNumEquals(preUpdateAnswer, actualAnswer)
- })
- })
-
- describe('when the relevant info is not available', () => {
- it('returns 0', async () => {
- const actual = await proxy.getAnswer(phaseBase.mul(777))
- bigNumEquals(0, actual)
- })
- })
-
- describe('when the round ID is too large', () => {
- const overflowRoundId = BigNumber.from(2)
- .pow(255)
- .add(phaseBase) // get the original phase
- .add(1) // get the original round
- it('returns 0', async () => {
- const actual = await proxy.getTimestamp(overflowRoundId)
- bigNumEquals(0, actual)
- })
- })
- })
-
- describe('#getTimestamp', () => {
- describe('when the relevant round is not available', () => {
- beforeEach(async () => {
- await proxy.proposeAggregator(flux.address)
- await proxy.confirmAggregator(flux.address)
- })
-
- it('does not revert when called with a non existent ID', async () => {
- const proxyId = phaseBase.mul(await proxy.phaseId()).add(1)
- const actual = await proxy.getTimestamp(proxyId)
- bigNumEquals(0, actual)
- })
- })
-
- describe('when the relevant info is not available', () => {
- it('returns 0', async () => {
- const actual = await proxy.getTimestamp(phaseBase.mul(777))
- bigNumEquals(0, actual)
- })
- })
-
- describe('when the round ID is too large', () => {
- const overflowRoundId = BigNumber.from(2)
- .pow(255)
- .add(phaseBase) // get the original phase
- .add(1) // get the original round
-
- it('returns 0', async () => {
- const actual = await proxy.getTimestamp(overflowRoundId)
- bigNumEquals(0, actual)
- })
- })
- })
-
- describe('#latestTimestamp', () => {
- beforeEach(async () => {
- const height = await aggregator.latestTimestamp()
- assert.notEqual('0', height.toString())
- })
-
- it('pulls the timestamp from the aggregator', async () => {
- bigNumEquals(
- await aggregator.latestTimestamp(),
- await proxy.latestTimestamp(),
- )
- const latestRound = await proxy.latestRound()
- bigNumEquals(
- await aggregator.latestTimestamp(),
- await proxy.getTimestamp(latestRound),
- )
- })
-
- describe('after being updated to another contract', () => {
- beforeEach(async () => {
- await increaseTimeBy(30, ethers.provider)
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
-
- const height2 = await aggregator2.latestTimestamp()
- assert.notEqual('0', height2.toString())
-
- const height1 = await aggregator.latestTimestamp()
- assert.notEqual(
- height1.toString(),
- height2.toString(),
- 'Height1 and Height2 should not be equal',
- )
-
- await proxy.proposeAggregator(aggregator2.address)
- await proxy.confirmAggregator(aggregator2.address)
- })
-
- it('pulls the timestamp from the new aggregator', async () => {
- bigNumEquals(
- await aggregator2.latestTimestamp(),
- await proxy.latestTimestamp(),
- )
- const latestRound = await proxy.latestRound()
- bigNumEquals(
- await aggregator2.latestTimestamp(),
- await proxy.getTimestamp(latestRound),
- )
- })
- })
- })
-
- describe('#getRoundData', () => {
- describe('when pointed at a Historic Aggregator', () => {
- beforeEach(async () => {
- historicAggregator = await historicAggregatorFactory
- .connect(defaultAccount)
- .deploy(response2)
- await proxy.proposeAggregator(historicAggregator.address)
- await proxy.confirmAggregator(historicAggregator.address)
- })
-
- it('reverts', async () => {
- const latestRoundId = await historicAggregator.latestRound()
- await evmRevert(proxy.getRoundData(latestRoundId))
- })
-
- describe('when pointed at an Aggregator Facade', () => {
- beforeEach(async () => {
- const facade = await aggregatorFacadeFactory
- .connect(defaultAccount)
- .deploy(aggregator.address, 18, 'LINK/USD: Aggregator Facade')
- await proxy.proposeAggregator(facade.address)
- await proxy.confirmAggregator(facade.address)
- })
-
- it('works for a valid roundId', async () => {
- const aggId = await aggregator.latestRound()
- const phaseId = phaseBase.mul(await proxy.phaseId())
- const proxyId = phaseId.add(aggId)
-
- const round = await proxy.getRoundData(proxyId)
- bigNumEquals(proxyId, round.id)
- bigNumEquals(response, round.answer)
- const nowSeconds = new Date().valueOf() / 1000
- assert.isAbove(round.updatedAt.toNumber(), nowSeconds - 120)
- bigNumEquals(round.updatedAt, round.startedAt)
- bigNumEquals(proxyId, round.answeredInRound)
- })
- })
- })
-
- describe('when pointed at a FluxAggregator', () => {
- beforeEach(async () => {
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
-
- await proxy.proposeAggregator(aggregator2.address)
- await proxy.confirmAggregator(aggregator2.address)
- })
-
- it('works for a valid round ID', async () => {
- const aggId = phaseBase.sub(2)
- await aggregator2
- .connect(personas.Carol)
- .updateRoundData(aggId, response2, 77, 42)
-
- const phaseId = phaseBase.mul(await proxy.phaseId())
- const proxyId = phaseId.add(aggId)
-
- const round = await proxy.getRoundData(proxyId)
- bigNumEquals(proxyId, round.id)
- bigNumEquals(response2, round.answer)
- bigNumEquals(42, round.startedAt)
- bigNumEquals(77, round.updatedAt)
- bigNumEquals(proxyId, round.answeredInRound)
- })
- })
-
- it('reads round ID of a previous phase', async () => {
- const oldphaseId = phaseBase.mul(await proxy.phaseId())
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
-
- await proxy.proposeAggregator(aggregator2.address)
- await proxy.confirmAggregator(aggregator2.address)
-
- const aggId = await aggregator.latestRound()
- const proxyId = oldphaseId.add(aggId)
-
- const round = await proxy.getRoundData(proxyId)
- bigNumEquals(proxyId, round.id)
- bigNumEquals(response, round.answer)
-
- const nowSeconds = new Date().valueOf() / 1000
- assert.isAbove(round.startedAt.toNumber(), nowSeconds - 120)
- bigNumEquals(round.startedAt, round.updatedAt)
- bigNumEquals(proxyId, round.answeredInRound)
- })
- })
-
- describe('#latestRoundData', () => {
- describe('when pointed at a Historic Aggregator', () => {
- beforeEach(async () => {
- historicAggregator = await historicAggregatorFactory
- .connect(defaultAccount)
- .deploy(response2)
- await proxy.proposeAggregator(historicAggregator.address)
- await proxy.confirmAggregator(historicAggregator.address)
- })
-
- it('reverts', async () => {
- await evmRevert(proxy.latestRoundData())
- })
-
- describe('when pointed at an Aggregator Facade', () => {
- beforeEach(async () => {
- const facade = await aggregatorFacadeFactory
- .connect(defaultAccount)
- .deploy(
- historicAggregator.address,
- 17,
- 'DOGE/ZWL: Aggregator Facade',
- )
- await proxy.proposeAggregator(facade.address)
- await proxy.confirmAggregator(facade.address)
- })
-
- it('does not revert', async () => {
- const aggId = await historicAggregator.latestRound()
- const phaseId = phaseBase.mul(await proxy.phaseId())
- const proxyId = phaseId.add(aggId)
-
- const round = await proxy.latestRoundData()
- bigNumEquals(proxyId, round.id)
- bigNumEquals(response2, round.answer)
- const nowSeconds = new Date().valueOf() / 1000
- assert.isAbove(round.updatedAt.toNumber(), nowSeconds - 120)
- bigNumEquals(round.updatedAt, round.startedAt)
- bigNumEquals(proxyId, round.answeredInRound)
- })
-
- it('uses the decimals set in the constructor', async () => {
- bigNumEquals(17, await proxy.decimals())
- })
-
- it('uses the description set in the constructor', async () => {
- assert.equal('DOGE/ZWL: Aggregator Facade', await proxy.description())
- })
-
- it('sets the version to 2', async () => {
- bigNumEquals(2, await proxy.version())
- })
- })
- })
-
- describe('when pointed at a FluxAggregator', () => {
- beforeEach(async () => {
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
-
- await proxy.proposeAggregator(aggregator2.address)
- await proxy.confirmAggregator(aggregator2.address)
- })
-
- it('does not revert', async () => {
- const aggId = phaseBase.sub(2)
- await aggregator2
- .connect(personas.Carol)
- .updateRoundData(aggId, response2, 77, 42)
-
- const phaseId = phaseBase.mul(await proxy.phaseId())
- const proxyId = phaseId.add(aggId)
-
- const round = await proxy.latestRoundData()
- bigNumEquals(proxyId, round.id)
- bigNumEquals(response2, round.answer)
- bigNumEquals(42, round.startedAt)
- bigNumEquals(77, round.updatedAt)
- bigNumEquals(proxyId, round.answeredInRound)
- })
-
- it('uses the decimals of the aggregator', async () => {
- bigNumEquals(18, await proxy.decimals())
- })
-
- it('uses the description of the aggregator', async () => {
- assert.equal(
- 'v0.6/tests/MockV3Aggregator.sol',
- await proxy.description(),
- )
- })
-
- it('uses the version of the aggregator', async () => {
- bigNumEquals(0, await proxy.version())
- })
- })
- })
-
- describe('#proposeAggregator', () => {
- beforeEach(async () => {
- await proxy.transferOwnership(await personas.Carol.getAddress())
- await proxy.connect(personas.Carol).acceptOwnership()
-
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, 1)
-
- assert.equal(aggregator.address, await proxy.aggregator())
- })
-
- describe('when called by the owner', () => {
- it('sets the address of the proposed aggregator', async () => {
- await proxy
- .connect(personas.Carol)
- .proposeAggregator(aggregator2.address)
-
- assert.equal(aggregator2.address, await proxy.proposedAggregator())
- })
-
- it('emits an AggregatorProposed event', async () => {
- const tx = await proxy
- .connect(personas.Carol)
- .proposeAggregator(aggregator2.address)
- const receipt = await tx.wait()
- const eventLog = receipt?.events
-
- assert.equal(eventLog?.length, 1)
- assert.equal(eventLog?.[0].event, 'AggregatorProposed')
- assert.equal(eventLog?.[0].args?.[0], aggregator.address)
- assert.equal(eventLog?.[0].args?.[1], aggregator2.address)
- })
- })
-
- describe('when called by a non-owner', () => {
- it('does not update', async () => {
- await evmRevert(
- proxy.connect(personas.Neil).proposeAggregator(aggregator2.address),
- 'Only callable by owner',
- )
-
- assert.equal(aggregator.address, await proxy.aggregator())
- })
- })
- })
-
- describe('#confirmAggregator', () => {
- beforeEach(async () => {
- await proxy.transferOwnership(await personas.Carol.getAddress())
- await proxy.connect(personas.Carol).acceptOwnership()
-
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, 1)
-
- assert.equal(aggregator.address, await proxy.aggregator())
- })
-
- describe('when called by the owner', () => {
- beforeEach(async () => {
- await proxy
- .connect(personas.Carol)
- .proposeAggregator(aggregator2.address)
- })
-
- it('sets the address of the new aggregator', async () => {
- await proxy
- .connect(personas.Carol)
- .confirmAggregator(aggregator2.address)
-
- assert.equal(aggregator2.address, await proxy.aggregator())
- })
-
- it('increases the phase', async () => {
- bigNumEquals(1, await proxy.phaseId())
-
- await proxy
- .connect(personas.Carol)
- .confirmAggregator(aggregator2.address)
-
- bigNumEquals(2, await proxy.phaseId())
- })
-
- it('increases the round ID', async () => {
- bigNumEquals(phaseBase.add(1), await proxy.latestRound())
-
- await proxy
- .connect(personas.Carol)
- .confirmAggregator(aggregator2.address)
-
- bigNumEquals(phaseBase.mul(2).add(1), await proxy.latestRound())
- })
-
- it('sets the proxy phase and aggregator', async () => {
- assert.equal(
- '0x0000000000000000000000000000000000000000',
- await proxy.phaseAggregators(2),
- )
-
- await proxy
- .connect(personas.Carol)
- .confirmAggregator(aggregator2.address)
-
- assert.equal(aggregator2.address, await proxy.phaseAggregators(2))
- })
-
- it('emits an AggregatorConfirmed event', async () => {
- const tx = await proxy
- .connect(personas.Carol)
- .confirmAggregator(aggregator2.address)
- const receipt = await tx.wait()
- const eventLog = receipt?.events
-
- assert.equal(eventLog?.length, 1)
- assert.equal(eventLog?.[0].event, 'AggregatorConfirmed')
- assert.equal(eventLog?.[0].args?.[0], aggregator.address)
- assert.equal(eventLog?.[0].args?.[1], aggregator2.address)
- })
- })
-
- describe('when called by a non-owner', () => {
- beforeEach(async () => {
- await proxy
- .connect(personas.Carol)
- .proposeAggregator(aggregator2.address)
- })
-
- it('does not update', async () => {
- await evmRevert(
- proxy.connect(personas.Neil).confirmAggregator(aggregator2.address),
- 'Only callable by owner',
- )
-
- assert.equal(aggregator.address, await proxy.aggregator())
- })
- })
- })
-
- describe('#proposedGetRoundData', () => {
- beforeEach(async () => {
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
- })
-
- describe('when an aggregator has been proposed', () => {
- beforeEach(async () => {
- await proxy
- .connect(defaultAccount)
- .proposeAggregator(aggregator2.address)
- assert.equal(await proxy.proposedAggregator(), aggregator2.address)
- })
-
- it('returns the data for the proposed aggregator', async () => {
- const roundId = await aggregator2.latestRound()
- const round = await proxy.proposedGetRoundData(roundId)
- bigNumEquals(roundId, round.id)
- bigNumEquals(response2, round.answer)
- })
-
- describe('after the aggregator has been confirmed', () => {
- beforeEach(async () => {
- await proxy
- .connect(defaultAccount)
- .confirmAggregator(aggregator2.address)
- assert.equal(await proxy.aggregator(), aggregator2.address)
- })
-
- it('reverts', async () => {
- const roundId = await aggregator2.latestRound()
- await evmRevert(
- proxy.proposedGetRoundData(roundId),
- 'No proposed aggregator present',
- )
- })
- })
- })
- })
-
- describe('#proposedLatestRoundData', () => {
- beforeEach(async () => {
- aggregator2 = await aggregatorFactory
- .connect(defaultAccount)
- .deploy(decimals, response2)
- })
-
- describe('when an aggregator has been proposed', () => {
- beforeEach(async () => {
- await proxy
- .connect(defaultAccount)
- .proposeAggregator(aggregator2.address)
- assert.equal(await proxy.proposedAggregator(), aggregator2.address)
- })
-
- it('returns the data for the proposed aggregator', async () => {
- const roundId = await aggregator2.latestRound()
- const round = await proxy.proposedLatestRoundData()
- bigNumEquals(roundId, round.id)
- bigNumEquals(response2, round.answer)
- })
-
- describe('after the aggregator has been confirmed', () => {
- beforeEach(async () => {
- await proxy
- .connect(defaultAccount)
- .confirmAggregator(aggregator2.address)
- assert.equal(await proxy.aggregator(), aggregator2.address)
- })
-
- it('reverts', async () => {
- await evmRevert(
- proxy.proposedLatestRoundData(),
- 'No proposed aggregator present',
- )
- })
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/AuthorizedForwarder.test.ts b/contracts/test/v0.7/AuthorizedForwarder.test.ts
deleted file mode 100644
index e1fa2f1f70..0000000000
--- a/contracts/test/v0.7/AuthorizedForwarder.test.ts
+++ /dev/null
@@ -1,444 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { Contract, ContractFactory, ContractReceipt } from 'ethers'
-import { getUsers, Roles } from '../test-helpers/setup'
-import { evmRevert } from '../test-helpers/matchers'
-
-let getterSetterFactory: ContractFactory
-let forwarderFactory: ContractFactory
-let brokenFactory: ContractFactory
-let linkTokenFactory: ContractFactory
-
-let roles: Roles
-const zeroAddress = ethers.constants.AddressZero
-
-before(async () => {
- const users = await getUsers()
-
- roles = users.roles
- getterSetterFactory = await ethers.getContractFactory(
- 'src/v0.4/tests/GetterSetter.sol:GetterSetter',
- roles.defaultAccount,
- )
- brokenFactory = await ethers.getContractFactory(
- 'src/v0.8/tests/Broken.sol:Broken',
- roles.defaultAccount,
- )
- forwarderFactory = await ethers.getContractFactory(
- 'src/v0.7/AuthorizedForwarder.sol:AuthorizedForwarder',
- roles.defaultAccount,
- )
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
-})
-
-describe('AuthorizedForwarder', () => {
- let link: Contract
- let forwarder: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- forwarder = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(
- link.address,
- await roles.defaultAccount.getAddress(),
- zeroAddress,
- '0x',
- )
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(forwarder, [
- 'forward',
- 'getAuthorizedSenders',
- 'getChainlinkToken',
- 'isAuthorizedSender',
- 'ownerForward',
- 'setAuthorizedSenders',
- 'transferOwnershipWithMessage',
- 'typeAndVersion',
- // ConfirmedOwner
- 'transferOwnership',
- 'acceptOwnership',
- 'owner',
- ])
- })
-
- describe('#typeAndVersion', () => {
- it('describes the authorized forwarder', async () => {
- assert.equal(
- await forwarder.typeAndVersion(),
- 'AuthorizedForwarder 1.0.0',
- )
- })
- })
-
- describe('deployment', () => {
- it('sets the correct link token', async () => {
- assert.equal(await forwarder.getChainlinkToken(), link.address)
- })
-
- it('reverts on zeroAddress value for link token', async () => {
- await evmRevert(
- forwarderFactory.connect(roles.defaultAccount).deploy(
- zeroAddress, // Link Address
- await roles.defaultAccount.getAddress(),
- zeroAddress,
- '0x',
- ),
- )
- })
-
- it('sets no authorized senders', async () => {
- const senders = await forwarder.getAuthorizedSenders()
- assert.equal(senders.length, 0)
- })
- })
-
- describe('#setAuthorizedSenders', () => {
- let newSenders: string[]
- let receipt: ContractReceipt
- describe('when called by the owner', () => {
- describe('set authorized senders containing duplicate/s', () => {
- beforeEach(async () => {
- newSenders = [
- await roles.oracleNode1.getAddress(),
- await roles.oracleNode1.getAddress(),
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
- })
- it('reverts with a must not have duplicate senders message', async () => {
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .setAuthorizedSenders(newSenders),
- 'Must not have duplicate senders',
- )
- })
- })
-
- describe('setting 3 authorized senders', () => {
- beforeEach(async () => {
- newSenders = [
- await roles.oracleNode1.getAddress(),
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .setAuthorizedSenders(newSenders)
- receipt = await tx.wait()
- })
-
- it('adds the authorized nodes', async () => {
- const authorizedSenders = await forwarder.getAuthorizedSenders()
- assert.equal(newSenders.length, authorizedSenders.length)
- for (let i = 0; i < authorizedSenders.length; i++) {
- assert.equal(authorizedSenders[i], newSenders[i])
- }
- })
-
- it('emits an event', async () => {
- assert.equal(receipt.events?.length, 1)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'AuthorizedSendersChanged')
- const encodedSenders = ethers.utils.defaultAbiCoder.encode(
- ['address[]', 'address'],
- [newSenders, await roles.defaultAccount.getAddress()],
- )
- assert.equal(responseEvent?.data, encodedSenders)
- })
-
- it('replaces the authorized nodes', async () => {
- const newSenders = await forwarder
- .connect(roles.defaultAccount)
- .getAuthorizedSenders()
- assert.notIncludeOrderedMembers(newSenders, [
- await roles.oracleNode.getAddress(),
- ])
- })
-
- after(async () => {
- await forwarder
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.oracleNode.getAddress()])
- })
- })
-
- describe('setting 0 authorized senders', () => {
- beforeEach(async () => {
- newSenders = []
- })
-
- it('reverts with a minimum senders message', async () => {
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .setAuthorizedSenders(newSenders),
- 'Must have at least 1 sender',
- )
- })
- })
- })
-
- describe('when called by a non-owner', () => {
- it('cannot add an authorized node', async () => {
- await evmRevert(
- forwarder
- .connect(roles.stranger)
- .setAuthorizedSenders([await roles.stranger.getAddress()]),
- 'Cannot set authorized senders',
- )
- })
- })
- })
-
- describe('#forward', () => {
- let bytes: string
- let payload: string
- let mock: Contract
-
- beforeEach(async () => {
- mock = await getterSetterFactory.connect(roles.defaultAccount).deploy()
- bytes = ethers.utils.hexlify(ethers.utils.randomBytes(100))
- payload = getterSetterFactory.interface.encodeFunctionData(
- getterSetterFactory.interface.getFunction('setBytes'),
- [bytes],
- )
- })
-
- describe('when called by an unauthorized node', () => {
- it('reverts', async () => {
- await evmRevert(
- forwarder.connect(roles.stranger).forward(mock.address, payload),
- )
- })
- })
-
- describe('when called by an authorized node', () => {
- beforeEach(async () => {
- await forwarder
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.defaultAccount.getAddress()])
- })
-
- describe('when destination call reverts', () => {
- let brokenMock: Contract
- let brokenPayload: string
- let brokenMsgPayload: string
-
- beforeEach(async () => {
- brokenMock = await brokenFactory
- .connect(roles.defaultAccount)
- .deploy()
- brokenMsgPayload = brokenFactory.interface.encodeFunctionData(
- brokenFactory.interface.getFunction('revertWithMessage'),
- ['Failure message'],
- )
-
- brokenPayload = brokenFactory.interface.encodeFunctionData(
- brokenFactory.interface.getFunction('revertSilently'),
- [],
- )
- })
-
- describe('when reverts with message', () => {
- it('return revert message', async () => {
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .forward(brokenMock.address, brokenMsgPayload),
- "reverted with reason string 'Failure message'",
- )
- })
- })
-
- describe('when reverts without message', () => {
- it('return silent failure message', async () => {
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .forward(brokenMock.address, brokenPayload),
- 'Forwarded call reverted without reason',
- )
- })
- })
- })
-
- describe('when sending to a non-contract address', () => {
- it('reverts', async () => {
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .forward(zeroAddress, payload),
- 'Must forward to a contract',
- )
- })
- })
-
- describe('when attempting to forward to the link token', () => {
- it('reverts', async () => {
- const sighash = linkTokenFactory.interface.getSighash('name') // any Link Token function
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .forward(link.address, sighash),
- )
- })
- })
-
- describe('when forwarding to any other address', () => {
- it('forwards the data', async () => {
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .forward(mock.address, payload)
- await tx.wait()
- assert.equal(await mock.getBytes(), bytes)
- })
-
- it('perceives the message is sent by the AuthorizedForwarder', async () => {
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .forward(mock.address, payload)
- await expect(tx)
- .to.emit(mock, 'SetBytes')
- .withArgs(forwarder.address, bytes)
- })
- })
- })
- })
-
- describe('#transferOwnershipWithMessage', () => {
- const message = '0x42'
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- forwarder
- .connect(roles.stranger)
- .transferOwnershipWithMessage(
- await roles.stranger.getAddress(),
- message,
- ),
- 'Only callable by owner',
- )
- })
- })
-
- describe('when called by the owner', () => {
- it('calls the normal ownership transfer proposal', async () => {
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .transferOwnershipWithMessage(
- await roles.stranger.getAddress(),
- message,
- )
- const receipt = await tx.wait()
-
- assert.equal(receipt?.events?.[0]?.event, 'OwnershipTransferRequested')
- assert.equal(receipt?.events?.[0]?.address, forwarder.address)
- assert.equal(
- receipt?.events?.[0]?.args?.[0],
- await roles.defaultAccount.getAddress(),
- )
- assert.equal(
- receipt?.events?.[0]?.args?.[1],
- await roles.stranger.getAddress(),
- )
- })
-
- it('calls the normal ownership transfer proposal', async () => {
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .transferOwnershipWithMessage(
- await roles.stranger.getAddress(),
- message,
- )
- const receipt = await tx.wait()
-
- assert.equal(
- receipt?.events?.[1]?.event,
- 'OwnershipTransferRequestedWithMessage',
- )
- assert.equal(receipt?.events?.[1]?.address, forwarder.address)
- assert.equal(
- receipt?.events?.[1]?.args?.[0],
- await roles.defaultAccount.getAddress(),
- )
- assert.equal(
- receipt?.events?.[1]?.args?.[1],
- await roles.stranger.getAddress(),
- )
- assert.equal(receipt?.events?.[1]?.args?.[2], message)
- })
- })
- })
-
- describe('#ownerForward', () => {
- let bytes: string
- let payload: string
- let mock: Contract
-
- beforeEach(async () => {
- mock = await getterSetterFactory.connect(roles.defaultAccount).deploy()
- bytes = ethers.utils.hexlify(ethers.utils.randomBytes(100))
- payload = getterSetterFactory.interface.encodeFunctionData(
- getterSetterFactory.interface.getFunction('setBytes'),
- [bytes],
- )
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- forwarder.connect(roles.stranger).ownerForward(mock.address, payload),
- )
- })
- })
-
- describe('when called by owner', () => {
- describe('when attempting to forward to the link token', () => {
- it('does not revert', async () => {
- const sighash = linkTokenFactory.interface.getSighash('name') // any Link Token function
-
- await forwarder
- .connect(roles.defaultAccount)
- .ownerForward(link.address, sighash)
- })
- })
-
- describe('when forwarding to any other address', () => {
- it('forwards the data', async () => {
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .ownerForward(mock.address, payload)
- await tx.wait()
- assert.equal(await mock.getBytes(), bytes)
- })
-
- it('reverts when sending to a non-contract address', async () => {
- await evmRevert(
- forwarder
- .connect(roles.defaultAccount)
- .ownerForward(zeroAddress, payload),
- 'Must forward to a contract',
- )
- })
-
- it('perceives the message is sent by the Operator', async () => {
- const tx = await forwarder
- .connect(roles.defaultAccount)
- .ownerForward(mock.address, payload)
- await expect(tx)
- .to.emit(mock, 'SetBytes')
- .withArgs(forwarder.address, bytes)
- })
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/Chainlink.test.ts b/contracts/test/v0.7/Chainlink.test.ts
deleted file mode 100644
index 7792895934..0000000000
--- a/contracts/test/v0.7/Chainlink.test.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi, decodeDietCBOR, hexToBuf } from '../test-helpers/helpers'
-import { assert } from 'chai'
-import { Contract, ContractFactory, providers, Signer } from 'ethers'
-import { Roles, getUsers } from '../test-helpers/setup'
-import { makeDebug } from '../test-helpers/debug'
-
-const debug = makeDebug('ChainlinkTestHelper')
-let concreteChainlinkFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- roles = (await getUsers()).roles
- concreteChainlinkFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/ChainlinkTestHelper.sol:ChainlinkTestHelper',
- roles.defaultAccount,
- )
-})
-
-describe('ChainlinkTestHelper', () => {
- let ccl: Contract
- let defaultAccount: Signer
-
- beforeEach(async () => {
- defaultAccount = roles.defaultAccount
- ccl = await concreteChainlinkFactory.connect(defaultAccount).deploy()
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(ccl, [
- 'add',
- 'addBytes',
- 'addInt',
- 'addStringArray',
- 'addUint',
- 'closeEvent',
- 'setBuffer',
- ])
- })
-
- async function parseCCLEvent(tx: providers.TransactionResponse) {
- const receipt = await tx.wait()
- const data = receipt.logs?.[0].data
- const d = debug.extend('parseCCLEvent')
- d('data %s', data)
- return ethers.utils.defaultAbiCoder.decode(['bytes'], data ?? '')
- }
-
- describe('#close', () => {
- it('handles empty payloads', async () => {
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, {})
- })
- })
-
- describe('#setBuffer', () => {
- it('emits the buffer', async () => {
- await ccl.setBuffer('0xA161616162')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { a: 'b' })
- })
- })
-
- describe('#add', () => {
- it('stores and logs keys and values', async () => {
- await ccl.add('first', 'word!!')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { first: 'word!!' })
- })
-
- it('handles two entries', async () => {
- await ccl.add('first', 'uno')
- await ccl.add('second', 'dos')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- assert.deepEqual(decoded, {
- first: 'uno',
- second: 'dos',
- })
- })
- })
-
- describe('#addBytes', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addBytes('first', '0xaabbccddeeff')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- const expected = hexToBuf('0xaabbccddeeff')
- assert.deepEqual(decoded, { first: expected })
- })
-
- it('handles two entries', async () => {
- await ccl.addBytes('first', '0x756E6F')
- await ccl.addBytes('second', '0x646F73')
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- const expectedFirst = hexToBuf('0x756E6F')
- const expectedSecond = hexToBuf('0x646F73')
- assert.deepEqual(decoded, {
- first: expectedFirst,
- second: expectedSecond,
- })
- })
-
- it('handles strings', async () => {
- await ccl.addBytes('first', ethers.utils.toUtf8Bytes('apple'))
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- const expected = ethers.utils.toUtf8Bytes('apple')
- assert.deepEqual(decoded, { first: expected })
- })
- })
-
- describe('#addInt', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addInt('first', 1)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { first: 1 })
- })
-
- it('handles two entries', async () => {
- await ccl.addInt('first', 1)
- await ccl.addInt('second', 2)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- assert.deepEqual(decoded, {
- first: 1,
- second: 2,
- })
- })
- })
-
- describe('#addUint', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addUint('first', 1)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { first: 1 })
- })
-
- it('handles two entries', async () => {
- await ccl.addUint('first', 1)
- await ccl.addUint('second', 2)
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
-
- assert.deepEqual(decoded, {
- first: 1,
- second: 2,
- })
- })
- })
-
- describe('#addStringArray', () => {
- it('stores and logs keys and values', async () => {
- await ccl.addStringArray('word', [
- ethers.utils.formatBytes32String('seinfeld'),
- ethers.utils.formatBytes32String('"4"'),
- ethers.utils.formatBytes32String('LIFE'),
- ])
- const tx = await ccl.closeEvent()
- const [payload] = await parseCCLEvent(tx)
- const decoded = await decodeDietCBOR(payload)
- assert.deepEqual(decoded, { word: ['seinfeld', '"4"', 'LIFE'] })
- })
- })
-})
diff --git a/contracts/test/v0.7/ChainlinkClient.test.ts b/contracts/test/v0.7/ChainlinkClient.test.ts
deleted file mode 100644
index 198d382af7..0000000000
--- a/contracts/test/v0.7/ChainlinkClient.test.ts
+++ /dev/null
@@ -1,454 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert } from 'chai'
-import { Contract, ContractFactory } from 'ethers'
-import { Roles, getUsers } from '../test-helpers/setup'
-import {
- convertFufillParams,
- decodeCCRequest,
- decodeRunRequest,
- RunRequest,
-} from '../test-helpers/oracle'
-import { decodeDietCBOR } from '../test-helpers/helpers'
-import { evmRevert } from '../test-helpers/matchers'
-
-let concreteChainlinkClientFactory: ContractFactory
-let emptyOracleFactory: ContractFactory
-let getterSetterFactory: ContractFactory
-let operatorFactory: ContractFactory
-let linkTokenFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- roles = (await getUsers()).roles
-
- concreteChainlinkClientFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/ChainlinkClientTestHelper.sol:ChainlinkClientTestHelper',
- roles.defaultAccount,
- )
- emptyOracleFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/EmptyOracle.sol:EmptyOracle',
- roles.defaultAccount,
- )
- getterSetterFactory = await ethers.getContractFactory(
- 'src/v0.5/tests/GetterSetter.sol:GetterSetter',
- roles.defaultAccount,
- )
- operatorFactory = await ethers.getContractFactory(
- 'src/v0.7/Operator.sol:Operator',
- roles.defaultAccount,
- )
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
-})
-
-describe('ChainlinkClientTestHelper', () => {
- const specId =
- '0x4c7b7ffb66b344fbaa64995af81e355a00000000000000000000000000000000'
- let cc: Contract
- let gs: Contract
- let oc: Contract
- let newoc: Contract
- let link: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- oc = await operatorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, await roles.defaultAccount.getAddress())
- newoc = await operatorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, await roles.defaultAccount.getAddress())
- gs = await getterSetterFactory.connect(roles.defaultAccount).deploy()
- cc = await concreteChainlinkClientFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, oc.address)
- })
-
- describe('#newRequest', () => {
- it('forwards the information to the oracle contract through the link token', async () => {
- const tx = await cc.publicNewRequest(
- specId,
- gs.address,
- ethers.utils.toUtf8Bytes('requestedBytes32(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
-
- assert.equal(1, receipt.logs?.length)
- const [jId, cbAddr, cbFId, cborData] = receipt.logs
- ? decodeCCRequest(receipt.logs[0])
- : []
- const params = decodeDietCBOR(cborData ?? '')
-
- assert.equal(specId, jId)
- assert.equal(gs.address, cbAddr)
- assert.equal('0xed53e511', cbFId)
- assert.deepEqual({}, params)
- })
- })
-
- describe('#chainlinkRequest(Request)', () => {
- it('emits an event from the contract showing the run ID', async () => {
- const tx = await cc.publicRequest(
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
-
- const { events, logs } = await tx.wait()
-
- assert.equal(4, events?.length)
-
- assert.equal(logs?.[0].address, cc.address)
- assert.equal(events?.[0].event, 'ChainlinkRequested')
- })
- })
-
- describe('#chainlinkRequestTo(Request)', () => {
- it('emits an event from the contract showing the run ID', async () => {
- const tx = await cc.publicRequestRunTo(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { events } = await tx.wait()
-
- assert.equal(4, events?.length)
- assert.equal(events?.[0].event, 'ChainlinkRequested')
- })
-
- it('emits an event on the target oracle contract', async () => {
- const tx = await cc.publicRequestRunTo(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { logs } = await tx.wait()
- const event = logs && newoc.interface.parseLog(logs[3])
-
- assert.equal(4, logs?.length)
- assert.equal(event?.name, 'OracleRequest')
- })
-
- it('does not modify the stored oracle address', async () => {
- await cc.publicRequestRunTo(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
-
- const actualOracleAddress = await cc.publicOracleAddress()
- assert.equal(oc.address, actualOracleAddress)
- })
- })
-
- describe('#requestOracleData', () => {
- it('emits an event from the contract showing the run ID', async () => {
- const tx = await cc.publicRequestOracleData(
- specId,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
-
- const { events, logs } = await tx.wait()
-
- assert.equal(4, events?.length)
-
- assert.equal(logs?.[0].address, cc.address)
- assert.equal(events?.[0].event, 'ChainlinkRequested')
- })
- })
-
- describe('#requestOracleDataFrom', () => {
- it('emits an event from the contract showing the run ID', async () => {
- const tx = await cc.publicRequestOracleDataFrom(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { events } = await tx.wait()
-
- assert.equal(4, events?.length)
- assert.equal(events?.[0].event, 'ChainlinkRequested')
- })
-
- it('emits an event on the target oracle contract', async () => {
- const tx = await cc.publicRequestOracleDataFrom(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { logs } = await tx.wait()
- const event = logs && newoc.interface.parseLog(logs[3])
-
- assert.equal(4, logs?.length)
- assert.equal(event?.name, 'OracleRequest')
- })
-
- it('does not modify the stored oracle address', async () => {
- await cc.publicRequestOracleDataFrom(
- newoc.address,
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
-
- const actualOracleAddress = await cc.publicOracleAddress()
- assert.equal(oc.address, actualOracleAddress)
- })
- })
-
- describe('#cancelChainlinkRequest', () => {
- let requestId: string
- // a concrete chainlink attached to an empty oracle
- let ecc: Contract
-
- beforeEach(async () => {
- const emptyOracle = await emptyOracleFactory
- .connect(roles.defaultAccount)
- .deploy()
- ecc = await concreteChainlinkClientFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, emptyOracle.address)
-
- const tx = await ecc.publicRequest(
- specId,
- ecc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { events } = await tx.wait()
- requestId = (events?.[0]?.args as any).id
- })
-
- it('emits an event from the contract showing the run was cancelled', async () => {
- const tx = await ecc.publicCancelRequest(
- requestId,
- 0,
- ethers.utils.hexZeroPad('0x', 4),
- 0,
- )
- const { events } = await tx.wait()
-
- assert.equal(1, events?.length)
- assert.equal(events?.[0].event, 'ChainlinkCancelled')
- assert.equal(requestId, (events?.[0].args as any).id)
- })
-
- it('throws if given a bogus event ID', async () => {
- await evmRevert(
- ecc.publicCancelRequest(
- ethers.utils.formatBytes32String('bogusId'),
- 0,
- ethers.utils.hexZeroPad('0x', 4),
- 0,
- ),
- )
- })
- })
-
- describe('#recordChainlinkFulfillment(modifier)', () => {
- let request: RunRequest
-
- beforeEach(async () => {
- await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()])
- const tx = await cc.publicRequest(
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const { logs } = await tx.wait()
-
- request = decodeRunRequest(logs?.[3])
- })
-
- it('emits an event marking the request fulfilled', async () => {
- const tx = await oc
- .connect(roles.defaultAccount)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
- const { logs } = await tx.wait()
-
- const event = logs && cc.interface.parseLog(logs[1])
-
- assert.equal(2, logs?.length)
- assert.equal(event?.name, 'ChainlinkFulfilled')
- assert.equal(request.requestId, event?.args.id)
- })
-
- it('should only allow one fulfillment per id', async () => {
- await oc
- .connect(roles.defaultAccount)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
-
- await evmRevert(
- oc
- .connect(roles.defaultAccount)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Must have a valid requestId',
- )
- })
-
- it('should only allow the oracle to fulfill the request', async () => {
- await evmRevert(
- oc
- .connect(roles.stranger)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Not authorized sender',
- )
- })
- })
-
- describe('#fulfillChainlinkRequest(function)', () => {
- let request: RunRequest
-
- beforeEach(async () => {
- await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()])
- const tx = await cc.publicRequest(
- specId,
- cc.address,
- ethers.utils.toUtf8Bytes(
- 'publicFulfillChainlinkRequest(bytes32,bytes32)',
- ),
- 0,
- )
- const { logs } = await tx.wait()
-
- request = decodeRunRequest(logs?.[3])
- })
-
- it('emits an event marking the request fulfilled', async () => {
- const tx = await oc
- .connect(roles.defaultAccount)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
-
- const { logs } = await tx.wait()
- const event = logs && cc.interface.parseLog(logs[1])
-
- assert.equal(2, logs?.length)
- assert.equal(event?.name, 'ChainlinkFulfilled')
- assert.equal(request.requestId, event?.args?.id)
- })
-
- it('should only allow one fulfillment per id', async () => {
- await oc
- .connect(roles.defaultAccount)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
-
- await evmRevert(
- oc
- .connect(roles.defaultAccount)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Must have a valid requestId',
- )
- })
-
- it('should only allow the oracle to fulfill the request', async () => {
- await evmRevert(
- oc
- .connect(roles.stranger)
- .fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- ),
- 'Not authorized sender',
- )
- })
- })
-
- describe('#chainlinkToken', () => {
- it('returns the Link Token address', async () => {
- const addr = await cc.publicChainlinkToken()
- assert.equal(addr, link.address)
- })
- })
-
- describe('#addExternalRequest', () => {
- let mock: Contract
- let request: RunRequest
-
- beforeEach(async () => {
- mock = await concreteChainlinkClientFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, oc.address)
-
- const tx = await cc.publicRequest(
- specId,
- mock.address,
- ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'),
- 0,
- )
- const receipt = await tx.wait()
-
- request = decodeRunRequest(receipt.logs?.[3])
- await mock.publicAddExternalRequest(oc.address, request.requestId)
- })
-
- it('allows the external request to be fulfilled', async () => {
- await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()])
- await oc.fulfillOracleRequest(
- ...convertFufillParams(
- request,
- ethers.utils.formatBytes32String('hi mom!'),
- ),
- )
- })
-
- it('does not allow the same requestId to be used', async () => {
- await evmRevert(
- cc.publicAddExternalRequest(newoc.address, request.requestId),
- )
- })
- })
-})
diff --git a/contracts/test/v0.7/CompoundPriceFlaggingValidator.test.ts b/contracts/test/v0.7/CompoundPriceFlaggingValidator.test.ts
deleted file mode 100644
index 315f7bd9e6..0000000000
--- a/contracts/test/v0.7/CompoundPriceFlaggingValidator.test.ts
+++ /dev/null
@@ -1,471 +0,0 @@
-import { ethers } from 'hardhat'
-import { evmWordToAddress, getLogs, publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import {
- BigNumber,
- Contract,
- ContractFactory,
- ContractTransaction,
-} from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { evmRevert } from '../test-helpers/matchers'
-
-let personas: Personas
-let validatorFactory: ContractFactory
-let acFactory: ContractFactory
-let flagsFactory: ContractFactory
-let aggregatorFactory: ContractFactory
-let compoundOracleFactory: ContractFactory
-
-before(async () => {
- personas = (await getUsers()).personas
-
- validatorFactory = await ethers.getContractFactory(
- 'src/v0.7/dev/CompoundPriceFlaggingValidator.sol:CompoundPriceFlaggingValidator',
- personas.Carol,
- )
- acFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleWriteAccessController.sol:SimpleWriteAccessController',
- personas.Carol,
- )
- flagsFactory = await ethers.getContractFactory(
- 'src/v0.6/Flags.sol:Flags',
- personas.Carol,
- )
- aggregatorFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator',
- personas.Carol,
- )
- compoundOracleFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MockCompoundOracle.sol:MockCompoundOracle',
- personas.Carol,
- )
-})
-
-describe('CompoundPriceFlaggingVlidator', () => {
- let validator: Contract
- let aggregator: Contract
- let compoundOracle: Contract
- let flags: Contract
- let ac: Contract
-
- const aggregatorDecimals = 18
- // 1000
- const initialAggregatorPrice = BigNumber.from('1000000000000000000000')
-
- const compoundSymbol = 'ETH'
- const compoundDecimals = 6
- // 1100 (10% deviation from aggregator price)
- const initialCompoundPrice = BigNumber.from('1100000000')
-
- // (50,000,000 / 1,000,000,000) = 0.05 = 5% deviation threshold
- const initialDeviationNumerator = 50_000_000
-
- beforeEach(async () => {
- ac = await acFactory.connect(personas.Carol).deploy()
- flags = await flagsFactory.connect(personas.Carol).deploy(ac.address)
- aggregator = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(aggregatorDecimals, initialAggregatorPrice)
- compoundOracle = await compoundOracleFactory
- .connect(personas.Carol)
- .deploy()
- await compoundOracle.setPrice(
- compoundSymbol,
- initialCompoundPrice,
- compoundDecimals,
- )
- validator = await validatorFactory
- .connect(personas.Carol)
- .deploy(flags.address, compoundOracle.address)
- await validator
- .connect(personas.Carol)
- .setFeedDetails(
- aggregator.address,
- compoundSymbol,
- compoundDecimals,
- initialDeviationNumerator,
- )
- await ac.connect(personas.Carol).addAccess(validator.address)
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(validator, [
- 'update',
- 'check',
- 'setFeedDetails',
- 'setFlagsAddress',
- 'setCompoundOpenOracleAddress',
- 'getFeedDetails',
- 'flags',
- 'compoundOpenOracle',
- // Upkeep methods:
- 'checkUpkeep',
- 'performUpkeep',
- // Owned methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#constructor', () => {
- it('sets the owner', async () => {
- assert.equal(await validator.owner(), await personas.Carol.getAddress())
- })
-
- it('sets the arguments passed in', async () => {
- assert.equal(await validator.flags(), flags.address)
- assert.equal(await validator.compoundOpenOracle(), compoundOracle.address)
- })
- })
-
- describe('#setOpenOracleAddress', () => {
- let newCompoundOracle: Contract
- let tx: ContractTransaction
-
- beforeEach(async () => {
- newCompoundOracle = await compoundOracleFactory
- .connect(personas.Carol)
- .deploy()
- tx = await validator
- .connect(personas.Carol)
- .setCompoundOpenOracleAddress(newCompoundOracle.address)
- })
-
- it('changes the compound oracke address', async () => {
- assert.equal(
- await validator.compoundOpenOracle(),
- newCompoundOracle.address,
- )
- })
-
- it('emits a log event', async () => {
- await expect(tx)
- .to.emit(validator, 'CompoundOpenOracleAddressUpdated')
- .withArgs(compoundOracle.address, newCompoundOracle.address)
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- validator
- .connect(personas.Neil)
- .setCompoundOpenOracleAddress(newCompoundOracle.address),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('#setFlagsAddress', () => {
- let newFlagsContract: Contract
- let tx: ContractTransaction
-
- beforeEach(async () => {
- newFlagsContract = await flagsFactory
- .connect(personas.Carol)
- .deploy(ac.address)
- tx = await validator
- .connect(personas.Carol)
- .setFlagsAddress(newFlagsContract.address)
- })
-
- it('changes the flags address', async () => {
- assert.equal(await validator.flags(), newFlagsContract.address)
- })
-
- it('emits a log event', async () => {
- await expect(tx)
- .to.emit(validator, 'FlagsAddressUpdated')
- .withArgs(flags.address, newFlagsContract.address)
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- validator
- .connect(personas.Neil)
- .setFlagsAddress(newFlagsContract.address),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('#setFeedDetails', () => {
- let mockAggregator: Contract
- let tx: ContractTransaction
- const symbol = 'BTC'
- const decimals = 8
- const deviationNumerator = 50_000_000 // 5%
-
- beforeEach(async () => {
- await compoundOracle.connect(personas.Carol).setPrice('BTC', 1500000, 2)
- mockAggregator = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, 4000000000000)
- tx = await validator
- .connect(personas.Carol)
- .setFeedDetails(
- mockAggregator.address,
- symbol,
- decimals,
- deviationNumerator,
- )
- })
-
- it('sets the correct state', async () => {
- const response = await validator
- .connect(personas.Carol)
- .getFeedDetails(mockAggregator.address)
-
- assert.equal(response[0], symbol)
- assert.equal(response[1], decimals)
- assert.equal(response[2].toString(), deviationNumerator.toString())
- })
-
- it('uses the existing symbol if one already exists', async () => {
- const newSymbol = 'LINK'
-
- await compoundOracle
- .connect(personas.Carol)
- .setPrice(newSymbol, 1500000, 2)
-
- tx = await validator
- .connect(personas.Carol)
- .setFeedDetails(
- mockAggregator.address,
- newSymbol,
- decimals,
- deviationNumerator,
- )
-
- // Check the event
- await expect(tx)
- .to.emit(validator, 'FeedDetailsSet')
- .withArgs(mockAggregator.address, symbol, decimals, deviationNumerator)
-
- // Check the state
- const response = await validator
- .connect(personas.Carol)
- .getFeedDetails(mockAggregator.address)
- assert.equal(response[0], symbol)
- })
-
- it('emits an event', async () => {
- await expect(tx)
- .to.emit(validator, 'FeedDetailsSet')
- .withArgs(mockAggregator.address, symbol, decimals, deviationNumerator)
- })
-
- it('fails when given a 0 numerator', async () => {
- await evmRevert(
- validator
- .connect(personas.Carol)
- .setFeedDetails(mockAggregator.address, symbol, decimals, 0),
- 'Invalid threshold numerator',
- )
- })
-
- it('fails when given a numerator above 1 billion', async () => {
- await evmRevert(
- validator
- .connect(personas.Carol)
- .setFeedDetails(
- mockAggregator.address,
- symbol,
- decimals,
- 1_200_000_000,
- ),
- 'Invalid threshold numerator',
- )
- })
-
- it('fails when the compound price is invalid', async () => {
- await evmRevert(
- validator
- .connect(personas.Carol)
- .setFeedDetails(
- mockAggregator.address,
- 'TEST',
- decimals,
- deviationNumerator,
- ),
- 'Invalid Compound price',
- )
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- validator
- .connect(personas.Neil)
- .setFeedDetails(
- mockAggregator.address,
- symbol,
- decimals,
- deviationNumerator,
- ),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('#check', () => {
- describe('with a single aggregator', () => {
- describe('with a deviated price exceding threshold', () => {
- it('returns the deviated aggregator', async () => {
- const aggregators = [aggregator.address]
- const response = await validator.check(aggregators)
- assert.equal(response.length, 1)
- assert.equal(response[0], aggregator.address)
- })
- })
-
- describe('with a price within the threshold', () => {
- const newCompoundPrice = BigNumber.from('1000000000')
- beforeEach(async () => {
- await compoundOracle.setPrice(
- 'ETH',
- newCompoundPrice,
- compoundDecimals,
- )
- })
-
- it('returns an empty array', async () => {
- const aggregators = [aggregator.address]
- const response = await validator.check(aggregators)
- assert.equal(response.length, 0)
- })
- })
- })
- })
-
- describe('#update', () => {
- describe('with a single aggregator', () => {
- describe('with a deviated price exceding threshold', () => {
- it('raises a flag on the flags contract', async () => {
- const aggregators = [aggregator.address]
- const tx = await validator.connect(personas.Carol).update(aggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 1)
- assert.equal(evmWordToAddress(logs[0].topics[1]), aggregator.address)
- })
- })
-
- describe('with a price within the threshold', () => {
- const newCompoundPrice = BigNumber.from('1000000000')
- beforeEach(async () => {
- await compoundOracle.setPrice(
- 'ETH',
- newCompoundPrice,
- compoundDecimals,
- )
- })
-
- it('does nothing', async () => {
- const aggregators = [aggregator.address]
- const tx = await validator.connect(personas.Carol).update(aggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
- })
- })
-
- describe('#checkUpkeep', () => {
- describe('with a single aggregator', () => {
- describe('with a deviated price exceding threshold', () => {
- it('returns the deviated aggregator', async () => {
- const aggregators = [aggregator.address]
- const encodedAggregators = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const response = await validator
- .connect(personas.Carol)
- .checkUpkeep(encodedAggregators)
-
- const decodedResponse = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- response?.[1],
- )
- assert.equal(decodedResponse?.[0]?.[0], aggregators[0])
- })
- })
-
- describe('with a price within the threshold', () => {
- const newCompoundPrice = BigNumber.from('1000000000')
- beforeEach(async () => {
- await compoundOracle.setPrice(
- 'ETH',
- newCompoundPrice,
- compoundDecimals,
- )
- })
-
- it('returns an empty array', async () => {
- const aggregators = [aggregator.address]
- const encodedAggregators = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const response = await validator
- .connect(personas.Carol)
- .checkUpkeep(encodedAggregators)
- const decodedResponse = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- response?.[1],
- )
- assert.equal(decodedResponse?.[0]?.length, 0)
- })
- })
- })
- })
-
- describe('#performUpkeep', () => {
- describe('with a single aggregator', () => {
- describe('with a deviated price exceding threshold', () => {
- it('raises a flag on the flags contract', async () => {
- const aggregators = [aggregator.address]
- const encodedAggregators = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const tx = await validator
- .connect(personas.Carol)
- .performUpkeep(encodedAggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 1)
- assert.equal(evmWordToAddress(logs[0].topics[1]), aggregator.address)
- })
- })
-
- describe('with a price within the threshold', () => {
- const newCompoundPrice = BigNumber.from('1000000000')
- beforeEach(async () => {
- await compoundOracle.setPrice(
- 'ETH',
- newCompoundPrice,
- compoundDecimals,
- )
- })
-
- it('does nothing', async () => {
- const aggregators = [aggregator.address]
- const encodedAggregators = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const tx = await validator
- .connect(personas.Carol)
- .performUpkeep(encodedAggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/ConfirmedOwner.test.ts b/contracts/test/v0.7/ConfirmedOwner.test.ts
deleted file mode 100644
index 3502cd15bc..0000000000
--- a/contracts/test/v0.7/ConfirmedOwner.test.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-import { ethers } from 'hardhat'
-import { publicAbi } from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { Contract, ContractFactory, Signer } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { evmRevert } from '../test-helpers/matchers'
-
-let confirmedOwnerTestHelperFactory: ContractFactory
-let confirmedOwnerFactory: ContractFactory
-
-let personas: Personas
-let owner: Signer
-let nonOwner: Signer
-let newOwner: Signer
-
-before(async () => {
- const users = await getUsers()
- personas = users.personas
- owner = personas.Carol
- nonOwner = personas.Neil
- newOwner = personas.Ned
-
- confirmedOwnerTestHelperFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/ConfirmedOwnerTestHelper.sol:ConfirmedOwnerTestHelper',
- owner,
- )
- confirmedOwnerFactory = await ethers.getContractFactory(
- 'src/v0.7/ConfirmedOwner.sol:ConfirmedOwner',
- owner,
- )
-})
-
-describe('ConfirmedOwner', () => {
- let confirmedOwner: Contract
-
- beforeEach(async () => {
- confirmedOwner = await confirmedOwnerTestHelperFactory
- .connect(owner)
- .deploy()
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(confirmedOwner, [
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- // test helper public methods
- 'modifierOnlyOwner',
- ])
- })
-
- describe('#constructor', () => {
- it('assigns ownership to the deployer', async () => {
- const [actual, expected] = await Promise.all([
- owner.getAddress(),
- confirmedOwner.owner(),
- ])
-
- assert.equal(actual, expected)
- })
-
- it('reverts if assigned to the zero address', async () => {
- await evmRevert(
- confirmedOwnerFactory
- .connect(owner)
- .deploy(ethers.constants.AddressZero),
- 'Cannot set owner to zero',
- )
- })
- })
-
- describe('#onlyOwner modifier', () => {
- describe('when called by an owner', () => {
- it('successfully calls the method', async () => {
- const tx = await confirmedOwner.connect(owner).modifierOnlyOwner()
- await expect(tx).to.emit(confirmedOwner, 'Here')
- })
- })
-
- describe('when called by anyone but the owner', () => {
- it('reverts', async () =>
- await evmRevert(confirmedOwner.connect(nonOwner).modifierOnlyOwner()))
- })
- })
-
- describe('#transferOwnership', () => {
- describe('when called by an owner', () => {
- it('emits a log', async () => {
- const tx = await confirmedOwner
- .connect(owner)
- .transferOwnership(await newOwner.getAddress())
- await expect(tx)
- .to.emit(confirmedOwner, 'OwnershipTransferRequested')
- .withArgs(await owner.getAddress(), await newOwner.getAddress())
- })
-
- it('does not allow ownership transfer to self', async () => {
- await evmRevert(
- confirmedOwner
- .connect(owner)
- .transferOwnership(await owner.getAddress()),
- 'Cannot transfer to self',
- )
- })
- })
- })
-
- describe('when called by anyone but the owner', () => {
- it('reverts', async () =>
- await evmRevert(
- confirmedOwner
- .connect(nonOwner)
- .transferOwnership(await newOwner.getAddress()),
- ))
- })
-
- describe('#acceptOwnership', () => {
- describe('after #transferOwnership has been called', () => {
- beforeEach(async () => {
- await confirmedOwner
- .connect(owner)
- .transferOwnership(await newOwner.getAddress())
- })
-
- it('allows the recipient to call it', async () => {
- const tx = await confirmedOwner.connect(newOwner).acceptOwnership()
- await expect(tx)
- .to.emit(confirmedOwner, 'OwnershipTransferred')
- .withArgs(await owner.getAddress(), await newOwner.getAddress())
- })
-
- it('does not allow a non-recipient to call it', async () =>
- await evmRevert(confirmedOwner.connect(nonOwner).acceptOwnership()))
- })
- })
-})
diff --git a/contracts/test/v0.7/KeeperRegistry1_1.test.ts b/contracts/test/v0.7/KeeperRegistry1_1.test.ts
deleted file mode 100644
index 4e3a8c91b3..0000000000
--- a/contracts/test/v0.7/KeeperRegistry1_1.test.ts
+++ /dev/null
@@ -1,1725 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert, expect } from 'chai'
-import { evmRevert } from '../test-helpers/matchers'
-import { getUsers, Personas } from '../test-helpers/setup'
-import { BigNumber, BigNumberish, Signer } from 'ethers'
-import { LinkToken__factory as LinkTokenFactory } from '../../typechain/factories/LinkToken__factory'
-import { KeeperRegistry1_1__factory as KeeperRegistryFactory } from '../../typechain/factories/KeeperRegistry1_1__factory'
-import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../typechain/factories/MockV3Aggregator__factory'
-import { UpkeepMock__factory as UpkeepMockFactory } from '../../typechain/factories/UpkeepMock__factory'
-import { UpkeepReverter__factory as UpkeepReverterFactory } from '../../typechain/factories/UpkeepReverter__factory'
-import { KeeperRegistry1_1 as KeeperRegistry } from '../../typechain/KeeperRegistry1_1'
-import { MockV3Aggregator } from '../../typechain/MockV3Aggregator'
-import { LinkToken } from '../../typechain/LinkToken'
-import { UpkeepMock } from '../../typechain/UpkeepMock'
-import { toWei } from '../test-helpers/helpers'
-
-async function getUpkeepID(tx: any) {
- const receipt = await tx.wait()
- return receipt.events[0].args.id
-}
-
-// -----------------------------------------------------------------------------------------------
-// DEV: these *should* match the perform/check gas overhead values in the contract and on the node
-const PERFORM_GAS_OVERHEAD = BigNumber.from(90000)
-const CHECK_GAS_OVERHEAD = BigNumber.from(170000)
-// -----------------------------------------------------------------------------------------------
-
-// Smart contract factories
-let linkTokenFactory: LinkTokenFactory
-let mockV3AggregatorFactory: MockV3AggregatorFactory
-let keeperRegistryFactory: KeeperRegistryFactory
-let upkeepMockFactory: UpkeepMockFactory
-let upkeepReverterFactory: UpkeepReverterFactory
-
-let personas: Personas
-
-before(async () => {
- personas = (await getUsers()).personas
-
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- )
- // need full path because there are two contracts with name MockV3Aggregator
- mockV3AggregatorFactory = (await ethers.getContractFactory(
- 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator',
- )) as unknown as MockV3AggregatorFactory
- // @ts-ignore bug in autogen file
- keeperRegistryFactory = await ethers.getContractFactory('KeeperRegistry1_1')
- upkeepMockFactory = await ethers.getContractFactory('UpkeepMock')
- upkeepReverterFactory = await ethers.getContractFactory('UpkeepReverter')
-})
-
-describe('KeeperRegistry1_1', () => {
- const linkEth = BigNumber.from(300000000)
- const gasWei = BigNumber.from(100)
- const linkDivisibility = BigNumber.from('1000000000000000000')
- const executeGas = BigNumber.from('100000')
- const paymentPremiumBase = BigNumber.from('1000000000')
- const paymentPremiumPPB = BigNumber.from('250000000')
- const flatFeeMicroLink = BigNumber.from(0)
- const blockCountPerTurn = BigNumber.from(3)
- const emptyBytes = '0x00'
- const zeroAddress = ethers.constants.AddressZero
- const extraGas = BigNumber.from('250000')
- const registryGasOverhead = BigNumber.from('80000')
- const stalenessSeconds = BigNumber.from(43820)
- const gasCeilingMultiplier = BigNumber.from(1)
- const maxCheckGas = BigNumber.from(20000000)
- const fallbackGasPrice = BigNumber.from(200)
- const fallbackLinkPrice = BigNumber.from(200000000)
-
- let owner: Signer
- let keeper1: Signer
- let keeper2: Signer
- let keeper3: Signer
- let nonkeeper: Signer
- let admin: Signer
- let payee1: Signer
- let payee2: Signer
- let payee3: Signer
-
- let linkToken: LinkToken
- let linkEthFeed: MockV3Aggregator
- let gasPriceFeed: MockV3Aggregator
- let registry: KeeperRegistry
- let mock: UpkeepMock
-
- let id: BigNumber
- let keepers: string[]
- let payees: string[]
-
- beforeEach(async () => {
- owner = personas.Default
- keeper1 = personas.Carol
- keeper2 = personas.Eddy
- keeper3 = personas.Nancy
- nonkeeper = personas.Ned
- admin = personas.Neil
- payee1 = personas.Nelly
- payee2 = personas.Norbert
- payee3 = personas.Nick
-
- keepers = [
- await keeper1.getAddress(),
- await keeper2.getAddress(),
- await keeper3.getAddress(),
- ]
- payees = [
- await payee1.getAddress(),
- await payee2.getAddress(),
- await payee3.getAddress(),
- ]
-
- linkToken = await linkTokenFactory.connect(owner).deploy()
- gasPriceFeed = await mockV3AggregatorFactory
- .connect(owner)
- .deploy(0, gasWei)
- linkEthFeed = await mockV3AggregatorFactory
- .connect(owner)
- .deploy(9, linkEth)
- registry = await keeperRegistryFactory
- .connect(owner)
- .deploy(
- linkToken.address,
- linkEthFeed.address,
- gasPriceFeed.address,
- paymentPremiumPPB,
- flatFeeMicroLink,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- gasCeilingMultiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
-
- mock = await upkeepMockFactory.deploy()
- await linkToken
- .connect(owner)
- .transfer(await keeper1.getAddress(), toWei('1000'))
- await linkToken
- .connect(owner)
- .transfer(await keeper2.getAddress(), toWei('1000'))
- await linkToken
- .connect(owner)
- .transfer(await keeper3.getAddress(), toWei('1000'))
-
- await registry.connect(owner).setKeepers(keepers, payees)
- const tx = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- id = await getUpkeepID(tx)
- })
-
- const linkForGas = (
- upkeepGasSpent: BigNumberish,
- premiumPPB?: BigNumberish,
- flatFee?: BigNumberish,
- ) => {
- premiumPPB = premiumPPB === undefined ? paymentPremiumPPB : premiumPPB
- flatFee = flatFee === undefined ? flatFeeMicroLink : flatFee
- const gasSpent = registryGasOverhead.add(BigNumber.from(upkeepGasSpent))
- const base = gasWei.mul(gasSpent).mul(linkDivisibility).div(linkEth)
- const premium = base.mul(premiumPPB).div(paymentPremiumBase)
- const flatFeeJules = BigNumber.from(flatFee).mul('1000000000000')
- return base.add(premium).add(flatFeeJules)
- }
-
- describe('#setKeepers', () => {
- const IGNORE_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'
- it('reverts when not called by the owner', async () => {
- await evmRevert(
- registry.connect(keeper1).setKeepers([], []),
- 'Only callable by owner',
- )
- })
-
- it('reverts when adding the same keeper twice', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .setKeepers(
- [await keeper1.getAddress(), await keeper1.getAddress()],
- [await payee1.getAddress(), await payee1.getAddress()],
- ),
- 'cannot add keeper twice',
- )
- })
-
- it('reverts with different numbers of keepers/payees', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .setKeepers(
- [await keeper1.getAddress(), await keeper2.getAddress()],
- [await payee1.getAddress()],
- ),
- 'address lists not the same length',
- )
- await evmRevert(
- registry
- .connect(owner)
- .setKeepers(
- [await keeper1.getAddress()],
- [await payee1.getAddress(), await payee2.getAddress()],
- ),
- 'address lists not the same length',
- )
- })
-
- it('reverts if the payee is the zero address', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .setKeepers(
- [await keeper1.getAddress(), await keeper2.getAddress()],
- [
- await payee1.getAddress(),
- '0x0000000000000000000000000000000000000000',
- ],
- ),
- 'cannot set payee to the zero address',
- )
- })
-
- it('emits events for every keeper added and removed', async () => {
- const oldKeepers = [
- await keeper1.getAddress(),
- await keeper2.getAddress(),
- ]
- const oldPayees = [await payee1.getAddress(), await payee2.getAddress()]
- await registry.connect(owner).setKeepers(oldKeepers, oldPayees)
- assert.deepEqual(oldKeepers, await registry.getKeeperList())
-
- // remove keepers
- const newKeepers = [
- await keeper2.getAddress(),
- await keeper3.getAddress(),
- ]
- const newPayees = [await payee2.getAddress(), await payee3.getAddress()]
- const tx = await registry.connect(owner).setKeepers(newKeepers, newPayees)
- assert.deepEqual(newKeepers, await registry.getKeeperList())
-
- await expect(tx)
- .to.emit(registry, 'KeepersUpdated')
- .withArgs(newKeepers, newPayees)
- })
-
- it('updates the keeper to inactive when removed', async () => {
- await registry.connect(owner).setKeepers(keepers, payees)
- await registry
- .connect(owner)
- .setKeepers(
- [await keeper1.getAddress(), await keeper3.getAddress()],
- [await payee1.getAddress(), await payee3.getAddress()],
- )
- const added = await registry.getKeeperInfo(await keeper1.getAddress())
- assert.isTrue(added.active)
- const removed = await registry.getKeeperInfo(await keeper2.getAddress())
- assert.isFalse(removed.active)
- })
-
- it('does not change the payee if IGNORE_ADDRESS is used as payee', async () => {
- const oldKeepers = [
- await keeper1.getAddress(),
- await keeper2.getAddress(),
- ]
- const oldPayees = [await payee1.getAddress(), await payee2.getAddress()]
- await registry.connect(owner).setKeepers(oldKeepers, oldPayees)
- assert.deepEqual(oldKeepers, await registry.getKeeperList())
-
- const newKeepers = [
- await keeper2.getAddress(),
- await keeper3.getAddress(),
- ]
- const newPayees = [IGNORE_ADDRESS, await payee3.getAddress()]
- const tx = await registry.connect(owner).setKeepers(newKeepers, newPayees)
- assert.deepEqual(newKeepers, await registry.getKeeperList())
-
- const ignored = await registry.getKeeperInfo(await keeper2.getAddress())
- assert.equal(await payee2.getAddress(), ignored.payee)
- assert.equal(true, ignored.active)
-
- await expect(tx)
- .to.emit(registry, 'KeepersUpdated')
- .withArgs(newKeepers, newPayees)
- })
-
- it('reverts if the owner changes the payee', async () => {
- await registry.connect(owner).setKeepers(keepers, payees)
- await evmRevert(
- registry
- .connect(owner)
- .setKeepers(keepers, [
- await payee1.getAddress(),
- await payee2.getAddress(),
- await owner.getAddress(),
- ]),
- 'cannot change payee',
- )
- })
- })
-
- describe('#registerUpkeep', () => {
- it('reverts if the target is not a contract', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .registerUpkeep(
- zeroAddress,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- ),
- 'target is not a contract',
- )
- })
-
- it('reverts if called by a non-owner', async () => {
- await evmRevert(
- registry
- .connect(keeper1)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- ),
- 'Only callable by owner or registrar',
- )
- })
-
- it('reverts if execute gas is too low', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- 2299,
- await admin.getAddress(),
- emptyBytes,
- ),
- 'min gas is 2300',
- )
- })
-
- it('reverts if execute gas is too high', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- 5000001,
- await admin.getAddress(),
- emptyBytes,
- ),
- 'max gas is 5000000',
- )
- })
-
- it('creates a record of the registration', async () => {
- const tx = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- id = await getUpkeepID(tx)
- await expect(tx)
- .to.emit(registry, 'UpkeepRegistered')
- .withArgs(id, executeGas, await admin.getAddress())
- const registration = await registry.getUpkeep(id)
- assert.equal(mock.address, registration.target)
- assert.equal(0, registration.balance.toNumber())
- assert.equal(emptyBytes, registration.checkData)
- assert(registration.maxValidBlocknumber.eq('0xffffffffffffffff'))
- })
- })
-
- describe('#addFunds', () => {
- const amount = toWei('1')
-
- beforeEach(async () => {
- await linkToken.connect(keeper1).approve(registry.address, toWei('100'))
- })
-
- it('reverts if the registration does not exist', async () => {
- await evmRevert(
- registry.connect(keeper1).addFunds(id.add(1), amount),
- 'upkeep must be active',
- )
- })
-
- it('adds to the balance of the registration', async () => {
- await registry.connect(keeper1).addFunds(id, amount)
- const registration = await registry.getUpkeep(id)
- assert.isTrue(amount.eq(registration.balance))
- })
-
- it('emits a log', async () => {
- const tx = await registry.connect(keeper1).addFunds(id, amount)
- await expect(tx)
- .to.emit(registry, 'FundsAdded')
- .withArgs(id, await keeper1.getAddress(), amount)
- })
-
- it('reverts if the upkeep is canceled', async () => {
- await registry.connect(admin).cancelUpkeep(id)
- await evmRevert(
- registry.connect(keeper1).addFunds(id, amount),
- 'upkeep must be active',
- )
- })
- })
-
- describe('#checkUpkeep', () => {
- it('reverts if the upkeep is not funded', async () => {
- await mock.setCanPerform(true)
- await mock.setCanCheck(true)
- await evmRevert(
- registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress()),
- 'insufficient funds',
- )
- })
-
- context('when the registration is funded', () => {
- beforeEach(async () => {
- await linkToken.connect(keeper1).approve(registry.address, toWei('100'))
- await registry.connect(keeper1).addFunds(id, toWei('100'))
- })
-
- it('reverts if executed', async () => {
- await mock.setCanPerform(true)
- await mock.setCanCheck(true)
- await evmRevert(
- registry.checkUpkeep(id, await keeper1.getAddress()),
- 'only for simulated backend',
- )
- })
-
- it('reverts if the specified keeper is not valid', async () => {
- await mock.setCanPerform(true)
- await mock.setCanCheck(true)
- await evmRevert(
- registry.checkUpkeep(id, await owner.getAddress()),
- 'only for simulated backend',
- )
- })
-
- context('and upkeep is not needed', () => {
- beforeEach(async () => {
- await mock.setCanCheck(false)
- })
-
- it('reverts', async () => {
- await evmRevert(
- registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress()),
- 'upkeep not needed',
- )
- })
- })
-
- context('and the upkeep check fails', () => {
- beforeEach(async () => {
- const reverter = await upkeepReverterFactory.deploy()
- const tx = await registry
- .connect(owner)
- .registerUpkeep(
- reverter.address,
- 2500000,
- await admin.getAddress(),
- emptyBytes,
- )
- id = await getUpkeepID(tx)
- await linkToken
- .connect(keeper1)
- .approve(registry.address, toWei('100'))
- await registry.connect(keeper1).addFunds(id, toWei('100'))
- })
-
- it('reverts', async () => {
- await evmRevert(
- registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress()),
- 'call to check target failed',
- )
- })
- })
-
- context('and upkeep check simulations succeeds', () => {
- beforeEach(async () => {
- await mock.setCanCheck(true)
- await mock.setCanPerform(true)
- })
-
- context('and the registry is paused', () => {
- beforeEach(async () => {
- await registry.connect(owner).pause()
- })
-
- it('reverts', async () => {
- await evmRevert(
- registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress()),
- 'Pausable: paused',
- )
-
- await registry.connect(owner).unpause()
-
- await registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress())
- })
- })
-
- it('returns true with pricing info if the target can execute', async () => {
- const newGasMultiplier = BigNumber.from(10)
- await registry
- .connect(owner)
- .setConfig(
- paymentPremiumPPB,
- flatFeeMicroLink,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- newGasMultiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
- const response = await registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress())
- assert.isTrue(response.gasLimit.eq(executeGas))
- assert.isTrue(response.linkEth.eq(linkEth))
- assert.isTrue(
- response.adjustedGasWei.eq(gasWei.mul(newGasMultiplier)),
- )
- assert.isTrue(
- response.maxLinkPayment.eq(
- linkForGas(executeGas.toNumber()).mul(newGasMultiplier),
- ),
- )
- })
-
- it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => {
- await mock.setCheckGasToBurn(maxCheckGas)
- await mock.setPerformGasToBurn(executeGas)
- const gas = maxCheckGas
- .add(executeGas)
- .add(PERFORM_GAS_OVERHEAD)
- .add(CHECK_GAS_OVERHEAD)
- await registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress(), {
- gasLimit: gas,
- })
- })
- })
- })
- })
-
- describe('#performUpkeep', () => {
- let _lastKeeper = keeper1
- async function getPerformPaymentAmount() {
- _lastKeeper = _lastKeeper === keeper1 ? keeper2 : keeper1
- const before = (
- await registry.getKeeperInfo(await _lastKeeper.getAddress())
- ).balance
- await registry.connect(_lastKeeper).performUpkeep(id, '0x')
- const after = (
- await registry.getKeeperInfo(await _lastKeeper.getAddress())
- ).balance
- const difference = after.sub(before)
- return difference
- }
-
- it('reverts if the registration is not funded', async () => {
- await evmRevert(
- registry.connect(keeper2).performUpkeep(id, '0x'),
- 'insufficient funds',
- )
- })
-
- context('when the registration is funded', () => {
- beforeEach(async () => {
- await linkToken.connect(owner).approve(registry.address, toWei('100'))
- await registry.connect(owner).addFunds(id, toWei('100'))
- })
-
- it('does not revert if the target cannot execute', async () => {
- const mockResponse = await mock
- .connect(zeroAddress)
- .callStatic.checkUpkeep('0x')
- assert.isFalse(mockResponse.callable)
-
- await registry.connect(keeper3).performUpkeep(id, '0x')
- })
-
- it('returns false if the target cannot execute', async () => {
- const mockResponse = await mock
- .connect(zeroAddress)
- .callStatic.checkUpkeep('0x')
- assert.isFalse(mockResponse.callable)
-
- assert.isFalse(
- await registry.connect(keeper1).callStatic.performUpkeep(id, '0x'),
- )
- })
-
- it('returns true if called', async () => {
- await mock.setCanPerform(true)
-
- const response = await registry
- .connect(keeper1)
- .callStatic.performUpkeep(id, '0x')
- assert.isTrue(response)
- })
-
- it('reverts if not enough gas supplied', async () => {
- await mock.setCanPerform(true)
-
- await evmRevert(
- registry
- .connect(keeper1)
- .performUpkeep(id, '0x', { gasLimit: BigNumber.from('120000') }),
- )
- })
-
- it('executes the data passed to the registry', async () => {
- await mock.setCanPerform(true)
-
- const performData = '0xc0ffeec0ffee'
- const tx = await registry
- .connect(keeper1)
- .performUpkeep(id, performData, { gasLimit: extraGas })
- const receipt = await tx.wait()
- const eventLog = receipt?.events
-
- assert.equal(eventLog?.length, 2)
- assert.equal(eventLog?.[1].event, 'UpkeepPerformed')
- assert.equal(eventLog?.[1].args?.[0].toNumber(), id.toNumber())
- assert.equal(eventLog?.[1].args?.[1], true)
- assert.equal(eventLog?.[1].args?.[2], await keeper1.getAddress())
- assert.isNotEmpty(eventLog?.[1].args?.[3])
- assert.equal(eventLog?.[1].args?.[4], performData)
- })
-
- it('updates payment balances', async () => {
- const keeperBefore = await registry.getKeeperInfo(
- await keeper1.getAddress(),
- )
- const registrationBefore = await registry.getUpkeep(id)
- const keeperLinkBefore = await linkToken.balanceOf(
- await keeper1.getAddress(),
- )
- const registryLinkBefore = await linkToken.balanceOf(registry.address)
-
- // Do the thing
- await registry.connect(keeper1).performUpkeep(id, '0x')
-
- const keeperAfter = await registry.getKeeperInfo(
- await keeper1.getAddress(),
- )
- const registrationAfter = await registry.getUpkeep(id)
- const keeperLinkAfter = await linkToken.balanceOf(
- await keeper1.getAddress(),
- )
- const registryLinkAfter = await linkToken.balanceOf(registry.address)
-
- assert.isTrue(keeperAfter.balance.gt(keeperBefore.balance))
- assert.isTrue(registrationBefore.balance.gt(registrationAfter.balance))
- assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore))
- assert.isTrue(registryLinkBefore.eq(registryLinkAfter))
- })
-
- it('only pays for gas used [ @skip-coverage ]', async () => {
- const before = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
- const tx = await registry.connect(keeper1).performUpkeep(id, '0x')
- const receipt = await tx.wait()
- const after = (await registry.getKeeperInfo(await keeper1.getAddress()))
- .balance
-
- const max = linkForGas(executeGas.toNumber())
- const totalTx = linkForGas(receipt.gasUsed.toNumber())
- const difference = after.sub(before)
- assert.isTrue(max.gt(totalTx))
- assert.isTrue(totalTx.gt(difference))
- assert.isTrue(linkForGas(5700).lt(difference)) // exact number is flaky
- assert.isTrue(linkForGas(6000).gt(difference)) // instead test a range
- })
-
- it('only pays at a rate up to the gas ceiling [ @skip-coverage ]', async () => {
- const multiplier = BigNumber.from(10)
- const gasPrice = BigNumber.from('1000000000') // 10M x the gas feed's rate
- await registry
- .connect(owner)
- .setConfig(
- paymentPremiumPPB,
- flatFeeMicroLink,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- multiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
-
- const before = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
- const tx = await registry
- .connect(keeper1)
- .performUpkeep(id, '0x', { gasPrice })
- const receipt = await tx.wait()
- const after = (await registry.getKeeperInfo(await keeper1.getAddress()))
- .balance
-
- const max = linkForGas(executeGas).mul(multiplier)
- const totalTx = linkForGas(receipt.gasUsed).mul(multiplier)
- const difference = after.sub(before)
- assert.isTrue(max.gt(totalTx))
- assert.isTrue(totalTx.gt(difference))
- assert.isTrue(linkForGas(5700).mul(multiplier).lt(difference))
- assert.isTrue(linkForGas(6000).mul(multiplier).gt(difference))
- })
-
- it('only pays as much as the node spent [ @skip-coverage ]', async () => {
- const multiplier = BigNumber.from(10)
- const gasPrice = BigNumber.from(200) // 2X the gas feed's rate
- const effectiveMultiplier = BigNumber.from(2)
- await registry
- .connect(owner)
- .setConfig(
- paymentPremiumPPB,
- flatFeeMicroLink,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- multiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
-
- const before = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
- const tx = await registry
- .connect(keeper1)
- .performUpkeep(id, '0x', { gasPrice })
- const receipt = await tx.wait()
- const after = (await registry.getKeeperInfo(await keeper1.getAddress()))
- .balance
-
- const max = linkForGas(executeGas.toNumber()).mul(effectiveMultiplier)
- const totalTx = linkForGas(receipt.gasUsed).mul(effectiveMultiplier)
- const difference = after.sub(before)
- assert.isTrue(max.gt(totalTx))
- assert.isTrue(totalTx.gt(difference))
- assert.isTrue(linkForGas(5700).mul(effectiveMultiplier).lt(difference))
- assert.isTrue(linkForGas(6000).mul(effectiveMultiplier).gt(difference))
- })
-
- it('pays the caller even if the target function fails', async () => {
- const tx = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- const id = await getUpkeepID(tx)
- await linkToken.connect(owner).approve(registry.address, toWei('100'))
- await registry.connect(owner).addFunds(id, toWei('100'))
- const keeperBalanceBefore = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
-
- // Do the thing
- await registry.connect(keeper1).performUpkeep(id, '0x')
-
- const keeperBalanceAfter = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
- assert.isTrue(keeperBalanceAfter.gt(keeperBalanceBefore))
- })
-
- it('reverts if called by a non-keeper', async () => {
- await evmRevert(
- registry.connect(nonkeeper).performUpkeep(id, '0x'),
- 'only active keepers',
- )
- })
-
- it('reverts if the upkeep has been canceled', async () => {
- await mock.setCanPerform(true)
-
- await registry.connect(owner).cancelUpkeep(id)
-
- await evmRevert(
- registry.connect(keeper1).performUpkeep(id, '0x'),
- 'invalid upkeep id',
- )
- })
-
- it('uses the fallback gas price if the feed price is stale [ @skip-coverage ]', async () => {
- const normalAmount = await getPerformPaymentAmount()
- const roundId = 99
- const answer = 100
- const updatedAt = 946684800 // New Years 2000 🥳
- const startedAt = 946684799
- await gasPriceFeed
- .connect(owner)
- .updateRoundData(roundId, answer, updatedAt, startedAt)
- const amountWithStaleFeed = await getPerformPaymentAmount()
- assert.isTrue(normalAmount.lt(amountWithStaleFeed))
- })
-
- it('uses the fallback gas price if the feed price is non-sensical [ @skip-coverage ]', async () => {
- const normalAmount = await getPerformPaymentAmount()
- const roundId = 99
- const updatedAt = Math.floor(Date.now() / 1000)
- const startedAt = 946684799
- await gasPriceFeed
- .connect(owner)
- .updateRoundData(roundId, -100, updatedAt, startedAt)
- const amountWithNegativeFeed = await getPerformPaymentAmount()
- await gasPriceFeed
- .connect(owner)
- .updateRoundData(roundId, 0, updatedAt, startedAt)
- const amountWithZeroFeed = await getPerformPaymentAmount()
- assert.isTrue(normalAmount.lt(amountWithNegativeFeed))
- assert.isTrue(normalAmount.lt(amountWithZeroFeed))
- })
-
- it('uses the fallback if the link price feed is stale', async () => {
- const normalAmount = await getPerformPaymentAmount()
- const roundId = 99
- const answer = 100
- const updatedAt = 946684800 // New Years 2000 🥳
- const startedAt = 946684799
- await linkEthFeed
- .connect(owner)
- .updateRoundData(roundId, answer, updatedAt, startedAt)
- const amountWithStaleFeed = await getPerformPaymentAmount()
- assert.isTrue(normalAmount.lt(amountWithStaleFeed))
- })
-
- it('uses the fallback link price if the feed price is non-sensical', async () => {
- const normalAmount = await getPerformPaymentAmount()
- const roundId = 99
- const updatedAt = Math.floor(Date.now() / 1000)
- const startedAt = 946684799
- await linkEthFeed
- .connect(owner)
- .updateRoundData(roundId, -100, updatedAt, startedAt)
- const amountWithNegativeFeed = await getPerformPaymentAmount()
- await linkEthFeed
- .connect(owner)
- .updateRoundData(roundId, 0, updatedAt, startedAt)
- const amountWithZeroFeed = await getPerformPaymentAmount()
- assert.isTrue(normalAmount.lt(amountWithNegativeFeed))
- assert.isTrue(normalAmount.lt(amountWithZeroFeed))
- })
-
- it('reverts if the same caller calls twice in a row', async () => {
- await registry.connect(keeper1).performUpkeep(id, '0x')
- await evmRevert(
- registry.connect(keeper1).performUpkeep(id, '0x'),
- 'keepers must take turns',
- )
- await registry.connect(keeper2).performUpkeep(id, '0x')
- await evmRevert(
- registry.connect(keeper2).performUpkeep(id, '0x'),
- 'keepers must take turns',
- )
- await registry.connect(keeper1).performUpkeep(id, '0x')
- })
-
- it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => {
- await mock.setPerformGasToBurn(executeGas)
- await mock.setCanPerform(true)
- const gas = executeGas.add(PERFORM_GAS_OVERHEAD)
- const performData = '0xc0ffeec0ffee'
- const tx = await registry
- .connect(keeper1)
- .performUpkeep(id, performData, { gasLimit: gas })
- const receipt = await tx.wait()
- const eventLog = receipt?.events
-
- assert.equal(eventLog?.length, 2)
- assert.equal(eventLog?.[1].event, 'UpkeepPerformed')
- assert.equal(eventLog?.[1].args?.[0].toNumber(), id.toNumber())
- assert.equal(eventLog?.[1].args?.[1], true)
- assert.equal(eventLog?.[1].args?.[2], await keeper1.getAddress())
- assert.isNotEmpty(eventLog?.[1].args?.[3])
- assert.equal(eventLog?.[1].args?.[4], performData)
- })
- })
- })
-
- describe('#withdrawFunds', () => {
- beforeEach(async () => {
- await linkToken.connect(keeper1).approve(registry.address, toWei('100'))
- await registry.connect(keeper1).addFunds(id, toWei('1'))
- })
-
- it('reverts if called by anyone but the admin', async () => {
- await evmRevert(
- registry
- .connect(owner)
- .withdrawFunds(id.add(1).toNumber(), await payee1.getAddress()),
- 'only callable by admin',
- )
- })
-
- it('reverts if called on an uncanceled upkeep', async () => {
- await evmRevert(
- registry.connect(admin).withdrawFunds(id, await payee1.getAddress()),
- 'upkeep must be canceled',
- )
- })
-
- it('reverts if called with the 0 address', async () => {
- await evmRevert(
- registry.connect(admin).withdrawFunds(id, zeroAddress),
- 'cannot send to zero address',
- )
- })
-
- describe('after the registration is cancelled', () => {
- beforeEach(async () => {
- await registry.connect(owner).cancelUpkeep(id)
- })
-
- it('moves the funds out and updates the balance', async () => {
- const payee1Before = await linkToken.balanceOf(
- await payee1.getAddress(),
- )
- const registryBefore = await linkToken.balanceOf(registry.address)
-
- let registration = await registry.getUpkeep(id)
- assert.isTrue(toWei('1').eq(registration.balance))
-
- await registry
- .connect(admin)
- .withdrawFunds(id, await payee1.getAddress())
-
- const payee1After = await linkToken.balanceOf(await payee1.getAddress())
- const registryAfter = await linkToken.balanceOf(registry.address)
-
- assert.isTrue(payee1Before.add(toWei('1')).eq(payee1After))
- assert.isTrue(registryBefore.sub(toWei('1')).eq(registryAfter))
-
- registration = await registry.getUpkeep(id)
- assert.equal(0, registration.balance.toNumber())
- })
- })
- })
-
- describe('#cancelUpkeep', () => {
- it('reverts if the ID is not valid', async () => {
- await evmRevert(
- registry.connect(owner).cancelUpkeep(id.add(1).toNumber()),
- 'too late to cancel upkeep',
- )
- })
-
- it('reverts if called by a non-owner/non-admin', async () => {
- await evmRevert(
- registry.connect(keeper1).cancelUpkeep(id),
- 'only owner or admin',
- )
- })
-
- describe('when called by the owner', async () => {
- it('sets the registration to invalid immediately', async () => {
- const tx = await registry.connect(owner).cancelUpkeep(id)
- const receipt = await tx.wait()
- const registration = await registry.getUpkeep(id)
- assert.equal(
- registration.maxValidBlocknumber.toNumber(),
- receipt.blockNumber,
- )
- })
-
- it('emits an event', async () => {
- const tx = await registry.connect(owner).cancelUpkeep(id)
- const receipt = await tx.wait()
- await expect(tx)
- .to.emit(registry, 'UpkeepCanceled')
- .withArgs(id, BigNumber.from(receipt.blockNumber))
- })
-
- it('updates the canceled registrations list', async () => {
- let canceled = await registry.callStatic.getCanceledUpkeepList()
- assert.deepEqual([], canceled)
-
- await registry.connect(owner).cancelUpkeep(id)
-
- canceled = await registry.callStatic.getCanceledUpkeepList()
- assert.deepEqual([id], canceled)
- })
-
- it('immediately prevents upkeep', async () => {
- await registry.connect(owner).cancelUpkeep(id)
-
- await evmRevert(
- registry.connect(keeper2).performUpkeep(id, '0x'),
- 'invalid upkeep id',
- )
- })
-
- it('does not revert if reverts if called multiple times', async () => {
- await registry.connect(owner).cancelUpkeep(id)
- await evmRevert(
- registry.connect(owner).cancelUpkeep(id),
- 'too late to cancel upkeep',
- )
- })
-
- describe('when called by the owner when the admin has just canceled', () => {
- let oldExpiration: BigNumber
-
- beforeEach(async () => {
- await registry.connect(admin).cancelUpkeep(id)
- const registration = await registry.getUpkeep(id)
- oldExpiration = registration.maxValidBlocknumber
- })
-
- it('allows the owner to cancel it more quickly', async () => {
- await registry.connect(owner).cancelUpkeep(id)
-
- const registration = await registry.getUpkeep(id)
- const newExpiration = registration.maxValidBlocknumber
- assert.isTrue(newExpiration.lt(oldExpiration))
- })
- })
- })
-
- describe('when called by the admin', async () => {
- const delay = 50
-
- it('sets the registration to invalid in 50 blocks', async () => {
- const tx = await registry.connect(admin).cancelUpkeep(id)
- const receipt = await tx.wait()
- const registration = await registry.getUpkeep(id)
- assert.equal(
- registration.maxValidBlocknumber.toNumber(),
- receipt.blockNumber + 50,
- )
- })
-
- it('emits an event', async () => {
- const tx = await registry.connect(admin).cancelUpkeep(id)
- const receipt = await tx.wait()
- await expect(tx)
- .to.emit(registry, 'UpkeepCanceled')
- .withArgs(id, BigNumber.from(receipt.blockNumber + delay))
- })
-
- it('updates the canceled registrations list', async () => {
- let canceled = await registry.callStatic.getCanceledUpkeepList()
- assert.deepEqual([], canceled)
-
- await registry.connect(admin).cancelUpkeep(id)
-
- canceled = await registry.callStatic.getCanceledUpkeepList()
- assert.deepEqual([id], canceled)
- })
-
- it('immediately prevents upkeep', async () => {
- await linkToken.connect(owner).approve(registry.address, toWei('100'))
- await registry.connect(owner).addFunds(id, toWei('100'))
- await registry.connect(admin).cancelUpkeep(id)
- await registry.connect(keeper2).performUpkeep(id, '0x') // still works
-
- for (let i = 0; i < delay; i++) {
- await ethers.provider.send('evm_mine', [])
- }
-
- await evmRevert(
- registry.connect(keeper2).performUpkeep(id, '0x'),
- 'invalid upkeep id',
- )
- })
-
- it('reverts if called again by the admin', async () => {
- await registry.connect(admin).cancelUpkeep(id)
-
- await evmRevert(
- registry.connect(admin).cancelUpkeep(id),
- 'too late to cancel upkeep',
- )
- })
-
- it('does not revert or double add the cancellation record if called by the owner immediately after', async () => {
- await registry.connect(admin).cancelUpkeep(id)
-
- await registry.connect(owner).cancelUpkeep(id)
-
- const canceled = await registry.callStatic.getCanceledUpkeepList()
- assert.deepEqual([id], canceled)
- })
-
- it('reverts if called by the owner after the timeout', async () => {
- await registry.connect(admin).cancelUpkeep(id)
-
- for (let i = 0; i < delay; i++) {
- await ethers.provider.send('evm_mine', [])
- }
-
- await evmRevert(
- registry.connect(owner).cancelUpkeep(id),
- 'too late to cancel upkeep',
- )
- })
- })
- })
-
- describe('#withdrawPayment', () => {
- beforeEach(async () => {
- await linkToken.connect(owner).approve(registry.address, toWei('100'))
- await registry.connect(owner).addFunds(id, toWei('100'))
- await registry.connect(keeper1).performUpkeep(id, '0x')
- })
-
- it('reverts if called by anyone but the payee', async () => {
- await evmRevert(
- registry
- .connect(payee2)
- .withdrawPayment(
- await keeper1.getAddress(),
- await nonkeeper.getAddress(),
- ),
- 'only callable by payee',
- )
- })
-
- it('reverts if called with the 0 address', async () => {
- await evmRevert(
- registry
- .connect(payee2)
- .withdrawPayment(await keeper1.getAddress(), zeroAddress),
- 'cannot send to zero address',
- )
- })
-
- it('updates the balances', async () => {
- const to = await nonkeeper.getAddress()
- const keeperBefore = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
- const registrationBefore = (await registry.getUpkeep(id)).balance
- const toLinkBefore = await linkToken.balanceOf(to)
- const registryLinkBefore = await linkToken.balanceOf(registry.address)
-
- //// Do the thing
- await registry
- .connect(payee1)
- .withdrawPayment(await keeper1.getAddress(), to)
-
- const keeperAfter = (
- await registry.getKeeperInfo(await keeper1.getAddress())
- ).balance
- const registrationAfter = (await registry.getUpkeep(id)).balance
- const toLinkAfter = await linkToken.balanceOf(to)
- const registryLinkAfter = await linkToken.balanceOf(registry.address)
-
- assert.isTrue(keeperAfter.eq(BigNumber.from(0)))
- assert.isTrue(registrationBefore.eq(registrationAfter))
- assert.isTrue(toLinkBefore.add(keeperBefore).eq(toLinkAfter))
- assert.isTrue(registryLinkBefore.sub(keeperBefore).eq(registryLinkAfter))
- })
-
- it('emits a log announcing the withdrawal', async () => {
- const balance = (await registry.getKeeperInfo(await keeper1.getAddress()))
- .balance
- const tx = await registry
- .connect(payee1)
- .withdrawPayment(
- await keeper1.getAddress(),
- await nonkeeper.getAddress(),
- )
- await expect(tx)
- .to.emit(registry, 'PaymentWithdrawn')
- .withArgs(
- await keeper1.getAddress(),
- balance,
- await nonkeeper.getAddress(),
- await payee1.getAddress(),
- )
- })
- })
-
- describe('#transferPayeeship', () => {
- it('reverts when called by anyone but the current payee', async () => {
- await evmRevert(
- registry
- .connect(payee2)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee2.getAddress(),
- ),
- 'only callable by payee',
- )
- })
-
- it('reverts when transferring to self', async () => {
- await evmRevert(
- registry
- .connect(payee1)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee1.getAddress(),
- ),
- 'cannot transfer to self',
- )
- })
-
- it('does not change the payee', async () => {
- await registry
- .connect(payee1)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee2.getAddress(),
- )
-
- const info = await registry.getKeeperInfo(await keeper1.getAddress())
- assert.equal(await payee1.getAddress(), info.payee)
- })
-
- it('emits an event announcing the new payee', async () => {
- const tx = await registry
- .connect(payee1)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee2.getAddress(),
- )
- await expect(tx)
- .to.emit(registry, 'PayeeshipTransferRequested')
- .withArgs(
- await keeper1.getAddress(),
- await payee1.getAddress(),
- await payee2.getAddress(),
- )
- })
-
- it('does not emit an event when called with the same proposal', async () => {
- await registry
- .connect(payee1)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee2.getAddress(),
- )
-
- const tx = await registry
- .connect(payee1)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee2.getAddress(),
- )
- const receipt = await tx.wait()
- assert.equal(0, receipt.logs.length)
- })
- })
-
- describe('#acceptPayeeship', () => {
- beforeEach(async () => {
- await registry
- .connect(payee1)
- .transferPayeeship(
- await keeper1.getAddress(),
- await payee2.getAddress(),
- )
- })
-
- it('reverts when called by anyone but the proposed payee', async () => {
- await evmRevert(
- registry.connect(payee1).acceptPayeeship(await keeper1.getAddress()),
- 'only callable by proposed payee',
- )
- })
-
- it('emits an event announcing the new payee', async () => {
- const tx = await registry
- .connect(payee2)
- .acceptPayeeship(await keeper1.getAddress())
- await expect(tx)
- .to.emit(registry, 'PayeeshipTransferred')
- .withArgs(
- await keeper1.getAddress(),
- await payee1.getAddress(),
- await payee2.getAddress(),
- )
- })
-
- it('does change the payee', async () => {
- await registry.connect(payee2).acceptPayeeship(await keeper1.getAddress())
-
- const info = await registry.getKeeperInfo(await keeper1.getAddress())
- assert.equal(await payee2.getAddress(), info.payee)
- })
- })
-
- describe('#setConfig', () => {
- const payment = BigNumber.from(1)
- const flatFee = BigNumber.from(2)
- const checks = BigNumber.from(3)
- const staleness = BigNumber.from(4)
- const ceiling = BigNumber.from(5)
- const maxGas = BigNumber.from(6)
- const fbGasEth = BigNumber.from(7)
- const fbLinkEth = BigNumber.from(8)
-
- it('reverts when called by anyone but the proposed owner', async () => {
- await evmRevert(
- registry
- .connect(payee1)
- .setConfig(
- payment,
- flatFee,
- checks,
- maxGas,
- staleness,
- gasCeilingMultiplier,
- fbGasEth,
- fbLinkEth,
- ),
- 'Only callable by owner',
- )
- })
-
- it('updates the config', async () => {
- const old = await registry.getConfig()
- const oldFlatFee = await registry.getFlatFee()
- assert.isTrue(paymentPremiumPPB.eq(old.paymentPremiumPPB))
- assert.isTrue(flatFeeMicroLink.eq(oldFlatFee))
- assert.isTrue(blockCountPerTurn.eq(old.blockCountPerTurn))
- assert.isTrue(stalenessSeconds.eq(old.stalenessSeconds))
- assert.isTrue(gasCeilingMultiplier.eq(old.gasCeilingMultiplier))
-
- await registry
- .connect(owner)
- .setConfig(
- payment,
- flatFee,
- checks,
- maxGas,
- staleness,
- ceiling,
- fbGasEth,
- fbLinkEth,
- )
-
- const updated = await registry.getConfig()
- const newFlatFee = await registry.getFlatFee()
- assert.equal(updated.paymentPremiumPPB, payment.toNumber())
- assert.equal(newFlatFee, flatFee.toNumber())
- assert.equal(updated.blockCountPerTurn, checks.toNumber())
- assert.equal(updated.stalenessSeconds, staleness.toNumber())
- assert.equal(updated.gasCeilingMultiplier, ceiling.toNumber())
- assert.equal(updated.checkGasLimit, maxGas.toNumber())
- assert.equal(updated.fallbackGasPrice.toNumber(), fbGasEth.toNumber())
- assert.equal(updated.fallbackLinkPrice.toNumber(), fbLinkEth.toNumber())
- })
-
- it('emits an event', async () => {
- const tx = await registry
- .connect(owner)
- .setConfig(
- payment,
- flatFee,
- checks,
- maxGas,
- staleness,
- ceiling,
- fbGasEth,
- fbLinkEth,
- )
- await expect(tx)
- .to.emit(registry, 'ConfigSet')
- .withArgs(
- payment,
- checks,
- maxGas,
- staleness,
- ceiling,
- fbGasEth,
- fbLinkEth,
- )
- })
- })
-
- describe('#onTokenTransfer', () => {
- const amount = toWei('1')
-
- it('reverts if not called by the LINK token', async () => {
- const data = ethers.utils.defaultAbiCoder.encode(
- ['uint256'],
- [id.toNumber().toString()],
- )
-
- await evmRevert(
- registry
- .connect(keeper1)
- .onTokenTransfer(await keeper1.getAddress(), amount, data),
- 'only callable through LINK',
- )
- })
-
- it('reverts if not called with more or less than 32 bytes', async () => {
- const longData = ethers.utils.defaultAbiCoder.encode(
- ['uint256', 'uint256'],
- ['33', '34'],
- )
- const shortData = '0x12345678'
-
- await evmRevert(
- linkToken
- .connect(owner)
- .transferAndCall(registry.address, amount, longData),
- )
- await evmRevert(
- linkToken
- .connect(owner)
- .transferAndCall(registry.address, amount, shortData),
- )
- })
-
- it('reverts if the upkeep is canceled', async () => {
- await registry.connect(admin).cancelUpkeep(id)
- await evmRevert(
- registry.connect(keeper1).addFunds(id, amount),
- 'upkeep must be active',
- )
- })
-
- it('updates the funds of the job id passed', async () => {
- const data = ethers.utils.defaultAbiCoder.encode(
- ['uint256'],
- [id.toNumber().toString()],
- )
-
- const before = (await registry.getUpkeep(id)).balance
- await linkToken
- .connect(owner)
- .transferAndCall(registry.address, amount, data)
- const after = (await registry.getUpkeep(id)).balance
-
- assert.isTrue(before.add(amount).eq(after))
- })
- })
-
- describe('#recoverFunds', () => {
- const sent = toWei('7')
-
- beforeEach(async () => {
- await linkToken.connect(keeper1).approve(registry.address, toWei('100'))
-
- // add funds to upkeep 1 and perform and withdraw some payment
- const tx = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- const id1 = await getUpkeepID(tx)
- await registry.connect(keeper1).addFunds(id1, toWei('5'))
- await registry.connect(keeper1).performUpkeep(id1, '0x')
- await registry.connect(keeper2).performUpkeep(id1, '0x')
- await registry.connect(keeper3).performUpkeep(id1, '0x')
- await registry
- .connect(payee1)
- .withdrawPayment(
- await keeper1.getAddress(),
- await nonkeeper.getAddress(),
- )
-
- // transfer funds directly to the registry
- await linkToken.connect(keeper1).transfer(registry.address, sent)
-
- // add funds to upkeep 2 and perform and withdraw some payment
- const tx2 = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- const id2 = await getUpkeepID(tx2)
- await registry.connect(keeper1).addFunds(id2, toWei('5'))
- await registry.connect(keeper1).performUpkeep(id2, '0x')
- await registry.connect(keeper2).performUpkeep(id2, '0x')
- await registry.connect(keeper3).performUpkeep(id2, '0x')
- await registry
- .connect(payee2)
- .withdrawPayment(
- await keeper2.getAddress(),
- await nonkeeper.getAddress(),
- )
-
- // transfer funds using onTokenTransfer
- const data = ethers.utils.defaultAbiCoder.encode(
- ['uint256'],
- [id2.toNumber().toString()],
- )
- await linkToken
- .connect(owner)
- .transferAndCall(registry.address, toWei('1'), data)
-
- // remove a keeper
- await registry
- .connect(owner)
- .setKeepers(
- [await keeper1.getAddress(), await keeper2.getAddress()],
- [await payee1.getAddress(), await payee2.getAddress()],
- )
-
- // withdraw some funds
- await registry.connect(owner).cancelUpkeep(id1)
- await registry.connect(admin).withdrawFunds(id1, await admin.getAddress())
- })
-
- it('reverts if not called by owner', async () => {
- await evmRevert(
- registry.connect(keeper1).recoverFunds(),
- 'Only callable by owner',
- )
- })
-
- it('allows any funds that have been accidentally transfered to be moved', async () => {
- const balanceBefore = await linkToken.balanceOf(registry.address)
-
- await linkToken.balanceOf(registry.address)
-
- await registry.connect(owner).recoverFunds()
- const balanceAfter = await linkToken.balanceOf(registry.address)
- assert.isTrue(balanceBefore.eq(balanceAfter.add(sent)))
- })
- })
-
- describe('#pause', () => {
- it('reverts if called by a non-owner', async () => {
- await evmRevert(
- registry.connect(keeper1).pause(),
- 'Only callable by owner',
- )
- })
-
- it('marks the contract as paused', async () => {
- assert.isFalse(await registry.paused())
-
- await registry.connect(owner).pause()
-
- assert.isTrue(await registry.paused())
- })
- })
-
- describe('#unpause', () => {
- beforeEach(async () => {
- await registry.connect(owner).pause()
- })
-
- it('reverts if called by a non-owner', async () => {
- await evmRevert(
- registry.connect(keeper1).unpause(),
- 'Only callable by owner',
- )
- })
-
- it('marks the contract as not paused', async () => {
- assert.isTrue(await registry.paused())
-
- await registry.connect(owner).unpause()
-
- assert.isFalse(await registry.paused())
- })
- })
-
- describe('#getMaxPaymentForGas', () => {
- const gasAmounts = [100000, 10000000]
- const premiums = [0, 250000000]
- const flatFees = [0, 1000000]
- it('calculates the max fee approptiately', async () => {
- for (let idx = 0; idx < gasAmounts.length; idx++) {
- const gas = gasAmounts[idx]
- for (let jdx = 0; jdx < premiums.length; jdx++) {
- const premium = premiums[jdx]
- for (let kdx = 0; kdx < flatFees.length; kdx++) {
- const flatFee = flatFees[kdx]
- await registry
- .connect(owner)
- .setConfig(
- premium,
- flatFee,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- gasCeilingMultiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
- const price = await registry.getMaxPaymentForGas(gas)
- expect(price).to.equal(linkForGas(gas, premium, flatFee))
- }
- }
- }
- })
- })
-
- describe('#checkUpkeep / #performUpkeep', () => {
- const performData = '0xc0ffeec0ffee'
- const multiplier = BigNumber.from(10)
- const flatFee = BigNumber.from('100000') //0.1 LINK
- const callGasPrice = 1
-
- it('uses the same minimum balance calculation [ @skip-coverage ]', async () => {
- await registry
- .connect(owner)
- .setConfig(
- paymentPremiumPPB,
- flatFee,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- multiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
- await linkToken.connect(owner).approve(registry.address, toWei('100'))
-
- const tx1 = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- const upkeepID1 = await getUpkeepID(tx1)
- const tx2 = await registry
- .connect(owner)
- .registerUpkeep(
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- )
- const upkeepID2 = await getUpkeepID(tx2)
- await mock.setCanCheck(true)
- await mock.setCanPerform(true)
- // upkeep 1 is underfunded, 2 is funded
- const minBalance1 = (await registry.getMaxPaymentForGas(executeGas)).sub(
- 1,
- )
- const minBalance2 = await registry.getMaxPaymentForGas(executeGas)
- await registry.connect(owner).addFunds(upkeepID1, minBalance1)
- await registry.connect(owner).addFunds(upkeepID2, minBalance2)
- // upkeep 1 check should revert, 2 should succeed
- await evmRevert(
- registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(upkeepID1, await keeper1.getAddress(), {
- gasPrice: callGasPrice,
- }),
- )
- await registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(upkeepID2, await keeper1.getAddress(), {
- gasPrice: callGasPrice,
- })
- // upkeep 1 perform should revert, 2 should succeed
- await evmRevert(
- registry
- .connect(keeper1)
- .performUpkeep(upkeepID1, performData, { gasLimit: extraGas }),
- 'insufficient funds',
- )
- await registry
- .connect(keeper1)
- .performUpkeep(upkeepID2, performData, { gasLimit: extraGas })
- })
- })
-
- describe('#getMinBalanceForUpkeep / #checkUpkeep', () => {
- it('calculates the minimum balance appropriately', async () => {
- const oneWei = BigNumber.from('1')
- await linkToken.connect(keeper1).approve(registry.address, toWei('100'))
- await mock.setCanCheck(true)
- await mock.setCanPerform(true)
- const minBalance = await registry.getMinBalanceForUpkeep(id)
- const tooLow = minBalance.sub(oneWei)
- await registry.connect(keeper1).addFunds(id, tooLow)
- await evmRevert(
- registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress()),
- 'insufficient funds',
- )
- await registry.connect(keeper1).addFunds(id, oneWei)
- await registry
- .connect(zeroAddress)
- .callStatic.checkUpkeep(id, await keeper1.getAddress())
- })
- })
-})
diff --git a/contracts/test/v0.7/Operator.test.ts b/contracts/test/v0.7/Operator.test.ts
deleted file mode 100644
index 4af846576b..0000000000
--- a/contracts/test/v0.7/Operator.test.ts
+++ /dev/null
@@ -1,3819 +0,0 @@
-import { ethers } from 'hardhat'
-import {
- publicAbi,
- toBytes32String,
- toWei,
- stringToBytes,
- increaseTime5Minutes,
- getLog,
-} from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import {
- BigNumber,
- constants,
- Contract,
- ContractFactory,
- ContractReceipt,
- ContractTransaction,
- Signer,
-} from 'ethers'
-import { getUsers, Roles } from '../test-helpers/setup'
-import { bigNumEquals, evmRevert } from '../test-helpers/matchers'
-import type { providers } from 'ethers'
-import {
- convertCancelParams,
- convertCancelByRequesterParams,
- convertFufillParams,
- convertFulfill2Params,
- decodeRunRequest,
- encodeOracleRequest,
- encodeRequestOracleData,
- RunRequest,
-} from '../test-helpers/oracle'
-
-let v7ConsumerFactory: ContractFactory
-let basicConsumerFactory: ContractFactory
-let multiWordConsumerFactory: ContractFactory
-let gasGuzzlingConsumerFactory: ContractFactory
-let getterSetterFactory: ContractFactory
-let maliciousRequesterFactory: ContractFactory
-let maliciousConsumerFactory: ContractFactory
-let maliciousMultiWordConsumerFactory: ContractFactory
-let operatorFactory: ContractFactory
-let forwarderFactory: ContractFactory
-let linkTokenFactory: ContractFactory
-const zeroAddress = ethers.constants.AddressZero
-
-let roles: Roles
-
-before(async () => {
- const users = await getUsers()
-
- roles = users.roles
- v7ConsumerFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/Consumer.sol:Consumer',
- )
- basicConsumerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/BasicConsumer.sol:BasicConsumer',
- )
- multiWordConsumerFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MultiWordConsumer.sol:MultiWordConsumer',
- )
- gasGuzzlingConsumerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/GasGuzzlingConsumer.sol:GasGuzzlingConsumer',
- )
- getterSetterFactory = await ethers.getContractFactory(
- 'src/v0.4/tests/GetterSetter.sol:GetterSetter',
- )
- maliciousRequesterFactory = await ethers.getContractFactory(
- 'src/v0.4/tests/MaliciousRequester.sol:MaliciousRequester',
- )
- maliciousConsumerFactory = await ethers.getContractFactory(
- 'src/v0.4/tests/MaliciousConsumer.sol:MaliciousConsumer',
- )
- maliciousMultiWordConsumerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer',
- )
- operatorFactory = await ethers.getContractFactory(
- 'src/v0.7/Operator.sol:Operator',
- )
- forwarderFactory = await ethers.getContractFactory(
- 'src/v0.7/AuthorizedForwarder.sol:AuthorizedForwarder',
- )
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- )
-})
-
-describe('Operator', () => {
- let fHash: string
- let specId: string
- let to: string
- let link: Contract
- let operator: Contract
- let forwarder1: Contract
- let forwarder2: Contract
- let owner: Signer
-
- beforeEach(async () => {
- fHash = getterSetterFactory.interface.getSighash('requestedBytes32')
- specId =
- '0x4c7b7ffb66b344fbaa64995af81e355a00000000000000000000000000000000'
- to = '0x80e29acb842498fe6591f020bd82766dce619d43'
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- owner = roles.defaultAccount
- operator = await operatorFactory
- .connect(owner)
- .deploy(link.address, await owner.getAddress())
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.oracleNode.getAddress()])
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(operator, [
- 'acceptAuthorizedReceivers',
- 'acceptOwnableContracts',
- 'cancelOracleRequest',
- 'cancelOracleRequestByRequester',
- 'distributeFunds',
- 'fulfillOracleRequest',
- 'fulfillOracleRequest2',
- 'getAuthorizedSenders',
- 'getChainlinkToken',
- 'getExpiryTime',
- 'isAuthorizedSender',
- 'onTokenTransfer',
- 'operatorRequest',
- 'oracleRequest',
- 'ownerForward',
- 'ownerTransferAndCall',
- 'setAuthorizedSenders',
- 'setAuthorizedSendersOn',
- 'transferOwnableContracts',
- 'typeAndVersion',
- 'withdraw',
- 'withdrawable',
- // Ownable methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#typeAndVersion', () => {
- it('describes the operator', async () => {
- assert.equal(await operator.typeAndVersion(), 'Operator 1.0.0')
- })
- })
-
- describe('#transferOwnableContracts', () => {
- beforeEach(async () => {
- forwarder1 = await forwarderFactory
- .connect(owner)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- forwarder2 = await forwarderFactory
- .connect(owner)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- })
-
- describe('being called by the owner', () => {
- it('cannot transfer to self', async () => {
- await evmRevert(
- operator
- .connect(owner)
- .transferOwnableContracts([forwarder1.address], operator.address),
- 'Cannot transfer to self',
- )
- })
-
- it('emits an ownership transfer request event', async () => {
- const tx = await operator
- .connect(owner)
- .transferOwnableContracts(
- [forwarder1.address, forwarder2.address],
- await roles.oracleNode1.getAddress(),
- )
- const receipt = await tx.wait()
- assert.equal(receipt?.events?.length, 2)
- const log1 = receipt?.events?.[0]
- assert.equal(log1?.event, 'OwnershipTransferRequested')
- assert.equal(log1?.address, forwarder1.address)
- assert.equal(log1?.args?.[0], operator.address)
- assert.equal(log1?.args?.[1], await roles.oracleNode1.getAddress())
- const log2 = receipt?.events?.[1]
- assert.equal(log2?.event, 'OwnershipTransferRequested')
- assert.equal(log2?.address, forwarder2.address)
- assert.equal(log2?.args?.[0], operator.address)
- assert.equal(log2?.args?.[1], await roles.oracleNode1.getAddress())
- })
- })
-
- describe('being called by a non-owner', () => {
- it('reverts with message', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .transferOwnableContracts(
- [forwarder1.address],
- await roles.oracleNode2.getAddress(),
- ),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('#acceptOwnableContracts', () => {
- describe('being called by the owner', () => {
- let operator2: Contract
- let receipt: ContractReceipt
-
- beforeEach(async () => {
- operator2 = await operatorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, await roles.defaultAccount.getAddress())
- forwarder1 = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- forwarder2 = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- await operator
- .connect(roles.defaultAccount)
- .transferOwnableContracts(
- [forwarder1.address, forwarder2.address],
- operator2.address,
- )
- const tx = await operator2
- .connect(roles.defaultAccount)
- .acceptOwnableContracts([forwarder1.address, forwarder2.address])
- receipt = await tx.wait()
- })
-
- it('sets the new owner on the forwarder', async () => {
- assert.equal(await forwarder1.owner(), operator2.address)
- })
-
- it('emits ownership transferred events', async () => {
- assert.equal(receipt?.events?.[0]?.event, 'OwnableContractAccepted')
- assert.equal(receipt?.events?.[0]?.args?.[0], forwarder1.address)
-
- assert.equal(receipt?.events?.[1]?.event, 'OwnershipTransferred')
- assert.equal(receipt?.events?.[1]?.address, forwarder1.address)
- assert.equal(receipt?.events?.[1]?.args?.[0], operator.address)
- assert.equal(receipt?.events?.[1]?.args?.[1], operator2.address)
-
- assert.equal(receipt?.events?.[2]?.event, 'OwnableContractAccepted')
- assert.equal(receipt?.events?.[2]?.args?.[0], forwarder2.address)
-
- assert.equal(receipt?.events?.[3]?.event, 'OwnershipTransferred')
- assert.equal(receipt?.events?.[3]?.address, forwarder2.address)
- assert.equal(receipt?.events?.[3]?.args?.[0], operator.address)
- assert.equal(receipt?.events?.[3]?.args?.[1], operator2.address)
- })
- })
-
- describe('being called by a non-owner authorized sender', () => {
- it('does not revert', async () => {
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.oracleNode1.getAddress()])
-
- await operator.connect(roles.oracleNode1).acceptOwnableContracts([])
- })
- })
-
- describe('being called by a non owner', () => {
- it('reverts with message', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .acceptOwnableContracts([await roles.oracleNode2.getAddress()]),
- 'Cannot set authorized senders',
- )
- })
- })
- })
-
- describe('#distributeFunds', () => {
- describe('when called with empty arrays', () => {
- it('reverts with invalid array message', async () => {
- await evmRevert(
- operator.connect(roles.defaultAccount).distributeFunds([], []),
- 'Invalid array length(s)',
- )
- })
- })
-
- describe('when called with unequal array lengths', () => {
- it('reverts with invalid array message', async () => {
- const receivers = [
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
- const amounts = [1, 2, 3]
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .distributeFunds(receivers, amounts),
- 'Invalid array length(s)',
- )
- })
- })
-
- describe('when called with not enough ETH', () => {
- it('reverts with subtraction overflow message', async () => {
- const amountToSend = toWei('2')
- const ethSent = toWei('1')
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .distributeFunds(
- [await roles.oracleNode2.getAddress()],
- [amountToSend],
- {
- value: ethSent,
- },
- ),
- 'SafeMath: subtraction overflow',
- )
- })
- })
-
- describe('when called with too much ETH', () => {
- it('reverts with too much ETH message', async () => {
- const amountToSend = toWei('2')
- const ethSent = toWei('3')
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .distributeFunds(
- [await roles.oracleNode2.getAddress()],
- [amountToSend],
- {
- value: ethSent,
- },
- ),
- 'Too much ETH sent',
- )
- })
- })
-
- describe('when called with correct values', () => {
- it('updates the balances', async () => {
- const node2BalanceBefore = await roles.oracleNode2.getBalance()
- const node3BalanceBefore = await roles.oracleNode3.getBalance()
- const receivers = [
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
- const sendNode2 = toWei('2')
- const sendNode3 = toWei('3')
- const totalAmount = toWei('5')
- const amounts = [sendNode2, sendNode3]
-
- await operator
- .connect(roles.defaultAccount)
- .distributeFunds(receivers, amounts, { value: totalAmount })
-
- const node2BalanceAfter = await roles.oracleNode2.getBalance()
- const node3BalanceAfter = await roles.oracleNode3.getBalance()
-
- assert.equal(
- node2BalanceAfter.sub(node2BalanceBefore).toString(),
- sendNode2.toString(),
- )
-
- assert.equal(
- node3BalanceAfter.sub(node3BalanceBefore).toString(),
- sendNode3.toString(),
- )
- })
- })
- })
-
- describe('#setAuthorizedSenders', () => {
- let newSenders: string[]
- let receipt: ContractReceipt
- describe('when called by the owner', () => {
- describe('setting 3 authorized senders', () => {
- beforeEach(async () => {
- newSenders = [
- await roles.oracleNode1.getAddress(),
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
- const tx = await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders(newSenders)
- receipt = await tx.wait()
- })
-
- it('adds the authorized nodes', async () => {
- const authorizedSenders = await operator.getAuthorizedSenders()
- assert.equal(newSenders.length, authorizedSenders.length)
- for (let i = 0; i < authorizedSenders.length; i++) {
- assert.equal(authorizedSenders[i], newSenders[i])
- }
- })
-
- it('emits an event on the Operator', async () => {
- assert.equal(receipt.events?.length, 1)
-
- const encodedSenders1 = ethers.utils.defaultAbiCoder.encode(
- ['address[]', 'address'],
- [newSenders, await roles.defaultAccount.getAddress()],
- )
-
- const responseEvent1 = receipt.events?.[0]
- assert.equal(responseEvent1?.event, 'AuthorizedSendersChanged')
- assert.equal(responseEvent1?.data, encodedSenders1)
- })
-
- it('replaces the authorized nodes', async () => {
- const originalAuthorization = await operator
- .connect(roles.defaultAccount)
- .isAuthorizedSender(await roles.oracleNode.getAddress())
- assert.isFalse(originalAuthorization)
- })
-
- after(async () => {
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.oracleNode.getAddress()])
- })
- })
-
- describe('setting 0 authorized senders', () => {
- beforeEach(async () => {
- newSenders = []
- })
-
- it('reverts with a minimum senders message', async () => {
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders(newSenders),
- 'Must have at least 1 sender',
- )
- })
- })
- })
-
- describe('when called by an authorized sender', () => {
- beforeEach(async () => {
- newSenders = [await roles.oracleNode1.getAddress()]
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders(newSenders)
- })
-
- it('succeeds', async () => {
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.stranger.getAddress()])
- })
- })
-
- describe('when called by a non-owner', () => {
- it('cannot add an authorized node', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .setAuthorizedSenders([await roles.stranger.getAddress()]),
- 'Cannot set authorized senders',
- )
- })
- })
- })
-
- describe('#setAuthorizedSendersOn', () => {
- let newSenders: string[]
-
- beforeEach(async () => {
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSenders([await roles.oracleNode1.getAddress()])
- newSenders = [
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
-
- forwarder1 = await forwarderFactory
- .connect(owner)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- forwarder2 = await forwarderFactory
- .connect(owner)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- })
-
- describe('when called by a non-authorized sender', () => {
- it('reverts', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .setAuthorizedSendersOn(newSenders, [forwarder1.address]),
- 'Cannot set authorized senders',
- )
- })
- })
-
- describe('when called by an owner', () => {
- it('does not revert', async () => {
- await operator
- .connect(roles.defaultAccount)
- .setAuthorizedSendersOn(
- [forwarder1.address, forwarder2.address],
- newSenders,
- )
- })
- })
-
- describe('when called by an authorized sender', () => {
- it('does not revert', async () => {
- await operator
- .connect(roles.oracleNode1)
- .setAuthorizedSendersOn(
- [forwarder1.address, forwarder2.address],
- newSenders,
- )
- })
-
- it('does revert with 0 senders', async () => {
- await operator
- .connect(roles.oracleNode1)
- .setAuthorizedSendersOn(
- [forwarder1.address, forwarder2.address],
- newSenders,
- )
- })
-
- it('emits a log announcing the change and who made it', async () => {
- const targets = [forwarder1.address, forwarder2.address]
- const tx = await operator
- .connect(roles.oracleNode1)
- .setAuthorizedSendersOn(targets, newSenders)
-
- const receipt = await tx.wait()
- const encodedArgs = ethers.utils.defaultAbiCoder.encode(
- ['address[]', 'address[]', 'address'],
- [targets, newSenders, await roles.oracleNode1.getAddress()],
- )
-
- const event1 = receipt.events?.[0]
- assert.equal(event1?.event, 'TargetsUpdatedAuthorizedSenders')
- assert.equal(event1?.address, operator.address)
- assert.equal(event1?.data, encodedArgs)
- })
-
- it('updates the sender list on each of the targets', async () => {
- const tx = await operator
- .connect(roles.oracleNode1)
- .setAuthorizedSendersOn(
- [forwarder1.address, forwarder2.address],
- newSenders,
- )
-
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 3, receipt.toString())
- const encodedSenders = ethers.utils.defaultAbiCoder.encode(
- ['address[]', 'address'],
- [newSenders, operator.address],
- )
-
- const event1 = receipt.events?.[1]
- assert.equal(event1?.event, 'AuthorizedSendersChanged')
- assert.equal(event1?.address, forwarder1.address)
- assert.equal(event1?.data, encodedSenders)
-
- const event2 = receipt.events?.[2]
- assert.equal(event2?.event, 'AuthorizedSendersChanged')
- assert.equal(event2?.address, forwarder2.address)
- assert.equal(event2?.data, encodedSenders)
- })
- })
- })
-
- describe('#acceptAuthorizedReceivers', () => {
- let newSenders: string[]
-
- describe('being called by the owner', () => {
- let operator2: Contract
- let receipt: ContractReceipt
-
- beforeEach(async () => {
- operator2 = await operatorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, await roles.defaultAccount.getAddress())
- forwarder1 = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- forwarder2 = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, zeroAddress, '0x')
- await operator
- .connect(roles.defaultAccount)
- .transferOwnableContracts(
- [forwarder1.address, forwarder2.address],
- operator2.address,
- )
- newSenders = [
- await roles.oracleNode2.getAddress(),
- await roles.oracleNode3.getAddress(),
- ]
-
- const tx = await operator2
- .connect(roles.defaultAccount)
- .acceptAuthorizedReceivers(
- [forwarder1.address, forwarder2.address],
- newSenders,
- )
- receipt = await tx.wait()
- })
-
- it('sets the new owner on the forwarder', async () => {
- assert.equal(await forwarder1.owner(), operator2.address)
- })
-
- it('emits ownership transferred events', async () => {
- assert.equal(receipt?.events?.[0]?.event, 'OwnableContractAccepted')
- assert.equal(receipt?.events?.[0]?.args?.[0], forwarder1.address)
-
- assert.equal(receipt?.events?.[1]?.event, 'OwnershipTransferred')
- assert.equal(receipt?.events?.[1]?.address, forwarder1.address)
- assert.equal(receipt?.events?.[1]?.args?.[0], operator.address)
- assert.equal(receipt?.events?.[1]?.args?.[1], operator2.address)
-
- assert.equal(receipt?.events?.[2]?.event, 'OwnableContractAccepted')
- assert.equal(receipt?.events?.[2]?.args?.[0], forwarder2.address)
-
- assert.equal(receipt?.events?.[3]?.event, 'OwnershipTransferred')
- assert.equal(receipt?.events?.[3]?.address, forwarder2.address)
- assert.equal(receipt?.events?.[3]?.args?.[0], operator.address)
- assert.equal(receipt?.events?.[3]?.args?.[1], operator2.address)
-
- assert.equal(
- receipt?.events?.[4]?.event,
- 'TargetsUpdatedAuthorizedSenders',
- )
-
- const encodedSenders = ethers.utils.defaultAbiCoder.encode(
- ['address[]', 'address'],
- [newSenders, operator2.address],
- )
- assert.equal(receipt?.events?.[5]?.event, 'AuthorizedSendersChanged')
- assert.equal(receipt?.events?.[5]?.address, forwarder1.address)
- assert.equal(receipt?.events?.[5]?.data, encodedSenders)
-
- assert.equal(receipt?.events?.[6]?.event, 'AuthorizedSendersChanged')
- assert.equal(receipt?.events?.[6]?.address, forwarder2.address)
- assert.equal(receipt?.events?.[6]?.data, encodedSenders)
- })
- })
-
- describe('being called by a non owner', () => {
- it('reverts with message', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .acceptAuthorizedReceivers(
- [forwarder1.address, forwarder2.address],
- newSenders,
- ),
- 'Cannot set authorized senders',
- )
- })
- })
- })
-
- describe('#onTokenTransfer', () => {
- describe('when called from any address but the LINK token', () => {
- it('triggers the intended method', async () => {
- const callData = encodeOracleRequest(
- specId,
- to,
- fHash,
- 0,
- constants.HashZero,
- )
-
- await evmRevert(
- operator.onTokenTransfer(
- await roles.defaultAccount.getAddress(),
- 0,
- callData,
- ),
- )
- })
- })
-
- describe('when called from the LINK token', () => {
- it('triggers the intended method', async () => {
- const callData = encodeOracleRequest(
- specId,
- to,
- fHash,
- 0,
- constants.HashZero,
- )
-
- const tx = await link.transferAndCall(operator.address, 0, callData, {
- value: 0,
- })
- const receipt = await tx.wait()
-
- assert.equal(3, receipt.logs?.length)
- })
-
- describe('with no data', () => {
- it('reverts', async () => {
- await evmRevert(
- link.transferAndCall(operator.address, 0, '0x', {
- value: 0,
- }),
- )
- })
- })
- })
-
- describe('malicious requester', () => {
- let mock: Contract
- let requester: Contract
- const paymentAmount = toWei('1')
-
- beforeEach(async () => {
- mock = await maliciousRequesterFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(mock.address, paymentAmount)
- })
-
- it('cannot withdraw from oracle', async () => {
- const operatorOriginalBalance = await link.balanceOf(operator.address)
- const mockOriginalBalance = await link.balanceOf(mock.address)
-
- await evmRevert(mock.maliciousWithdraw())
-
- const operatorNewBalance = await link.balanceOf(operator.address)
- const mockNewBalance = await link.balanceOf(mock.address)
-
- bigNumEquals(operatorOriginalBalance, operatorNewBalance)
- bigNumEquals(mockNewBalance, mockOriginalBalance)
- })
-
- describe('if the requester tries to create a requestId for another contract', () => {
- it('the requesters ID will not match with the oracle contract', async () => {
- const tx = await mock.maliciousTargetConsumer(to)
- const receipt = await tx.wait()
-
- const mockRequestId = receipt.logs?.[0].data
- const requestId = (receipt.events?.[0].args as any).requestId
- assert.notEqual(mockRequestId, requestId)
- })
-
- it('the target requester can still create valid requests', async () => {
- requester = await basicConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- await link.transfer(requester.address, paymentAmount)
- await mock.maliciousTargetConsumer(requester.address)
- await requester.requestEthereumPrice('USD', paymentAmount)
- })
- })
- })
-
- it('does not allow recursive calls of onTokenTransfer', async () => {
- const requestPayload = encodeOracleRequest(
- specId,
- to,
- fHash,
- 0,
- constants.HashZero,
- )
-
- const ottSelector =
- operatorFactory.interface.getSighash('onTokenTransfer')
- const header =
- '000000000000000000000000c5fdf4076b8f3a5357c5e395ab970b5b54098fef' + // to
- '0000000000000000000000000000000000000000000000000000000000000539' + // amount
- '0000000000000000000000000000000000000000000000000000000000000060' + // offset
- '0000000000000000000000000000000000000000000000000000000000000136' // length
-
- const maliciousPayload = ottSelector + header + requestPayload.slice(2)
-
- await evmRevert(
- link.transferAndCall(operator.address, 0, maliciousPayload, {
- value: 0,
- }),
- )
- })
- })
-
- describe('#oracleRequest', () => {
- describe('when called through the LINK token', () => {
- const paid = 100
- let log: providers.Log | undefined
- let receipt: providers.TransactionReceipt
-
- beforeEach(async () => {
- const args = encodeOracleRequest(
- specId,
- to,
- fHash,
- 1,
- constants.HashZero,
- )
- const tx = await link.transferAndCall(operator.address, paid, args)
- receipt = await tx.wait()
- assert.equal(3, receipt?.logs?.length)
-
- log = receipt.logs && receipt.logs[2]
- })
-
- it('logs an event', async () => {
- assert.equal(operator.address, log?.address)
-
- assert.equal(log?.topics?.[1], specId)
-
- const req = decodeRunRequest(receipt?.logs?.[2])
- assert.equal(await roles.defaultAccount.getAddress(), req.requester)
- bigNumEquals(paid, req.payment)
- })
-
- it('uses the expected event signature', async () => {
- // If updating this test, be sure to update models.RunLogTopic.
- const eventSignature =
- '0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65'
- assert.equal(eventSignature, log?.topics?.[0])
- })
-
- it('does not allow the same requestId to be used twice', async () => {
- const args2 = encodeOracleRequest(
- specId,
- to,
- fHash,
- 1,
- constants.HashZero,
- )
- await evmRevert(link.transferAndCall(operator.address, paid, args2))
- })
-
- describe('when called with a payload less than 2 EVM words + function selector', () => {
- it('throws an error', async () => {
- const funcSelector =
- operatorFactory.interface.getSighash('oracleRequest')
- const maliciousData =
- funcSelector +
- '0000000000000000000000000000000000000000000000000000000000000000000'
- await evmRevert(
- link.transferAndCall(operator.address, paid, maliciousData),
- )
- })
- })
-
- describe('when called with a payload between 3 and 9 EVM words', () => {
- it('throws an error', async () => {
- const funcSelector =
- operatorFactory.interface.getSighash('oracleRequest')
- const maliciousData =
- funcSelector +
- '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
- await evmRevert(
- link.transferAndCall(operator.address, paid, maliciousData),
- )
- })
- })
- })
-
- describe('when dataVersion is higher than 255', () => {
- it('throws an error', async () => {
- const paid = 100
- const args = encodeOracleRequest(
- specId,
- to,
- fHash,
- 1,
- constants.HashZero,
- 256,
- )
- await evmRevert(link.transferAndCall(operator.address, paid, args))
- })
- })
-
- describe('when not called through the LINK token', () => {
- it('reverts', async () => {
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .oracleRequest(
- '0x0000000000000000000000000000000000000000',
- 0,
- specId,
- to,
- fHash,
- 1,
- 1,
- '0x',
- ),
- )
- })
- })
- })
-
- describe('#operatorRequest', () => {
- describe('when called through the LINK token', () => {
- const paid = 100
- let log: providers.Log | undefined
- let receipt: providers.TransactionReceipt
-
- beforeEach(async () => {
- const args = encodeRequestOracleData(
- specId,
- fHash,
- 1,
- constants.HashZero,
- )
- const tx = await link.transferAndCall(operator.address, paid, args)
- receipt = await tx.wait()
- assert.equal(3, receipt?.logs?.length)
-
- log = receipt.logs && receipt.logs[2]
- })
-
- it('logs an event', async () => {
- assert.equal(operator.address, log?.address)
-
- assert.equal(log?.topics?.[1], specId)
-
- const req = decodeRunRequest(receipt?.logs?.[2])
- assert.equal(await roles.defaultAccount.getAddress(), req.requester)
- bigNumEquals(paid, req.payment)
- })
-
- it('uses the expected event signature', async () => {
- // If updating this test, be sure to update models.RunLogTopic.
- const eventSignature =
- '0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65'
- assert.equal(eventSignature, log?.topics?.[0])
- })
-
- it('does not allow the same requestId to be used twice', async () => {
- const args2 = encodeRequestOracleData(
- specId,
- fHash,
- 1,
- constants.HashZero,
- )
- await evmRevert(link.transferAndCall(operator.address, paid, args2))
- })
-
- describe('when called with a payload less than 2 EVM words + function selector', () => {
- it('throws an error', async () => {
- const funcSelector =
- operatorFactory.interface.getSighash('oracleRequest')
- const maliciousData =
- funcSelector +
- '0000000000000000000000000000000000000000000000000000000000000000000'
- await evmRevert(
- link.transferAndCall(operator.address, paid, maliciousData),
- )
- })
- })
-
- describe('when called with a payload between 3 and 9 EVM words', () => {
- it('throws an error', async () => {
- const funcSelector =
- operatorFactory.interface.getSighash('oracleRequest')
- const maliciousData =
- funcSelector +
- '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
- await evmRevert(
- link.transferAndCall(operator.address, paid, maliciousData),
- )
- })
- })
- })
-
- describe('when dataVersion is higher than 255', () => {
- it('throws an error', async () => {
- const paid = 100
- const args = encodeRequestOracleData(
- specId,
- fHash,
- 1,
- constants.HashZero,
- 256,
- )
- await evmRevert(link.transferAndCall(operator.address, paid, args))
- })
- })
-
- describe('when not called through the LINK token', () => {
- it('reverts', async () => {
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .oracleRequest(
- '0x0000000000000000000000000000000000000000',
- 0,
- specId,
- to,
- fHash,
- 1,
- 1,
- '0x',
- ),
- )
- })
- })
- })
-
- describe('#fulfillOracleRequest', () => {
- const response = 'Hi Mom!'
- let maliciousRequester: Contract
- let basicConsumer: Contract
- let maliciousConsumer: Contract
- let gasGuzzlingConsumer: Contract
- let request: ReturnType
-
- describe('gas guzzling consumer [ @skip-coverage ]', () => {
- beforeEach(async () => {
- gasGuzzlingConsumer = await gasGuzzlingConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(gasGuzzlingConsumer.address, paymentAmount)
- const tx =
- await gasGuzzlingConsumer.gassyRequestEthereumPrice(paymentAmount)
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('emits an OracleResponse event', async () => {
- const fulfillParams = convertFufillParams(request, response)
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 1)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
- })
-
- describe('cooperative consumer', () => {
- beforeEach(async () => {
- basicConsumer = await basicConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(basicConsumer.address, paymentAmount)
- const currency = 'USD'
- const tx = await basicConsumer.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- describe('when called by an unauthorized node', () => {
- beforeEach(async () => {
- assert.equal(
- false,
- await operator.isAuthorizedSender(
- await roles.stranger.getAddress(),
- ),
- )
- })
-
- it('raises an error', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .fulfillOracleRequest(...convertFufillParams(request, response)),
- )
- })
- })
-
- describe('when fulfilled with the wrong function', () => {
- let v7Consumer
- beforeEach(async () => {
- v7Consumer = await v7ConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(v7Consumer.address, paymentAmount)
- const currency = 'USD'
- const tx = await v7Consumer.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('raises an error', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .fulfillOracleRequest(...convertFufillParams(request, response)),
- )
- })
- })
-
- describe('when called by an authorized node', () => {
- it('raises an error if the request ID does not exist', async () => {
- request.requestId = ethers.utils.formatBytes32String('DOESNOTEXIST')
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response)),
- )
- })
-
- it('sets the value on the requested contract', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- const currentValue = await basicConsumer.currentPrice()
- assert.equal(response, ethers.utils.parseBytes32String(currentValue))
- })
-
- it('emits an OracleResponse event', async () => {
- const fulfillParams = convertFufillParams(request, response)
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 3)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
-
- it('does not allow a request to be fulfilled twice', async () => {
- const response2 = response + ' && Hello World!!'
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response2)),
- )
-
- const currentValue = await basicConsumer.currentPrice()
- assert.equal(response, ethers.utils.parseBytes32String(currentValue))
- })
- })
-
- describe('when the oracle does not provide enough gas', () => {
- // if updating this defaultGasLimit, be sure it matches with the
- // defaultGasLimit specified in store/tx_manager.go
- const defaultGasLimit = 500000
-
- beforeEach(async () => {
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it('does not allow the oracle to withdraw the payment', async () => {
- await evmRevert(
- operator.connect(roles.oracleNode).fulfillOracleRequest(
- ...convertFufillParams(request, response, {
- gasLimit: 70000,
- }),
- ),
- )
-
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it(`${defaultGasLimit} is enough to pass the gas requirement`, async () => {
- await operator.connect(roles.oracleNode).fulfillOracleRequest(
- ...convertFufillParams(request, response, {
- gasLimit: defaultGasLimit,
- }),
- )
-
- bigNumEquals(request.payment, await operator.withdrawable())
- })
- })
- })
-
- describe('with a malicious requester', () => {
- beforeEach(async () => {
- const paymentAmount = toWei('1')
- maliciousRequester = await maliciousRequesterFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousRequester.address, paymentAmount)
- })
-
- it('cannot cancel before the expiration', async () => {
- await evmRevert(
- maliciousRequester.maliciousRequestCancel(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- ),
- )
- })
-
- it('cannot call functions on the LINK token through callbacks', async () => {
- await evmRevert(
- maliciousRequester.request(
- specId,
- link.address,
- ethers.utils.toUtf8Bytes('transfer(address,uint256)'),
- ),
- )
- })
-
- describe('requester lies about amount of LINK sent', () => {
- it('the oracle uses the amount of LINK actually paid', async () => {
- const tx = await maliciousRequester.maliciousPrice(specId)
- const receipt = await tx.wait()
- const req = decodeRunRequest(receipt.logs?.[3])
-
- assert(toWei('1').eq(req.payment))
- })
- })
- })
-
- describe('with a malicious consumer', () => {
- const paymentAmount = toWei('1')
-
- beforeEach(async () => {
- maliciousConsumer = await maliciousConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousConsumer.address, paymentAmount)
- })
-
- describe('fails during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('assertFail(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
-
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response2 = 'hack the planet 102'
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response2)),
- )
- })
- })
-
- describe('calls selfdestruct', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- await maliciousConsumer.remove()
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
- })
-
- describe('request is canceled during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('cancelRequestOnFulfill(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- bigNumEquals(0, await link.balanceOf(maliciousConsumer.address))
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- const mockBalance = await link.balanceOf(maliciousConsumer.address)
- bigNumEquals(mockBalance, 0)
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response2 = 'hack the planet 102'
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response2)),
- )
- })
- })
-
- describe('tries to steal funds from node', () => {
- it('is not successful with call', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthCall(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
-
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with send', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthSend(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with transfer', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthTransfer(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, response))
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
- })
-
- describe('when calling an owned contract', () => {
- beforeEach(async () => {
- forwarder1 = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, link.address, operator.address, '0x')
- })
-
- it('does not allow the contract to callback to owned contracts', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('whatever(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- let request = decodeRunRequest(receipt.logs?.[3])
- let responseParams = convertFufillParams(request, response)
- // set the params to be the owned address
- responseParams[2] = forwarder1.address
-
- //accept ownership
- await operator
- .connect(roles.defaultAccount)
- .acceptOwnableContracts([forwarder1.address])
-
- // do the thing
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...responseParams),
- 'Cannot call owned contract',
- )
-
- await operator
- .connect(roles.defaultAccount)
- .transferOwnableContracts([forwarder1.address], link.address)
- //reverts for a different reason after transferring ownership
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...responseParams),
- 'Params do not match request ID',
- )
- })
- })
- })
- })
-
- describe('#fulfillOracleRequest2', () => {
- describe('single word fulfils', () => {
- const response = 'Hi mom!'
- const responseTypes = ['bytes32']
- const responseValues = [toBytes32String(response)]
- let maliciousRequester: Contract
- let basicConsumer: Contract
- let maliciousConsumer: Contract
- let gasGuzzlingConsumer: Contract
- let request: ReturnType
- let request2: ReturnType
-
- describe('gas guzzling consumer [ @skip-coverage ]', () => {
- beforeEach(async () => {
- gasGuzzlingConsumer = await gasGuzzlingConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(gasGuzzlingConsumer.address, paymentAmount)
- const tx =
- await gasGuzzlingConsumer.gassyRequestEthereumPrice(paymentAmount)
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('emits an OracleResponse2 event', async () => {
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 1)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
- })
-
- describe('cooperative consumer', () => {
- beforeEach(async () => {
- basicConsumer = await basicConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(basicConsumer.address, paymentAmount)
- const currency = 'USD'
- const tx = await basicConsumer.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- describe('when called by an unauthorized node', () => {
- beforeEach(async () => {
- assert.equal(
- false,
- await operator.isAuthorizedSender(
- await roles.stranger.getAddress(),
- ),
- )
- })
-
- it('raises an error', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- ),
- )
- })
- })
-
- describe('when called by an authorized node', () => {
- it('raises an error if the request ID does not exist', async () => {
- request.requestId = ethers.utils.formatBytes32String('DOESNOTEXIST')
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- ),
- )
- })
-
- it('sets the value on the requested contract', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const currentValue = await basicConsumer.currentPrice()
- assert.equal(
- response,
- ethers.utils.parseBytes32String(currentValue),
- )
- })
-
- it('emits an OracleResponse2 event', async () => {
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 3)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
-
- it('does not allow a request to be fulfilled twice', async () => {
- const response2 = response + ' && Hello World!!'
- const response2Values = [toBytes32String(response2)]
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- response2Values,
- ),
- ),
- )
-
- const currentValue = await basicConsumer.currentPrice()
- assert.equal(
- response,
- ethers.utils.parseBytes32String(currentValue),
- )
- })
- })
-
- describe('when the oracle does not provide enough gas', () => {
- // if updating this defaultGasLimit, be sure it matches with the
- // defaultGasLimit specified in store/tx_manager.go
- const defaultGasLimit = 500000
-
- beforeEach(async () => {
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it('does not allow the oracle to withdraw the payment', async () => {
- await evmRevert(
- operator.connect(roles.oracleNode).fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- {
- gasLimit: 70000,
- },
- ),
- ),
- )
-
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it(`${defaultGasLimit} is enough to pass the gas requirement`, async () => {
- await operator.connect(roles.oracleNode).fulfillOracleRequest2(
- ...convertFulfill2Params(request, responseTypes, responseValues, {
- gasLimit: defaultGasLimit,
- }),
- )
-
- bigNumEquals(request.payment, await operator.withdrawable())
- })
- })
- })
-
- describe('with a malicious oracle', () => {
- beforeEach(async () => {
- // Setup Request 1
- basicConsumer = await basicConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(basicConsumer.address, paymentAmount)
- const currency = 'USD'
- const tx = await basicConsumer.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- // Setup Request 2
- await link.transfer(basicConsumer.address, paymentAmount)
- const tx2 = await basicConsumer.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt2 = await tx2.wait()
- request2 = decodeRunRequest(receipt2.logs?.[3])
- })
-
- it('cannot spoof requestId in response data by moving calldata offset', async () => {
- // Malicious Oracle Fulfill 2
- const functionSelector = '0x6ae0bc76' // fulfillOracleRequest2
- const dataOffset =
- '0000000000000000000000000000000000000000000000000000000000000100' // Moved to 0x0124
- const fillerBytes =
- '0000000000000000000000000000000000000000000000000000000000000000'
- const expectedCalldataStart = request.requestId.slice(2) // 0xe4, this is checked against requestId in validateMultiWordResponseId
- const dataSize =
- '0000000000000000000000000000000000000000000000000000000000000040' // Two 32 byte blocks
- const maliciousCalldataId = request2.requestId.slice(2) // 0x0124, set to a different requestId
- const calldataData =
- '1122334455667788991122334455667788991122334455667788991122334455' // some garbage value as response value
-
- const data =
- functionSelector +
- /** Input Params - slice off 0x prefix and pad with 0's */
- request.requestId.slice(2) +
- request.payment.slice(2).padStart(64, '0') +
- request.callbackAddr.slice(2).padStart(64, '0') +
- request.callbackFunc.slice(2).padEnd(64, '0') +
- request.expiration.slice(2).padStart(64, '0') +
- // calldata "data"
- dataOffset +
- fillerBytes +
- expectedCalldataStart +
- dataSize +
- maliciousCalldataId +
- calldataData
-
- await evmRevert(
- operator.connect(roles.oracleNode).signer.sendTransaction({
- to: operator.address,
- data,
- }),
- )
- })
- })
-
- describe('with a malicious requester', () => {
- beforeEach(async () => {
- const paymentAmount = toWei('1')
- maliciousRequester = await maliciousRequesterFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousRequester.address, paymentAmount)
- })
-
- it('cannot cancel before the expiration', async () => {
- await evmRevert(
- maliciousRequester.maliciousRequestCancel(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- ),
- )
- })
-
- it('cannot call functions on the LINK token through callbacks', async () => {
- await evmRevert(
- maliciousRequester.request(
- specId,
- link.address,
- ethers.utils.toUtf8Bytes('transfer(address,uint256)'),
- ),
- )
- })
-
- describe('requester lies about amount of LINK sent', () => {
- it('the oracle uses the amount of LINK actually paid', async () => {
- const tx = await maliciousRequester.maliciousPrice(specId)
- const receipt = await tx.wait()
- const req = decodeRunRequest(receipt.logs?.[3])
-
- assert(toWei('1').eq(req.payment))
- })
- })
- })
-
- describe('with a malicious consumer', () => {
- const paymentAmount = toWei('1')
-
- beforeEach(async () => {
- maliciousConsumer = await maliciousConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousConsumer.address, paymentAmount)
- })
-
- describe('fails during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('assertFail(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
-
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response2 = 'hack the planet 102'
- const response2Values = [toBytes32String(response2)]
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- response2Values,
- ),
- ),
- )
- })
- })
-
- describe('calls selfdestruct', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- await maliciousConsumer.remove()
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
- })
-
- describe('request is canceled during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes(
- 'cancelRequestOnFulfill(bytes32,bytes32)',
- ),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- bigNumEquals(0, await link.balanceOf(maliciousConsumer.address))
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const mockBalance = await link.balanceOf(maliciousConsumer.address)
- bigNumEquals(mockBalance, 0)
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response2 = 'hack the planet 102'
- const response2Values = [toBytes32String(response2)]
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- response2Values,
- ),
- ),
- )
- })
- })
-
- describe('tries to steal funds from node', () => {
- it('is not successful with call', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthCall(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with send', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthSend(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with transfer', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthTransfer(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
- })
-
- describe('when calling an owned contract', () => {
- beforeEach(async () => {
- forwarder1 = await forwarderFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, link.address, operator.address, '0x')
- })
-
- it('does not allow the contract to callback to owned contracts', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('whatever(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- let request = decodeRunRequest(receipt.logs?.[3])
- let responseParams = convertFufillParams(request, response)
- // set the params to be the owned address
- responseParams[2] = forwarder1.address
-
- //accept ownership
- await operator
- .connect(roles.defaultAccount)
- .acceptOwnableContracts([forwarder1.address])
-
- // do the thing
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...responseParams),
- 'Cannot call owned contract',
- )
-
- await operator
- .connect(roles.defaultAccount)
- .transferOwnableContracts([forwarder1.address], link.address)
- //reverts for a different reason after transferring ownership
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...responseParams),
- 'Params do not match request ID',
- )
- })
- })
- })
- })
-
- describe('multi word fulfils', () => {
- describe('one bytes parameter', () => {
- const response =
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\
- Fusce euismod malesuada ligula, eget semper metus ultrices sit amet.'
- const responseTypes = ['bytes']
- const responseValues = [stringToBytes(response)]
- let maliciousRequester: Contract
- let multiConsumer: Contract
- let maliciousConsumer: Contract
- let gasGuzzlingConsumer: Contract
- let request: ReturnType
-
- describe('gas guzzling consumer [ @skip-coverage ]', () => {
- beforeEach(async () => {
- gasGuzzlingConsumer = await gasGuzzlingConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(gasGuzzlingConsumer.address, paymentAmount)
- const tx =
- await gasGuzzlingConsumer.gassyMultiWordRequest(paymentAmount)
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('emits an OracleResponse2 event', async () => {
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 1)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
- })
-
- describe('cooperative consumer', () => {
- beforeEach(async () => {
- multiConsumer = await multiWordConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(multiConsumer.address, paymentAmount)
- const currency = 'USD'
- const tx = await multiConsumer.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it("matches the consumer's request ID", async () => {
- const nonce = await multiConsumer.publicGetNextRequestCount()
- const tx = await multiConsumer.requestEthereumPrice('USD', 0)
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- const packed = ethers.utils.solidityPack(
- ['address', 'uint256'],
- [multiConsumer.address, nonce],
- )
- const expected = ethers.utils.keccak256(packed)
- assert.equal(expected, request.requestId)
- })
-
- describe('when called by an unauthorized node', () => {
- beforeEach(async () => {
- assert.equal(
- false,
- await operator.isAuthorizedSender(
- await roles.stranger.getAddress(),
- ),
- )
- })
-
- it('raises an error', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- ),
- )
- })
- })
-
- describe('when called by an authorized node', () => {
- it('raises an error if the request ID does not exist', async () => {
- request.requestId =
- ethers.utils.formatBytes32String('DOESNOTEXIST')
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- ),
- )
- })
-
- it('sets the value on the requested contract', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const currentValue = await multiConsumer.currentPrice()
- assert.equal(response, ethers.utils.toUtf8String(currentValue))
- })
-
- it('emits an OracleResponse2 event', async () => {
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 3)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
-
- it('does not allow a request to be fulfilled twice', async () => {
- const response2 = response + ' && Hello World!!'
- const response2Values = [stringToBytes(response2)]
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- response2Values,
- ),
- ),
- )
-
- const currentValue = await multiConsumer.currentPrice()
- assert.equal(response, ethers.utils.toUtf8String(currentValue))
- })
- })
-
- describe('when the oracle does not provide enough gas', () => {
- // if updating this defaultGasLimit, be sure it matches with the
- // defaultGasLimit specified in store/tx_manager.go
- const defaultGasLimit = 500000
-
- beforeEach(async () => {
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it('does not allow the oracle to withdraw the payment', async () => {
- await evmRevert(
- operator.connect(roles.oracleNode).fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- {
- gasLimit: 70000,
- },
- ),
- ),
- )
-
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it(`${defaultGasLimit} is enough to pass the gas requirement`, async () => {
- await operator.connect(roles.oracleNode).fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- {
- gasLimit: defaultGasLimit,
- },
- ),
- )
-
- bigNumEquals(request.payment, await operator.withdrawable())
- })
- })
- })
-
- describe('with a malicious requester', () => {
- beforeEach(async () => {
- const paymentAmount = toWei('1')
- maliciousRequester = await maliciousRequesterFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousRequester.address, paymentAmount)
- })
-
- it('cannot cancel before the expiration', async () => {
- await evmRevert(
- maliciousRequester.maliciousRequestCancel(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- ),
- )
- })
-
- it('cannot call functions on the LINK token through callbacks', async () => {
- await evmRevert(
- maliciousRequester.request(
- specId,
- link.address,
- ethers.utils.toUtf8Bytes('transfer(address,uint256)'),
- ),
- )
- })
-
- describe('requester lies about amount of LINK sent', () => {
- it('the oracle uses the amount of LINK actually paid', async () => {
- const tx = await maliciousRequester.maliciousPrice(specId)
- const receipt = await tx.wait()
- const req = decodeRunRequest(receipt.logs?.[3])
-
- assert(toWei('1').eq(req.payment))
- })
- })
- })
-
- describe('with a malicious consumer', () => {
- const paymentAmount = toWei('1')
-
- beforeEach(async () => {
- maliciousConsumer = await maliciousMultiWordConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousConsumer.address, paymentAmount)
- })
-
- describe('fails during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('assertFail(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
-
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response2 = 'hack the planet 102'
- const response2Values = [stringToBytes(response2)]
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- response2Values,
- ),
- ),
- )
- })
- })
-
- describe('calls selfdestruct', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- await maliciousConsumer.remove()
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
- })
-
- describe('request is canceled during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes(
- 'cancelRequestOnFulfill(bytes32,bytes32)',
- ),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- bigNumEquals(0, await link.balanceOf(maliciousConsumer.address))
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const mockBalance = await link.balanceOf(
- maliciousConsumer.address,
- )
- bigNumEquals(mockBalance, 0)
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response2 = 'hack the planet 102'
- const response2Values = [stringToBytes(response2)]
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- response2Values,
- ),
- ),
- )
- })
- })
-
- describe('tries to steal funds from node', () => {
- it('is not successful with call', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthCall(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with send', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthSend(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with transfer', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthTransfer(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
- })
- })
- })
-
- describe('multiple bytes32 parameters', () => {
- const response1 = '100'
- const response2 = '7777777'
- const response3 = 'forty two'
- const responseTypes = ['bytes32', 'bytes32', 'bytes32']
- const responseValues = [
- toBytes32String(response1),
- toBytes32String(response2),
- toBytes32String(response3),
- ]
- let maliciousRequester: Contract
- let multiConsumer: Contract
- let maliciousConsumer: Contract
- let gasGuzzlingConsumer: Contract
- let request: ReturnType
-
- describe('gas guzzling consumer [ @skip-coverage ]', () => {
- beforeEach(async () => {
- gasGuzzlingConsumer = await gasGuzzlingConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(gasGuzzlingConsumer.address, paymentAmount)
- const tx =
- await gasGuzzlingConsumer.gassyMultiWordRequest(paymentAmount)
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('emits an OracleResponse2 event', async () => {
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 1)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
- })
-
- describe('cooperative consumer', () => {
- beforeEach(async () => {
- multiConsumer = await multiWordConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(multiConsumer.address, paymentAmount)
- const currency = 'USD'
- const tx = await multiConsumer.requestMultipleParameters(
- currency,
- paymentAmount,
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- describe('when called by an unauthorized node', () => {
- beforeEach(async () => {
- assert.equal(
- false,
- await operator.isAuthorizedSender(
- await roles.stranger.getAddress(),
- ),
- )
- })
-
- it('raises an error', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- ),
- )
- })
- })
-
- describe('when called by an authorized node', () => {
- it('raises an error if the request ID does not exist', async () => {
- request.requestId =
- ethers.utils.formatBytes32String('DOESNOTEXIST')
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- ),
- )
- })
-
- it('sets the value on the requested contract', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const firstValue = await multiConsumer.usd()
- const secondValue = await multiConsumer.eur()
- const thirdValue = await multiConsumer.jpy()
- assert.equal(
- response1,
- ethers.utils.parseBytes32String(firstValue),
- )
- assert.equal(
- response2,
- ethers.utils.parseBytes32String(secondValue),
- )
- assert.equal(
- response3,
- ethers.utils.parseBytes32String(thirdValue),
- )
- })
-
- it('emits an OracleResponse2 event', async () => {
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- const tx = await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams)
- const receipt = await tx.wait()
- assert.equal(receipt.events?.length, 3)
- const responseEvent = receipt.events?.[0]
- assert.equal(responseEvent?.event, 'OracleResponse')
- assert.equal(responseEvent?.args?.[0], request.requestId)
- })
-
- it('does not allow a request to be fulfilled twice', async () => {
- const response4 = response3 + ' && Hello World!!'
- const repeatedResponseValues = [
- toBytes32String(response1),
- toBytes32String(response2),
- toBytes32String(response4),
- ]
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- repeatedResponseValues,
- ),
- ),
- )
-
- const firstValue = await multiConsumer.usd()
- const secondValue = await multiConsumer.eur()
- const thirdValue = await multiConsumer.jpy()
- assert.equal(
- response1,
- ethers.utils.parseBytes32String(firstValue),
- )
- assert.equal(
- response2,
- ethers.utils.parseBytes32String(secondValue),
- )
- assert.equal(
- response3,
- ethers.utils.parseBytes32String(thirdValue),
- )
- })
- })
-
- describe('when the oracle does not provide enough gas', () => {
- // if updating this defaultGasLimit, be sure it matches with the
- // defaultGasLimit specified in store/tx_manager.go
- const defaultGasLimit = 500000
-
- beforeEach(async () => {
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it('does not allow the oracle to withdraw the payment', async () => {
- await evmRevert(
- operator.connect(roles.oracleNode).fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- {
- gasLimit: 70000,
- },
- ),
- ),
- )
-
- bigNumEquals(0, await operator.withdrawable())
- })
-
- it(`${defaultGasLimit} is enough to pass the gas requirement`, async () => {
- await operator.connect(roles.oracleNode).fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- {
- gasLimit: defaultGasLimit,
- },
- ),
- )
-
- bigNumEquals(request.payment, await operator.withdrawable())
- })
- })
- })
-
- describe('with a malicious requester', () => {
- beforeEach(async () => {
- const paymentAmount = toWei('1')
- maliciousRequester = await maliciousRequesterFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousRequester.address, paymentAmount)
- })
-
- it('cannot cancel before the expiration', async () => {
- await evmRevert(
- maliciousRequester.maliciousRequestCancel(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- ),
- )
- })
-
- it('cannot call functions on the LINK token through callbacks', async () => {
- await evmRevert(
- maliciousRequester.request(
- specId,
- link.address,
- ethers.utils.toUtf8Bytes('transfer(address,uint256)'),
- ),
- )
- })
-
- describe('requester lies about amount of LINK sent', () => {
- it('the oracle uses the amount of LINK actually paid', async () => {
- const tx = await maliciousRequester.maliciousPrice(specId)
- const receipt = await tx.wait()
- const req = decodeRunRequest(receipt.logs?.[3])
-
- assert(toWei('1').eq(req.payment))
- })
- })
- })
-
- describe('with a malicious consumer', () => {
- const paymentAmount = toWei('1')
-
- beforeEach(async () => {
- maliciousConsumer = await maliciousMultiWordConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address)
- await link.transfer(maliciousConsumer.address, paymentAmount)
- })
-
- describe('fails during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('assertFail(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
-
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response4 = 'hack the planet 102'
- const repeatedResponseValues = [
- toBytes32String(response1),
- toBytes32String(response2),
- toBytes32String(response4),
- ]
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- repeatedResponseValues,
- ),
- ),
- )
- })
- })
-
- describe('calls selfdestruct', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('doesNothing(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
- await maliciousConsumer.remove()
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
- })
-
- describe('request is canceled during fulfillment', () => {
- beforeEach(async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes(
- 'cancelRequestOnFulfill(bytes32,bytes32)',
- ),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- bigNumEquals(0, await link.balanceOf(maliciousConsumer.address))
- })
-
- it('allows the oracle node to receive their payment', async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- const mockBalance = await link.balanceOf(
- maliciousConsumer.address,
- )
- bigNumEquals(mockBalance, 0)
-
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(balance, 0)
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), paymentAmount)
- const newBalance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- bigNumEquals(paymentAmount, newBalance)
- })
-
- it("can't fulfill the data again", async () => {
- const response4 = 'hack the planet 102'
- const repeatedResponseValues = [
- toBytes32String(response1),
- toBytes32String(response2),
- toBytes32String(response4),
- ]
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- repeatedResponseValues,
- ),
- ),
- )
- })
- })
-
- describe('tries to steal funds from node', () => {
- it('is not successful with call', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthCall(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
-
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with send', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthSend(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
-
- it('is not successful with transfer', async () => {
- const tx = await maliciousConsumer.requestData(
- specId,
- ethers.utils.toUtf8Bytes('stealEthTransfer(bytes32,bytes32)'),
- )
- const receipt = await tx.wait()
- request = decodeRunRequest(receipt.logs?.[3])
-
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- ),
- )
- bigNumEquals(
- 0,
- await ethers.provider.getBalance(maliciousConsumer.address),
- )
- })
- })
- })
- })
- })
-
- describe('when the response data is too short', () => {
- const response = 'Hi mom!'
- const responseTypes = ['bytes32']
- const responseValues = [toBytes32String(response)]
-
- it('reverts', async () => {
- let basicConsumer = await basicConsumerFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, operator.address, specId)
- const paymentAmount = toWei('1')
- await link.transfer(basicConsumer.address, paymentAmount)
- const tx = await basicConsumer.requestEthereumPrice(
- 'USD',
- paymentAmount,
- )
- const receipt = await tx.wait()
- let request = decodeRunRequest(receipt.logs?.[3])
-
- const fulfillParams = convertFulfill2Params(
- request,
- responseTypes,
- responseValues,
- )
- fulfillParams[5] = '0x' // overwrite the data to be of lenght 0
- await evmRevert(
- operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(...fulfillParams),
- 'Response must be > 32 bytes',
- )
- })
- })
- })
-
- describe('#withdraw', () => {
- describe('without reserving funds via oracleRequest', () => {
- it('does nothing', async () => {
- let balance = await link.balanceOf(await roles.oracleNode.getAddress())
- assert.equal(0, balance.toNumber())
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), toWei('1')),
- )
- balance = await link.balanceOf(await roles.oracleNode.getAddress())
- assert.equal(0, balance.toNumber())
- })
-
- describe('recovering funds that were mistakenly sent', () => {
- const paid = 1
- beforeEach(async () => {
- await link.transfer(operator.address, paid)
- })
-
- it('withdraws funds', async () => {
- const operatorBalanceBefore = await link.balanceOf(operator.address)
- const accountBalanceBefore = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.defaultAccount.getAddress(), paid)
-
- const operatorBalanceAfter = await link.balanceOf(operator.address)
- const accountBalanceAfter = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
-
- const accountDifference =
- accountBalanceAfter.sub(accountBalanceBefore)
- const operatorDifference =
- operatorBalanceBefore.sub(operatorBalanceAfter)
-
- bigNumEquals(operatorDifference, paid)
- bigNumEquals(accountDifference, paid)
- })
- })
- })
-
- describe('reserving funds via oracleRequest', () => {
- const payment = 15
- let request: ReturnType
-
- beforeEach(async () => {
- const requester = await roles.defaultAccount.getAddress()
- const args = encodeOracleRequest(
- specId,
- requester,
- fHash,
- 0,
- constants.HashZero,
- )
- const tx = await link.transferAndCall(operator.address, payment, args)
- const receipt = await tx.wait()
- assert.equal(3, receipt.logs?.length)
- request = decodeRunRequest(receipt.logs?.[2])
- })
-
- describe('but not freeing funds w fulfillOracleRequest', () => {
- it('does not transfer funds', async () => {
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.oracleNode.getAddress(), payment),
- )
- const balance = await link.balanceOf(
- await roles.oracleNode.getAddress(),
- )
- assert.equal(0, balance.toNumber())
- })
-
- describe('recovering funds that were mistakenly sent', () => {
- const paid = 1
- beforeEach(async () => {
- await link.transfer(operator.address, paid)
- })
-
- it('withdraws funds', async () => {
- const operatorBalanceBefore = await link.balanceOf(operator.address)
- const accountBalanceBefore = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.defaultAccount.getAddress(), paid)
-
- const operatorBalanceAfter = await link.balanceOf(operator.address)
- const accountBalanceAfter = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
-
- const accountDifference =
- accountBalanceAfter.sub(accountBalanceBefore)
- const operatorDifference =
- operatorBalanceBefore.sub(operatorBalanceAfter)
-
- bigNumEquals(operatorDifference, paid)
- bigNumEquals(accountDifference, paid)
- })
- })
- })
-
- describe('and freeing funds', () => {
- beforeEach(async () => {
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(
- ...convertFufillParams(request, 'Hello World!'),
- )
- })
-
- it('does not allow input greater than the balance', async () => {
- const originalOracleBalance = await link.balanceOf(operator.address)
- const originalStrangerBalance = await link.balanceOf(
- await roles.stranger.getAddress(),
- )
- const withdrawalAmount = payment + 1
-
- assert.isAbove(withdrawalAmount, originalOracleBalance.toNumber())
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.stranger.getAddress(), withdrawalAmount),
- )
-
- const newOracleBalance = await link.balanceOf(operator.address)
- const newStrangerBalance = await link.balanceOf(
- await roles.stranger.getAddress(),
- )
-
- assert.equal(
- originalOracleBalance.toNumber(),
- newOracleBalance.toNumber(),
- )
- assert.equal(
- originalStrangerBalance.toNumber(),
- newStrangerBalance.toNumber(),
- )
- })
-
- it('allows transfer of partial balance by owner to specified address', async () => {
- const partialAmount = 6
- const difference = payment - partialAmount
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.stranger.getAddress(), partialAmount)
- const strangerBalance = await link.balanceOf(
- await roles.stranger.getAddress(),
- )
- const oracleBalance = await link.balanceOf(operator.address)
- assert.equal(partialAmount, strangerBalance.toNumber())
- assert.equal(difference, oracleBalance.toNumber())
- })
-
- it('allows transfer of entire balance by owner to specified address', async () => {
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.stranger.getAddress(), payment)
- const balance = await link.balanceOf(
- await roles.stranger.getAddress(),
- )
- assert.equal(payment, balance.toNumber())
- })
-
- it('does not allow a transfer of funds by non-owner', async () => {
- await evmRevert(
- operator
- .connect(roles.stranger)
- .withdraw(await roles.stranger.getAddress(), payment),
- )
- const balance = await link.balanceOf(
- await roles.stranger.getAddress(),
- )
- assert.isTrue(ethers.constants.Zero.eq(balance))
- })
-
- describe('recovering funds that were mistakenly sent', () => {
- const paid = 1
- beforeEach(async () => {
- await link.transfer(operator.address, paid)
- })
-
- it('withdraws funds', async () => {
- const operatorBalanceBefore = await link.balanceOf(operator.address)
- const accountBalanceBefore = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
-
- await operator
- .connect(roles.defaultAccount)
- .withdraw(await roles.defaultAccount.getAddress(), paid)
-
- const operatorBalanceAfter = await link.balanceOf(operator.address)
- const accountBalanceAfter = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
-
- const accountDifference =
- accountBalanceAfter.sub(accountBalanceBefore)
- const operatorDifference =
- operatorBalanceBefore.sub(operatorBalanceAfter)
-
- bigNumEquals(operatorDifference, paid)
- bigNumEquals(accountDifference, paid)
- })
- })
- })
- })
- })
-
- describe('#withdrawable', () => {
- let request: ReturnType
- const amount = toWei('1')
-
- beforeEach(async () => {
- const requester = await roles.defaultAccount.getAddress()
- const args = encodeOracleRequest(
- specId,
- requester,
- fHash,
- 0,
- constants.HashZero,
- )
- const tx = await link.transferAndCall(operator.address, amount, args)
- const receipt = await tx.wait()
- assert.equal(3, receipt.logs?.length)
- request = decodeRunRequest(receipt.logs?.[2])
- await operator
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request, 'Hello World!'))
- })
-
- it('returns the correct value', async () => {
- const withdrawAmount = await operator.withdrawable()
- bigNumEquals(withdrawAmount, request.payment)
- })
-
- describe('funds that were mistakenly sent', () => {
- const paid = 1
- beforeEach(async () => {
- await link.transfer(operator.address, paid)
- })
-
- it('returns the correct value', async () => {
- const withdrawAmount = await operator.withdrawable()
-
- const expectedAmount = amount.add(paid)
- bigNumEquals(withdrawAmount, expectedAmount)
- })
- })
- })
-
- describe('#ownerTransferAndCall', () => {
- let operator2: Contract
- let args: string
- let to: string
- const startingBalance = 1000
- const payment = 20
-
- beforeEach(async () => {
- operator2 = await operatorFactory
- .connect(roles.oracleNode2)
- .deploy(link.address, await roles.oracleNode2.getAddress())
- to = operator2.address
- args = encodeOracleRequest(
- specId,
- operator.address,
- operatorFactory.interface.getSighash('fulfillOracleRequest'),
- 1,
- constants.HashZero,
- )
- })
-
- describe('when called by a non-owner', () => {
- it('reverts with owner error message', async () => {
- await link.transfer(operator.address, startingBalance)
- await evmRevert(
- operator
- .connect(roles.stranger)
- .ownerTransferAndCall(to, payment, args),
- 'Only callable by owner',
- )
- })
- })
-
- describe('when called by the owner', () => {
- beforeEach(async () => {
- await link.transfer(operator.address, startingBalance)
- })
-
- describe('without sufficient funds in contract', () => {
- it('reverts with funds message', async () => {
- const tooMuch = startingBalance * 2
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .ownerTransferAndCall(to, tooMuch, args),
- 'Amount requested is greater than withdrawable balance',
- )
- })
- })
-
- describe('with sufficient funds', () => {
- let tx: ContractTransaction
- let receipt: ContractReceipt
- let requesterBalanceBefore: BigNumber
- let requesterBalanceAfter: BigNumber
- let receiverBalanceBefore: BigNumber
- let receiverBalanceAfter: BigNumber
-
- before(async () => {
- requesterBalanceBefore = await link.balanceOf(operator.address)
- receiverBalanceBefore = await link.balanceOf(operator2.address)
- tx = await operator
- .connect(roles.defaultAccount)
- .ownerTransferAndCall(to, payment, args)
- receipt = await tx.wait()
- requesterBalanceAfter = await link.balanceOf(operator.address)
- receiverBalanceAfter = await link.balanceOf(operator2.address)
- })
-
- it('emits an event', async () => {
- assert.equal(3, receipt.logs?.length)
- const transferLog = await getLog(tx, 1)
- const parsedLog = link.interface.parseLog({
- data: transferLog.data,
- topics: transferLog.topics,
- })
- await expect(parsedLog.name).to.equal('Transfer')
- })
-
- it('transfers the tokens', async () => {
- bigNumEquals(
- requesterBalanceBefore.sub(requesterBalanceAfter),
- payment,
- )
- bigNumEquals(receiverBalanceAfter.sub(receiverBalanceBefore), payment)
- })
- })
- })
- })
-
- describe('#cancelOracleRequestByRequester', () => {
- const nonce = 17
-
- describe('with no pending requests', () => {
- it('fails', async () => {
- const fakeRequest: RunRequest = {
- requestId: ethers.utils.formatBytes32String('1337'),
- payment: '0',
- callbackFunc:
- getterSetterFactory.interface.getSighash('requestedBytes32'),
- expiration: '999999999999',
-
- callbackAddr: '',
- data: Buffer.from(''),
- dataVersion: 0,
- specId: '',
- requester: '',
- topic: '',
- }
- await increaseTime5Minutes(ethers.provider)
-
- await evmRevert(
- operator
- .connect(roles.stranger)
- .cancelOracleRequestByRequester(
- ...convertCancelByRequesterParams(fakeRequest, nonce),
- ),
- )
- })
- })
-
- describe('with a pending request', () => {
- const startingBalance = 100
- let request: ReturnType
- let receipt: providers.TransactionReceipt
-
- beforeEach(async () => {
- const requestAmount = 20
-
- await link.transfer(await roles.consumer.getAddress(), startingBalance)
-
- const args = encodeOracleRequest(
- specId,
- await roles.consumer.getAddress(),
- fHash,
- nonce,
- constants.HashZero,
- )
- const tx = await link
- .connect(roles.consumer)
- .transferAndCall(operator.address, requestAmount, args)
- receipt = await tx.wait()
-
- assert.equal(3, receipt.logs?.length)
- request = decodeRunRequest(receipt.logs?.[2])
-
- // pre conditions
- const oracleBalance = await link.balanceOf(operator.address)
- bigNumEquals(request.payment, oracleBalance)
-
- const consumerAmount = await link.balanceOf(
- await roles.consumer.getAddress(),
- )
- assert.equal(
- startingBalance - Number(request.payment),
- consumerAmount.toNumber(),
- )
- })
-
- describe('from a stranger', () => {
- it('fails', async () => {
- await evmRevert(
- operator
- .connect(roles.consumer)
- .cancelOracleRequestByRequester(
- ...convertCancelByRequesterParams(request, nonce),
- ),
- )
- })
- })
-
- describe('from the requester', () => {
- it('refunds the correct amount', async () => {
- await increaseTime5Minutes(ethers.provider)
- await operator
- .connect(roles.consumer)
- .cancelOracleRequestByRequester(
- ...convertCancelByRequesterParams(request, nonce),
- )
- const balance = await link.balanceOf(
- await roles.consumer.getAddress(),
- )
-
- assert.equal(startingBalance, balance.toNumber()) // 100
- })
-
- it('triggers a cancellation event', async () => {
- await increaseTime5Minutes(ethers.provider)
- const tx = await operator
- .connect(roles.consumer)
- .cancelOracleRequestByRequester(
- ...convertCancelByRequesterParams(request, nonce),
- )
- const receipt = await tx.wait()
-
- assert.equal(receipt.logs?.length, 2)
- assert.equal(request.requestId, receipt.logs?.[0].topics[1])
- })
-
- it('fails when called twice', async () => {
- await increaseTime5Minutes(ethers.provider)
- await operator
- .connect(roles.consumer)
- .cancelOracleRequestByRequester(
- ...convertCancelByRequesterParams(request, nonce),
- )
-
- await evmRevert(
- operator
- .connect(roles.consumer)
- .cancelOracleRequestByRequester(...convertCancelParams(request)),
- )
- })
- })
- })
- })
-
- describe('#cancelOracleRequest', () => {
- describe('with no pending requests', () => {
- it('fails', async () => {
- const fakeRequest: RunRequest = {
- requestId: ethers.utils.formatBytes32String('1337'),
- payment: '0',
- callbackFunc:
- getterSetterFactory.interface.getSighash('requestedBytes32'),
- expiration: '999999999999',
-
- callbackAddr: '',
- data: Buffer.from(''),
- dataVersion: 0,
- specId: '',
- requester: '',
- topic: '',
- }
- await increaseTime5Minutes(ethers.provider)
-
- await evmRevert(
- operator
- .connect(roles.stranger)
- .cancelOracleRequest(...convertCancelParams(fakeRequest)),
- )
- })
- })
-
- describe('with a pending request', () => {
- const startingBalance = 100
- let request: ReturnType
- let receipt: providers.TransactionReceipt
-
- beforeEach(async () => {
- const requestAmount = 20
-
- await link.transfer(await roles.consumer.getAddress(), startingBalance)
-
- const args = encodeOracleRequest(
- specId,
- await roles.consumer.getAddress(),
- fHash,
- 1,
- constants.HashZero,
- )
- const tx = await link
- .connect(roles.consumer)
- .transferAndCall(operator.address, requestAmount, args)
- receipt = await tx.wait()
-
- assert.equal(3, receipt.logs?.length)
- request = decodeRunRequest(receipt.logs?.[2])
- })
-
- it('has correct initial balances', async () => {
- const oracleBalance = await link.balanceOf(operator.address)
- bigNumEquals(request.payment, oracleBalance)
-
- const consumerAmount = await link.balanceOf(
- await roles.consumer.getAddress(),
- )
- assert.equal(
- startingBalance - Number(request.payment),
- consumerAmount.toNumber(),
- )
- })
-
- describe('from a stranger', () => {
- it('fails', async () => {
- await evmRevert(
- operator
- .connect(roles.consumer)
- .cancelOracleRequest(...convertCancelParams(request)),
- )
- })
- })
-
- describe('from the requester', () => {
- it('refunds the correct amount', async () => {
- await increaseTime5Minutes(ethers.provider)
- await operator
- .connect(roles.consumer)
- .cancelOracleRequest(...convertCancelParams(request))
- const balance = await link.balanceOf(
- await roles.consumer.getAddress(),
- )
-
- assert.equal(startingBalance, balance.toNumber()) // 100
- })
-
- it('triggers a cancellation event', async () => {
- await increaseTime5Minutes(ethers.provider)
- const tx = await operator
- .connect(roles.consumer)
- .cancelOracleRequest(...convertCancelParams(request))
- const receipt = await tx.wait()
-
- assert.equal(receipt.logs?.length, 2)
- assert.equal(request.requestId, receipt.logs?.[0].topics[1])
- })
-
- it('fails when called twice', async () => {
- await increaseTime5Minutes(ethers.provider)
- await operator
- .connect(roles.consumer)
- .cancelOracleRequest(...convertCancelParams(request))
-
- await evmRevert(
- operator
- .connect(roles.consumer)
- .cancelOracleRequest(...convertCancelParams(request)),
- )
- })
- })
- })
- })
-
- describe('#ownerForward', () => {
- let bytes: string
- let payload: string
- let mock: Contract
-
- beforeEach(async () => {
- bytes = ethers.utils.hexlify(ethers.utils.randomBytes(100))
- payload = getterSetterFactory.interface.encodeFunctionData(
- getterSetterFactory.interface.getFunction('setBytes'),
- [bytes],
- )
- mock = await getterSetterFactory.connect(roles.defaultAccount).deploy()
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- operator.connect(roles.stranger).ownerForward(mock.address, payload),
- )
- })
- })
-
- describe('when called by owner', () => {
- describe('when attempting to forward to the link token', () => {
- it('reverts', async () => {
- const sighash = linkTokenFactory.interface.getSighash('name')
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .ownerForward(link.address, sighash),
- 'Cannot call to LINK',
- )
- })
- })
-
- describe('when forwarding to any other address', () => {
- it('forwards the data', async () => {
- const tx = await operator
- .connect(roles.defaultAccount)
- .ownerForward(mock.address, payload)
- await tx.wait()
- assert.equal(await mock.getBytes(), bytes)
- })
-
- it('reverts when sending to a non-contract address', async () => {
- await evmRevert(
- operator
- .connect(roles.defaultAccount)
- .ownerForward(zeroAddress, payload),
- 'Must forward to a contract',
- )
- })
-
- it('perceives the message is sent by the Operator', async () => {
- const tx = await operator
- .connect(roles.defaultAccount)
- .ownerForward(mock.address, payload)
- const receipt = await tx.wait()
- const log: any = receipt.logs?.[0]
- const logData = mock.interface.decodeEventLog(
- mock.interface.getEvent('SetBytes'),
- log.data,
- log.topics,
- )
- assert.equal(ethers.utils.getAddress(logData.from), operator.address)
- })
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/OperatorFactory.test.ts b/contracts/test/v0.7/OperatorFactory.test.ts
deleted file mode 100644
index d2a24600e2..0000000000
--- a/contracts/test/v0.7/OperatorFactory.test.ts
+++ /dev/null
@@ -1,293 +0,0 @@
-import { ethers } from 'hardhat'
-import { evmWordToAddress, publicAbi } from '../test-helpers/helpers'
-import { assert } from 'chai'
-import { Contract, ContractFactory, ContractReceipt } from 'ethers'
-import { getUsers, Roles } from '../test-helpers/setup'
-
-let linkTokenFactory: ContractFactory
-let operatorGeneratorFactory: ContractFactory
-let operatorFactory: ContractFactory
-let forwarderFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- const users = await getUsers()
-
- roles = users.roles
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
- operatorGeneratorFactory = await ethers.getContractFactory(
- 'src/v0.7/OperatorFactory.sol:OperatorFactory',
- roles.defaultAccount,
- )
- operatorFactory = await ethers.getContractFactory(
- 'src/v0.7/Operator.sol:Operator',
- roles.defaultAccount,
- )
- forwarderFactory = await ethers.getContractFactory(
- 'src/v0.7/AuthorizedForwarder.sol:AuthorizedForwarder',
- roles.defaultAccount,
- )
-})
-
-describe('OperatorFactory', () => {
- let link: Contract
- let operatorGenerator: Contract
- let operator: Contract
- let forwarder: Contract
- let receipt: ContractReceipt
- let emittedOperator: string
- let emittedForwarder: string
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- operatorGenerator = await operatorGeneratorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(operatorGenerator, [
- 'created',
- 'deployNewOperator',
- 'deployNewOperatorAndForwarder',
- 'deployNewForwarder',
- 'deployNewForwarderAndTransferOwnership',
- 'getChainlinkToken',
- 'typeAndVersion',
- ])
- })
-
- describe('#typeAndVersion', () => {
- it('describes the authorized forwarder', async () => {
- assert.equal(
- await operatorGenerator.typeAndVersion(),
- 'OperatorFactory 1.0.0',
- )
- })
- })
-
- describe('#deployNewOperator', () => {
- beforeEach(async () => {
- const tx = await operatorGenerator
- .connect(roles.oracleNode)
- .deployNewOperator()
-
- receipt = await tx.wait()
- emittedOperator = evmWordToAddress(receipt.logs?.[0].topics?.[1])
- })
-
- it('emits an event', async () => {
- assert.equal(receipt?.events?.[0]?.event, 'OperatorCreated')
- assert.equal(emittedOperator, receipt.events?.[0].args?.[0])
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[0].args?.[1],
- )
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[0].args?.[2],
- )
- })
-
- it('sets the correct owner', async () => {
- operator = await operatorFactory
- .connect(roles.defaultAccount)
- .attach(emittedOperator)
- const ownerString = await operator.owner()
- assert.equal(ownerString, await roles.oracleNode.getAddress())
- })
-
- it('records that it deployed that address', async () => {
- assert.isTrue(await operatorGenerator.created(emittedOperator))
- })
- })
-
- describe('#deployNewOperatorAndForwarder', () => {
- beforeEach(async () => {
- const tx = await operatorGenerator
- .connect(roles.oracleNode)
- .deployNewOperatorAndForwarder()
-
- receipt = await tx.wait()
- emittedOperator = evmWordToAddress(receipt.logs?.[0].topics?.[1])
- emittedForwarder = evmWordToAddress(receipt.logs?.[3].topics?.[1])
- })
-
- it('emits an event recording that the operator was deployed', async () => {
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[0].args?.[1],
- )
- assert.equal(receipt?.events?.[0]?.event, 'OperatorCreated')
- assert.equal(receipt?.events?.[0]?.args?.[0], emittedOperator)
- assert.equal(
- receipt?.events?.[0]?.args?.[1],
- await roles.oracleNode.getAddress(),
- )
- assert.equal(
- receipt?.events?.[0]?.args?.[2],
- await roles.oracleNode.getAddress(),
- )
- })
-
- it('proposes the transfer of the forwarder to the operator', async () => {
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[0].args?.[1],
- )
- assert.equal(
- receipt?.events?.[1]?.topics?.[0],
- '0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278', //OwnershipTransferRequested(address,address)
- )
- assert.equal(
- evmWordToAddress(receipt?.events?.[1]?.topics?.[1]),
- operatorGenerator.address,
- )
- assert.equal(
- evmWordToAddress(receipt?.events?.[1]?.topics?.[2]),
- emittedOperator,
- )
-
- assert.equal(
- receipt?.events?.[2]?.topics?.[0],
- '0x4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e', //OwnershipTransferRequestedWithMessage(address,address,bytes)
- )
- assert.equal(
- evmWordToAddress(receipt?.events?.[2]?.topics?.[1]),
- operatorGenerator.address,
- )
- assert.equal(
- evmWordToAddress(receipt?.events?.[2]?.topics?.[2]),
- emittedOperator,
- )
- })
-
- it('emits an event recording that the forwarder was deployed', async () => {
- assert.equal(receipt?.events?.[3]?.event, 'AuthorizedForwarderCreated')
- assert.equal(receipt?.events?.[3]?.args?.[0], emittedForwarder)
- assert.equal(receipt?.events?.[3]?.args?.[1], operatorGenerator.address)
- assert.equal(
- receipt?.events?.[3]?.args?.[2],
- await roles.oracleNode.getAddress(),
- )
- })
-
- it('sets the correct owner on the operator', async () => {
- operator = await operatorFactory
- .connect(roles.defaultAccount)
- .attach(receipt?.events?.[0]?.args?.[0])
- assert.equal(await roles.oracleNode.getAddress(), await operator.owner())
- })
-
- it('sets the operator as the owner of the forwarder', async () => {
- forwarder = await forwarderFactory
- .connect(roles.defaultAccount)
- .attach(emittedForwarder)
- assert.equal(operatorGenerator.address, await forwarder.owner())
- })
-
- it('records that it deployed that address', async () => {
- assert.isTrue(await operatorGenerator.created(emittedOperator))
- assert.isTrue(await operatorGenerator.created(emittedForwarder))
- })
- })
-
- describe('#deployNewForwarder', () => {
- beforeEach(async () => {
- const tx = await operatorGenerator
- .connect(roles.oracleNode)
- .deployNewForwarder()
-
- receipt = await tx.wait()
- emittedForwarder = receipt.events?.[0].args?.[0]
- })
-
- it('emits an event', async () => {
- assert.equal(receipt?.events?.[0]?.event, 'AuthorizedForwarderCreated')
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[0].args?.[1],
- ) // owner
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[0].args?.[2],
- ) // sender
- })
-
- it('sets the caller as the owner', async () => {
- forwarder = await forwarderFactory
- .connect(roles.defaultAccount)
- .attach(emittedForwarder)
- const ownerString = await forwarder.owner()
- assert.equal(ownerString, await roles.oracleNode.getAddress())
- })
-
- it('records that it deployed that address', async () => {
- assert.isTrue(await operatorGenerator.created(emittedForwarder))
- })
- })
-
- describe('#deployNewForwarderAndTransferOwnership', () => {
- const message = '0x42'
-
- beforeEach(async () => {
- const tx = await operatorGenerator
- .connect(roles.oracleNode)
- .deployNewForwarderAndTransferOwnership(
- await roles.stranger.getAddress(),
- message,
- )
- receipt = await tx.wait()
-
- emittedForwarder = evmWordToAddress(receipt.logs?.[2].topics?.[1])
- })
-
- it('emits an event', async () => {
- assert.equal(receipt?.events?.[2]?.event, 'AuthorizedForwarderCreated')
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[2].args?.[1],
- ) // owner
- assert.equal(
- await roles.oracleNode.getAddress(),
- receipt.events?.[2].args?.[2],
- ) // sender
- })
-
- it('sets the caller as the owner', async () => {
- forwarder = await forwarderFactory
- .connect(roles.defaultAccount)
- .attach(emittedForwarder)
- const ownerString = await forwarder.owner()
- assert.equal(ownerString, await roles.oracleNode.getAddress())
- })
-
- it('proposes a transfer to the recipient', async () => {
- const emittedOwner = evmWordToAddress(receipt.logs?.[0].topics?.[1])
- assert.equal(emittedOwner, await roles.oracleNode.getAddress())
- const emittedRecipient = evmWordToAddress(receipt.logs?.[0].topics?.[2])
- assert.equal(emittedRecipient, await roles.stranger.getAddress())
- })
-
- it('proposes a transfer to the recipient with the specified message', async () => {
- const emittedOwner = evmWordToAddress(receipt.logs?.[1].topics?.[1])
- assert.equal(emittedOwner, await roles.oracleNode.getAddress())
- const emittedRecipient = evmWordToAddress(receipt.logs?.[1].topics?.[2])
- assert.equal(emittedRecipient, await roles.stranger.getAddress())
-
- const encodedMessage = ethers.utils.defaultAbiCoder.encode(
- ['bytes'],
- [message],
- )
- assert.equal(receipt?.logs?.[1]?.data, encodedMessage)
- })
-
- it('records that it deployed that address', async () => {
- assert.isTrue(await operatorGenerator.created(emittedForwarder))
- })
- })
-})
diff --git a/contracts/test/v0.7/StalenessFlaggingValidator.test.ts b/contracts/test/v0.7/StalenessFlaggingValidator.test.ts
deleted file mode 100644
index 8a5c4b6763..0000000000
--- a/contracts/test/v0.7/StalenessFlaggingValidator.test.ts
+++ /dev/null
@@ -1,632 +0,0 @@
-import { ethers } from 'hardhat'
-import {
- evmWordToAddress,
- getLog,
- getLogs,
- numToBytes32,
- publicAbi,
-} from '../test-helpers/helpers'
-import { assert, expect } from 'chai'
-import { BigNumber, Contract, ContractFactory } from 'ethers'
-import { Personas, getUsers } from '../test-helpers/setup'
-import { evmRevert } from '../test-helpers/matchers'
-
-let personas: Personas
-let validatorFactory: ContractFactory
-let flagsFactory: ContractFactory
-let acFactory: ContractFactory
-let aggregatorFactory: ContractFactory
-
-before(async () => {
- personas = (await getUsers()).personas
-
- validatorFactory = await ethers.getContractFactory(
- 'src/v0.7/dev/StalenessFlaggingValidator.sol:StalenessFlaggingValidator',
- personas.Carol,
- )
- flagsFactory = await ethers.getContractFactory(
- 'src/v0.6/Flags.sol:Flags',
- personas.Carol,
- )
- acFactory = await ethers.getContractFactory(
- 'src/v0.6/SimpleWriteAccessController.sol:SimpleWriteAccessController',
- personas.Carol,
- )
- aggregatorFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator',
- personas.Carol,
- )
-})
-
-describe('StalenessFlaggingValidator', () => {
- let validator: Contract
- let flags: Contract
- let ac: Contract
-
- const flaggingThreshold1 = 10000
- const flaggingThreshold2 = 20000
-
- beforeEach(async () => {
- ac = await acFactory.connect(personas.Carol).deploy()
- flags = await flagsFactory.connect(personas.Carol).deploy(ac.address)
- validator = await validatorFactory
- .connect(personas.Carol)
- .deploy(flags.address)
-
- await ac.connect(personas.Carol).addAccess(validator.address)
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(validator, [
- 'update',
- 'check',
- 'setThresholds',
- 'setFlagsAddress',
- 'threshold',
- 'flags',
- // Upkeep methods:
- 'checkUpkeep',
- 'performUpkeep',
- // Owned methods:
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- ])
- })
-
- describe('#constructor', () => {
- it('sets the arguments passed in', async () => {
- assert.equal(await validator.flags(), flags.address)
- })
-
- it('sets the owner', async () => {
- assert.equal(await validator.owner(), await personas.Carol.getAddress())
- })
- })
-
- describe('#setFlagsAddress', () => {
- const newFlagsAddress = '0x0123456789012345678901234567890123456789'
-
- it('changes the flags address', async () => {
- assert.equal(flags.address, await validator.flags())
-
- await validator.connect(personas.Carol).setFlagsAddress(newFlagsAddress)
-
- assert.equal(newFlagsAddress, await validator.flags())
- })
-
- it('emits a log event only when actually changed', async () => {
- const tx = await validator
- .connect(personas.Carol)
- .setFlagsAddress(newFlagsAddress)
- await expect(tx)
- .to.emit(validator, 'FlagsAddressUpdated')
- .withArgs(flags.address, newFlagsAddress)
-
- const sameChangeTx = await validator
- .connect(personas.Carol)
- .setFlagsAddress(newFlagsAddress)
-
- await expect(sameChangeTx).to.not.emit(validator, 'FlagsAddressUpdated')
- })
-
- describe('when called by a non-owner', () => {
- it('reverts', async () => {
- await evmRevert(
- validator.connect(personas.Neil).setFlagsAddress(newFlagsAddress),
- 'Only callable by owner',
- )
- })
- })
- })
-
- describe('#setThresholds', () => {
- let agg1: Contract
- let agg2: Contract
- let aggregators: Array
- let thresholds: Array
-
- beforeEach(async () => {
- const decimals = 8
- const initialAnswer = 10000000000
- agg1 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- agg2 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- })
-
- describe('failure', () => {
- beforeEach(() => {
- aggregators = [agg1.address, agg2.address]
- thresholds = [flaggingThreshold1]
- })
-
- it('reverts when called by a non-owner', async () => {
- await evmRevert(
- validator
- .connect(personas.Neil)
- .setThresholds(aggregators, thresholds),
- 'Only callable by owner',
- )
- })
-
- it('reverts when passed uneven arrays', async () => {
- await evmRevert(
- validator
- .connect(personas.Carol)
- .setThresholds(aggregators, thresholds),
- 'Different sized arrays',
- )
- })
- })
-
- describe('success', () => {
- let tx: any
-
- beforeEach(() => {
- aggregators = [agg1.address, agg2.address]
- thresholds = [flaggingThreshold1, flaggingThreshold2]
- })
-
- describe('when called with 2 new thresholds', () => {
- beforeEach(async () => {
- tx = await validator
- .connect(personas.Carol)
- .setThresholds(aggregators, thresholds)
- })
-
- it('sets the thresholds', async () => {
- const first = await validator.threshold(agg1.address)
- const second = await validator.threshold(agg2.address)
- assert.equal(first.toString(), flaggingThreshold1.toString())
- assert.equal(second.toString(), flaggingThreshold2.toString())
- })
-
- it('emits events', async () => {
- const firstEvent = await getLog(tx, 0)
- assert.equal(evmWordToAddress(firstEvent.topics[1]), agg1.address)
- assert.equal(firstEvent.topics[3], numToBytes32(flaggingThreshold1))
- const secondEvent = await getLog(tx, 1)
- assert.equal(evmWordToAddress(secondEvent.topics[1]), agg2.address)
- assert.equal(secondEvent.topics[3], numToBytes32(flaggingThreshold2))
- })
- })
-
- describe('when called with 2, but 1 has not changed', () => {
- it('emits only 1 event', async () => {
- tx = await validator
- .connect(personas.Carol)
- .setThresholds(aggregators, thresholds)
-
- const newThreshold = flaggingThreshold2 + 1
- tx = await validator
- .connect(personas.Carol)
- .setThresholds(aggregators, [flaggingThreshold1, newThreshold])
- const logs = await getLogs(tx)
- assert.equal(logs.length, 1)
- const log = logs[0]
- assert.equal(evmWordToAddress(log.topics[1]), agg2.address)
- assert.equal(log.topics[2], numToBytes32(flaggingThreshold2))
- assert.equal(log.topics[3], numToBytes32(newThreshold))
- })
- })
- })
- })
-
- describe('#check', () => {
- let agg1: Contract
- let agg2: Contract
- let aggregators: Array
- let thresholds: Array
- const decimals = 8
- const initialAnswer = 10000000000
- beforeEach(async () => {
- agg1 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- agg2 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- aggregators = [agg1.address, agg2.address]
- thresholds = [flaggingThreshold1, flaggingThreshold2]
- await validator.setThresholds(aggregators, thresholds)
- })
-
- describe('when neither are stale', () => {
- it('returns an empty array', async () => {
- const response = await validator.check(aggregators)
- assert.equal(response.length, 0)
- })
- })
-
- describe('when threshold is not set in the validator', () => {
- it('returns an empty array', async () => {
- const agg3 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- const response = await validator.check([agg3.address])
- assert.equal(response.length, 0)
- })
- })
-
- describe('when one of the aggregators is stale', () => {
- it('returns an array with one stale aggregator', async () => {
- const currentTimestamp = await agg1.latestTimestamp()
- const staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
- const response = await validator.check(aggregators)
-
- assert.equal(response.length, 1)
- assert.equal(response[0], agg1.address)
- })
- })
-
- describe('When both aggregators are stale', () => {
- it('returns an array with both aggregators', async () => {
- let currentTimestamp = await agg1.latestTimestamp()
- let staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- currentTimestamp = await agg2.latestTimestamp()
- staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold2 + 1),
- )
- await agg2.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const response = await validator.check(aggregators)
-
- assert.equal(response.length, 2)
- assert.equal(response[0], agg1.address)
- assert.equal(response[1], agg2.address)
- })
- })
- })
-
- describe('#update', () => {
- let agg1: Contract
- let agg2: Contract
- let aggregators: Array
- let thresholds: Array
- const decimals = 8
- const initialAnswer = 10000000000
- beforeEach(async () => {
- agg1 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- agg2 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- aggregators = [agg1.address, agg2.address]
- thresholds = [flaggingThreshold1, flaggingThreshold2]
- await validator.setThresholds(aggregators, thresholds)
- })
-
- describe('when neither are stale', () => {
- it('does not raise a flag', async () => {
- const tx = await validator.update(aggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
-
- describe('when threshold is not set in the validator', () => {
- it('does not raise a flag', async () => {
- const agg3 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- const tx = await validator.update([agg3.address])
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
-
- describe('when one is stale', () => {
- it('raises a flag for that aggregator', async () => {
- const currentTimestamp = await agg1.latestTimestamp()
- const staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const tx = await validator.update(aggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 1)
- assert.equal(evmWordToAddress(logs[0].topics[1]), agg1.address)
- })
- })
-
- describe('when both are stale', () => {
- it('raises 2 flags, one for each aggregator', async () => {
- let currentTimestamp = await agg1.latestTimestamp()
- let staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- currentTimestamp = await agg2.latestTimestamp()
- staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold2 + 1),
- )
- await agg2.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const tx = await validator.update(aggregators)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 2)
- assert.equal(evmWordToAddress(logs[0].topics[1]), agg1.address)
- assert.equal(evmWordToAddress(logs[1].topics[1]), agg2.address)
- })
- })
- })
-
- describe('#checkUpkeep', () => {
- let agg1: Contract
- let agg2: Contract
- let aggregators: Array
- let thresholds: Array
- const decimals = 8
- const initialAnswer = 10000000000
- beforeEach(async () => {
- agg1 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- agg2 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- aggregators = [agg1.address, agg2.address]
- thresholds = [flaggingThreshold1, flaggingThreshold2]
- await validator.setThresholds(aggregators, thresholds)
- })
-
- describe('when neither are stale', () => {
- it('returns false and an empty array', async () => {
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const response = await validator.checkUpkeep(bytesData)
-
- assert.equal(response[0], false)
- const decodedResponse = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- response?.[1],
- )
- assert.equal(decodedResponse[0].length, 0)
- })
- })
-
- describe('when threshold is not set in the validator', () => {
- it('returns flase and an empty array', async () => {
- const agg3 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [[agg3.address]],
- )
- const response = await validator.checkUpkeep(bytesData)
-
- assert.equal(response[0], false)
- const decodedResponse = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- response?.[1],
- )
- assert.equal(decodedResponse[0].length, 0)
- })
- })
-
- describe('when one of the aggregators is stale', () => {
- it('returns true with an array with one stale aggregator', async () => {
- const currentTimestamp = await agg1.latestTimestamp()
- const staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const response = await validator.checkUpkeep(bytesData)
-
- assert.equal(response[0], true)
- const decodedResponse = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- response?.[1],
- )
- const decodedArray = decodedResponse[0]
- assert.equal(decodedArray.length, 1)
- assert.equal(decodedArray[0], agg1.address)
- })
- })
-
- describe('When both aggregators are stale', () => {
- it('returns true with an array with both aggregators', async () => {
- let currentTimestamp = await agg1.latestTimestamp()
- let staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- currentTimestamp = await agg2.latestTimestamp()
- staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold2 + 1),
- )
- await agg2.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const response = await validator.checkUpkeep(bytesData)
-
- assert.equal(response[0], true)
- const decodedResponse = ethers.utils.defaultAbiCoder.decode(
- ['address[]'],
- response?.[1],
- )
- const decodedArray = decodedResponse[0]
- assert.equal(decodedArray.length, 2)
- assert.equal(decodedArray[0], agg1.address)
- assert.equal(decodedArray[1], agg2.address)
- })
- })
- })
-
- describe('#performUpkeep', () => {
- let agg1: Contract
- let agg2: Contract
- let aggregators: Array
- let thresholds: Array
- const decimals = 8
- const initialAnswer = 10000000000
- beforeEach(async () => {
- agg1 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- agg2 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- aggregators = [agg1.address, agg2.address]
- thresholds = [flaggingThreshold1, flaggingThreshold2]
- await validator.setThresholds(aggregators, thresholds)
- })
-
- describe('when neither are stale', () => {
- it('does not raise a flag', async () => {
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const tx = await validator.performUpkeep(bytesData)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
-
- describe('when threshold is not set in the validator', () => {
- it('does not raise a flag', async () => {
- const agg3 = await aggregatorFactory
- .connect(personas.Carol)
- .deploy(decimals, initialAnswer)
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [[agg3.address]],
- )
- const tx = await validator.performUpkeep(bytesData)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
-
- describe('when one is stale', () => {
- it('raises a flag for that aggregator', async () => {
- const currentTimestamp = await agg1.latestTimestamp()
- const staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const tx = await validator.performUpkeep(bytesData)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 1)
- assert.equal(evmWordToAddress(logs[0].topics[1]), agg1.address)
- })
- })
-
- describe('when both are stale', () => {
- it('raises 2 flags, one for each aggregator', async () => {
- let currentTimestamp = await agg1.latestTimestamp()
- let staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold1 + 1),
- )
- await agg1.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- currentTimestamp = await agg2.latestTimestamp()
- staleTimestamp = currentTimestamp.sub(
- BigNumber.from(flaggingThreshold2 + 1),
- )
- await agg2.updateRoundData(
- 99,
- initialAnswer,
- staleTimestamp,
- staleTimestamp,
- )
-
- const bytesData = ethers.utils.defaultAbiCoder.encode(
- ['address[]'],
- [aggregators],
- )
- const tx = await validator.performUpkeep(bytesData)
- const logs = await getLogs(tx)
- assert.equal(logs.length, 2)
- assert.equal(evmWordToAddress(logs[0].topics[1]), agg1.address)
- assert.equal(evmWordToAddress(logs[1].topics[1]), agg2.address)
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/UpkeepRegistrationRequests.test.ts b/contracts/test/v0.7/UpkeepRegistrationRequests.test.ts
deleted file mode 100644
index 5ec9306c66..0000000000
--- a/contracts/test/v0.7/UpkeepRegistrationRequests.test.ts
+++ /dev/null
@@ -1,603 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert, expect } from 'chai'
-import { evmRevert } from '../test-helpers/matchers'
-import { getUsers, Personas } from '../test-helpers/setup'
-import { BigNumber, Signer } from 'ethers'
-import { LinkToken__factory as LinkTokenFactory } from '../../typechain/factories/LinkToken__factory'
-import { KeeperRegistry1_1__factory as KeeperRegistryFactory } from '../../typechain/factories/KeeperRegistry1_1__factory'
-import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../typechain/factories/MockV3Aggregator__factory'
-import { UpkeepRegistrationRequests__factory as UpkeepRegistrationRequestsFactory } from '../../typechain/factories/UpkeepRegistrationRequests__factory'
-import { UpkeepMock__factory as UpkeepMockFactory } from '../../typechain/factories/UpkeepMock__factory'
-import { KeeperRegistry1_1 as KeeperRegistry } from '../../typechain/KeeperRegistry1_1'
-import { UpkeepRegistrationRequests } from '../../typechain/UpkeepRegistrationRequests'
-import { MockV3Aggregator } from '../../typechain/MockV3Aggregator'
-import { LinkToken } from '../../typechain/LinkToken'
-import { UpkeepMock } from '../../typechain/UpkeepMock'
-
-let linkTokenFactory: LinkTokenFactory
-let mockV3AggregatorFactory: MockV3AggregatorFactory
-let keeperRegistryFactory: KeeperRegistryFactory
-let upkeepRegistrationRequestsFactory: UpkeepRegistrationRequestsFactory
-let upkeepMockFactory: UpkeepMockFactory
-
-let personas: Personas
-
-before(async () => {
- personas = (await getUsers()).personas
-
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- )
- mockV3AggregatorFactory = (await ethers.getContractFactory(
- 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator',
- )) as unknown as MockV3AggregatorFactory
- // @ts-ignore bug in autogen file
- keeperRegistryFactory = await ethers.getContractFactory('KeeperRegistry1_1')
- upkeepRegistrationRequestsFactory = await ethers.getContractFactory(
- 'UpkeepRegistrationRequests',
- )
- upkeepMockFactory = await ethers.getContractFactory('UpkeepMock')
-})
-
-const errorMsgs = {
- onlyOwner: 'revert Only callable by owner',
- onlyAdmin: 'only admin / owner can cancel',
- hashPayload: 'hash and payload do not match',
- requestNotFound: 'request not found',
-}
-
-describe('UpkeepRegistrationRequests', () => {
- const upkeepName = 'SampleUpkeep'
-
- const linkEth = BigNumber.from(300000000)
- const gasWei = BigNumber.from(100)
- const executeGas = BigNumber.from(100000)
- const source = BigNumber.from(100)
- const paymentPremiumPPB = BigNumber.from(250000000)
- const flatFeeMicroLink = BigNumber.from(0)
-
- const window_big = BigNumber.from(1000)
- const window_small = BigNumber.from(2)
- const threshold_big = BigNumber.from(1000)
- const threshold_small = BigNumber.from(5)
-
- const blockCountPerTurn = BigNumber.from(3)
- const emptyBytes = '0x00'
- const stalenessSeconds = BigNumber.from(43820)
- const gasCeilingMultiplier = BigNumber.from(1)
- const maxCheckGas = BigNumber.from(20000000)
- const fallbackGasPrice = BigNumber.from(200)
- const fallbackLinkPrice = BigNumber.from(200000000)
- const minLINKJuels = BigNumber.from('1000000000000000000')
- const amount = BigNumber.from('5000000000000000000')
- const amount1 = BigNumber.from('6000000000000000000')
-
- let owner: Signer
- let admin: Signer
- let someAddress: Signer
- let registrarOwner: Signer
- let stranger: Signer
-
- let linkToken: LinkToken
- let linkEthFeed: MockV3Aggregator
- let gasPriceFeed: MockV3Aggregator
- let registry: KeeperRegistry
- let mock: UpkeepMock
- let registrar: UpkeepRegistrationRequests
-
- beforeEach(async () => {
- owner = personas.Default
- admin = personas.Neil
- someAddress = personas.Ned
- registrarOwner = personas.Nelly
- stranger = personas.Nancy
-
- linkToken = await linkTokenFactory.connect(owner).deploy()
- gasPriceFeed = await mockV3AggregatorFactory
- .connect(owner)
- .deploy(0, gasWei)
- linkEthFeed = await mockV3AggregatorFactory
- .connect(owner)
- .deploy(9, linkEth)
- registry = await keeperRegistryFactory
- .connect(owner)
- .deploy(
- linkToken.address,
- linkEthFeed.address,
- gasPriceFeed.address,
- paymentPremiumPPB,
- flatFeeMicroLink,
- blockCountPerTurn,
- maxCheckGas,
- stalenessSeconds,
- gasCeilingMultiplier,
- fallbackGasPrice,
- fallbackLinkPrice,
- )
-
- mock = await upkeepMockFactory.deploy()
-
- registrar = await upkeepRegistrationRequestsFactory
- .connect(registrarOwner)
- .deploy(linkToken.address, minLINKJuels)
-
- await registry.setRegistrar(registrar.address)
- })
-
- describe('#typeAndVersion', () => {
- it('uses the correct type and version', async () => {
- const typeAndVersion = await registrar.typeAndVersion()
- assert.equal(typeAndVersion, 'UpkeepRegistrationRequests 1.0.0')
- })
- })
-
- describe('#register', () => {
- it('reverts if not called by the LINK token', async () => {
- await evmRevert(
- registrar
- .connect(someAddress)
- .register(
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ),
- 'Must use LINK token',
- )
- })
-
- it('reverts if the amount passed in data mismatches actual amount sent', async () => {
- await registrar
- .connect(registrarOwner)
- .setRegistrationConfig(
- true,
- window_small,
- threshold_big,
- registry.address,
- minLINKJuels,
- )
-
- const abiEncodedBytes = registrar.interface.encodeFunctionData(
- 'register',
- [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount1,
- source,
- ],
- )
-
- await evmRevert(
- linkToken.transferAndCall(registrar.address, amount, abiEncodedBytes),
- 'Amount mismatch',
- )
- })
-
- it('reverts if the admin address is 0x0000...', async () => {
- const abiEncodedBytes = registrar.interface.encodeFunctionData(
- 'register',
- [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- '0x0000000000000000000000000000000000000000',
- emptyBytes,
- amount,
- source,
- ],
- )
-
- await evmRevert(
- linkToken.transferAndCall(registrar.address, amount, abiEncodedBytes),
- 'Unable to create request',
- )
- })
-
- it('Auto Approve ON - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => {
- //get current upkeep count
- const upkeepCount = await registry.getUpkeepCount()
-
- //set auto approve ON with high threshold limits
- await registrar
- .connect(registrarOwner)
- .setRegistrationConfig(
- true,
- window_small,
- threshold_big,
- registry.address,
- minLINKJuels,
- )
-
- //register with auto approve ON
- const abiEncodedBytes = registrar.interface.encodeFunctionData(
- 'register',
- [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ],
- )
- const tx = await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
-
- //confirm if a new upkeep has been registered and the details are the same as the one just registered
- const newupkeep = await registry.getUpkeep(upkeepCount)
- assert.equal(newupkeep.target, mock.address)
- assert.equal(newupkeep.admin, await admin.getAddress())
- assert.equal(newupkeep.checkData, emptyBytes)
- assert.equal(newupkeep.balance.toString(), amount.toString())
- assert.equal(newupkeep.executeGas, executeGas.toNumber())
-
- await expect(tx).to.emit(registrar, 'RegistrationRequested')
- await expect(tx).to.emit(registrar, 'RegistrationApproved')
- })
-
- it('Auto Approve OFF - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => {
- //get upkeep count before attempting registration
- const beforeCount = await registry.getUpkeepCount()
-
- //set auto approve OFF, threshold limits dont matter in this case
- await registrar
- .connect(registrarOwner)
- .setRegistrationConfig(
- false,
- window_small,
- threshold_big,
- registry.address,
- minLINKJuels,
- )
-
- //register with auto approve OFF
- const abiEncodedBytes = registrar.interface.encodeFunctionData(
- 'register',
- [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ],
- )
- const tx = await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
- const receipt = await tx.wait()
-
- //get upkeep count after attempting registration
- const afterCount = await registry.getUpkeepCount()
- //confirm that a new upkeep has NOT been registered and upkeep count is still the same
- assert.deepEqual(beforeCount, afterCount)
-
- //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not
- await expect(tx).to.emit(registrar, 'RegistrationRequested')
- await expect(tx).not.to.emit(registrar, 'RegistrationApproved')
-
- const hash = receipt.logs[2].topics[1]
- const pendingRequest = await registrar.getPendingRequest(hash)
- assert.equal(await admin.getAddress(), pendingRequest[0])
- assert.ok(amount.eq(pendingRequest[1]))
- })
-
- it('Auto Approve ON - Throttle max approvals - does not registers an upkeep on KeeperRegistry beyond the throttle limit, emits only RegistrationRequested event after throttle starts', async () => {
- //get upkeep count before attempting registration
- const beforeCount = await registry.getUpkeepCount()
-
- //set auto approve on, with low threshold limits
- await registrar
- .connect(registrarOwner)
- .setRegistrationConfig(
- true,
- window_big,
- threshold_small,
- registry.address,
- minLINKJuels,
- )
-
- let abiEncodedBytes = registrar.interface.encodeFunctionData('register', [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ])
-
- //register within threshold, new upkeep should be registered
- await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
- const intermediateCount = await registry.getUpkeepCount()
- //make sure 1 upkeep was registered
- assert.equal(beforeCount.toNumber() + 1, intermediateCount.toNumber())
-
- //try registering more than threshold(say 2x), new upkeeps should not be registered after the threshold amount is reached
- for (let step = 0; step < threshold_small.toNumber() * 2; step++) {
- abiEncodedBytes = registrar.interface.encodeFunctionData('register', [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas.toNumber() + step, // make unique hash
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ])
-
- await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
- }
- const afterCount = await registry.getUpkeepCount()
- //count of newly registered upkeeps should be equal to the threshold set for auto approval
- const newRegistrationsCount =
- afterCount.toNumber() - beforeCount.toNumber()
- assert(
- newRegistrationsCount == threshold_small.toNumber(),
- 'Registrations beyond threshold',
- )
- })
- })
-
- describe('#approve', () => {
- let hash: string
-
- beforeEach(async () => {
- await registrar
- .connect(registrarOwner)
- .setRegistrationConfig(
- false,
- window_small,
- threshold_big,
- registry.address,
- minLINKJuels,
- )
-
- //register with auto approve OFF
- const abiEncodedBytes = registrar.interface.encodeFunctionData(
- 'register',
- [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ],
- )
-
- const tx = await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
- const receipt = await tx.wait()
- hash = receipt.logs[2].topics[1]
- })
-
- it('reverts if not called by the owner', async () => {
- const tx = registrar
- .connect(stranger)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- await evmRevert(tx, 'Only callable by owner')
- })
-
- it('reverts if the hash does not exist', async () => {
- const tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44',
- )
- await evmRevert(tx, errorMsgs.requestNotFound)
- })
-
- it('reverts if any member of the payload changes', async () => {
- let tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- ethers.Wallet.createRandom().address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- await evmRevert(tx, errorMsgs.hashPayload)
- tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- 10000,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- await evmRevert(tx, errorMsgs.hashPayload)
- tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- ethers.Wallet.createRandom().address,
- emptyBytes,
- hash,
- )
- await evmRevert(tx, errorMsgs.hashPayload)
- tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- '0x1234',
- hash,
- )
- await evmRevert(tx, errorMsgs.hashPayload)
- })
-
- it('approves an existing registration request', async () => {
- const tx = await registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- await expect(tx).to.emit(registrar, 'RegistrationApproved')
- })
-
- it('deletes the request afterwards / reverts if the request DNE', async () => {
- await registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- const tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- await evmRevert(tx, errorMsgs.requestNotFound)
- })
- })
-
- describe('#cancel', () => {
- let hash: string
-
- beforeEach(async () => {
- await registrar
- .connect(registrarOwner)
- .setRegistrationConfig(
- false,
- window_small,
- threshold_big,
- registry.address,
- minLINKJuels,
- )
-
- //register with auto approve OFF
- const abiEncodedBytes = registrar.interface.encodeFunctionData(
- 'register',
- [
- upkeepName,
- emptyBytes,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- amount,
- source,
- ],
- )
- const tx = await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
- const receipt = await tx.wait()
- hash = receipt.logs[2].topics[1]
- // submit duplicate request (increase balance)
- await linkToken.transferAndCall(
- registrar.address,
- amount,
- abiEncodedBytes,
- )
- })
-
- it('reverts if not called by the admin / owner', async () => {
- const tx = registrar.connect(stranger).cancel(hash)
- await evmRevert(tx, errorMsgs.onlyAdmin)
- })
-
- it('reverts if the hash does not exist', async () => {
- const tx = registrar
- .connect(registrarOwner)
- .cancel(
- '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44',
- )
- await evmRevert(tx, 'request not found')
- })
-
- it('refunds the total request balance to the admin address', async () => {
- const before = await linkToken.balanceOf(await admin.getAddress())
- const tx = await registrar.connect(admin).cancel(hash)
- const after = await linkToken.balanceOf(await admin.getAddress())
- assert.isTrue(after.sub(before).eq(amount.mul(BigNumber.from(2))))
- await expect(tx).to.emit(registrar, 'RegistrationRejected')
- })
-
- it('deletes the request hash', async () => {
- await registrar.connect(registrarOwner).cancel(hash)
- let tx = registrar.connect(registrarOwner).cancel(hash)
- await evmRevert(tx, errorMsgs.requestNotFound)
- tx = registrar
- .connect(registrarOwner)
- .approve(
- upkeepName,
- mock.address,
- executeGas,
- await admin.getAddress(),
- emptyBytes,
- hash,
- )
- await evmRevert(tx, errorMsgs.requestNotFound)
- })
- })
-})
diff --git a/contracts/test/v0.7/VRFD20.test.ts b/contracts/test/v0.7/VRFD20.test.ts
deleted file mode 100644
index f1e0e9ab0a..0000000000
--- a/contracts/test/v0.7/VRFD20.test.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-import { ethers } from 'hardhat'
-import { assert, expect } from 'chai'
-import {
- BigNumber,
- constants,
- Contract,
- ContractFactory,
- ContractTransaction,
-} from 'ethers'
-import { getUsers, Personas, Roles } from '../test-helpers/setup'
-import {
- evmWordToAddress,
- getLog,
- publicAbi,
- toBytes32String,
- toWei,
- numToBytes32,
- getLogs,
-} from '../test-helpers/helpers'
-
-let roles: Roles
-let personas: Personas
-let linkTokenFactory: ContractFactory
-let vrfCoordinatorMockFactory: ContractFactory
-let vrfD20Factory: ContractFactory
-
-before(async () => {
- const users = await getUsers()
-
- roles = users.roles
- personas = users.personas
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
- vrfCoordinatorMockFactory = await ethers.getContractFactory(
- 'src/v0.7/tests/VRFCoordinatorMock.sol:VRFCoordinatorMock',
- roles.defaultAccount,
- )
- vrfD20Factory = await ethers.getContractFactory(
- 'src/v0.6/examples/VRFD20.sol:VRFD20',
- roles.defaultAccount,
- )
-})
-
-describe('VRFD20', () => {
- const deposit = toWei('1')
- const fee = toWei('0.1')
- const keyHash = toBytes32String('keyHash')
-
- let link: Contract
- let vrfCoordinator: Contract
- let vrfD20: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
- vrfCoordinator = await vrfCoordinatorMockFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
- vrfD20 = await vrfD20Factory
- .connect(roles.defaultAccount)
- .deploy(vrfCoordinator.address, link.address, keyHash, fee)
- await link.transfer(vrfD20.address, deposit)
- })
-
- it('has a limited public interface [ @skip-coverage ]', () => {
- publicAbi(vrfD20, [
- // Owned
- 'acceptOwnership',
- 'owner',
- 'transferOwnership',
- //VRFConsumerBase
- 'rawFulfillRandomness',
- // VRFD20
- 'rollDice',
- 'house',
- 'withdrawLINK',
- 'keyHash',
- 'fee',
- 'setKeyHash',
- 'setFee',
- ])
- })
-
- describe('#withdrawLINK', () => {
- describe('failure', () => {
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20
- .connect(roles.stranger)
- .withdrawLINK(await roles.stranger.getAddress(), deposit),
- ).to.be.revertedWith('Only callable by owner')
- })
-
- it('reverts when not enough LINK in the contract', async () => {
- const withdrawAmount = deposit.mul(2)
- await expect(
- vrfD20
- .connect(roles.defaultAccount)
- .withdrawLINK(
- await roles.defaultAccount.getAddress(),
- withdrawAmount,
- ),
- ).to.be.reverted
- })
- })
-
- describe('success', () => {
- it('withdraws LINK', async () => {
- const startingAmount = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
- const expectedAmount = BigNumber.from(startingAmount).add(deposit)
- await vrfD20
- .connect(roles.defaultAccount)
- .withdrawLINK(await roles.defaultAccount.getAddress(), deposit)
- const actualAmount = await link.balanceOf(
- await roles.defaultAccount.getAddress(),
- )
- assert.equal(actualAmount.toString(), expectedAmount.toString())
- })
- })
- })
-
- describe('#setKeyHash', () => {
- const newHash = toBytes32String('newhash')
-
- describe('failure', () => {
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20.connect(roles.stranger).setKeyHash(newHash),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('success', () => {
- it('sets the key hash', async () => {
- await vrfD20.setKeyHash(newHash)
- const actualHash = await vrfD20.keyHash()
- assert.equal(actualHash, newHash)
- })
- })
- })
-
- describe('#setFee', () => {
- const newFee = 1234
-
- describe('failure', () => {
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20.connect(roles.stranger).setFee(newFee),
- ).to.be.revertedWith('Only callable by owner')
- })
- })
-
- describe('success', () => {
- it('sets the fee', async () => {
- await vrfD20.setFee(newFee)
- const actualFee = await vrfD20.fee()
- assert.equal(actualFee.toString(), newFee.toString())
- })
- })
- })
-
- describe('#house', () => {
- describe('failure', () => {
- it('reverts when dice not rolled', async () => {
- await expect(
- vrfD20.house(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Dice not rolled')
- })
-
- it('reverts when dice roll is in progress', async () => {
- await vrfD20.rollDice(await personas.Nancy.getAddress())
- await expect(
- vrfD20.house(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Roll in progress')
- })
- })
-
- describe('success', () => {
- it('returns the correct house', async () => {
- const randomness = 98765
- const expectedHouse = 'Martell'
- const tx = await vrfD20.rollDice(await personas.Nancy.getAddress())
- const log = await getLog(tx, 3)
- const eventRequestId = log?.topics?.[1]
- await vrfCoordinator.callBackWithRandomness(
- eventRequestId,
- randomness,
- vrfD20.address,
- )
- const response = await vrfD20.house(await personas.Nancy.getAddress())
- assert.equal(response.toString(), expectedHouse)
- })
- })
- })
-
- describe('#rollDice', () => {
- describe('success', () => {
- let tx: ContractTransaction
- beforeEach(async () => {
- tx = await vrfD20.rollDice(await personas.Nancy.getAddress())
- })
-
- it('emits a RandomnessRequest event from the VRFCoordinator', async () => {
- const log = await getLog(tx, 2)
- const topics = log?.topics
- assert.equal(evmWordToAddress(topics?.[1]), vrfD20.address)
- assert.equal(topics?.[2], keyHash)
- assert.equal(topics?.[3], constants.HashZero)
- })
- })
-
- describe('failure', () => {
- it('reverts when LINK balance is zero', async () => {
- const vrfD202 = await vrfD20Factory
- .connect(roles.defaultAccount)
- .deploy(vrfCoordinator.address, link.address, keyHash, fee)
- await expect(
- vrfD202.rollDice(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Not enough LINK to pay fee')
- })
-
- it('reverts when called by a non-owner', async () => {
- await expect(
- vrfD20
- .connect(roles.stranger)
- .rollDice(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Only callable by owner')
- })
-
- it('reverts when the roller rolls more than once', async () => {
- await vrfD20.rollDice(await personas.Nancy.getAddress())
- await expect(
- vrfD20.rollDice(await personas.Nancy.getAddress()),
- ).to.be.revertedWith('Already rolled')
- })
- })
- })
-
- describe('#fulfillRandomness', () => {
- const randomness = 98765
- const expectedModResult = (randomness % 20) + 1
- const expectedHouse = 'Martell'
- let eventRequestId: string
- beforeEach(async () => {
- const tx = await vrfD20.rollDice(await personas.Nancy.getAddress())
- const log = await getLog(tx, 3)
- eventRequestId = log?.topics?.[1]
- })
-
- describe('success', () => {
- let tx: ContractTransaction
- beforeEach(async () => {
- tx = await vrfCoordinator.callBackWithRandomness(
- eventRequestId,
- randomness,
- vrfD20.address,
- )
- })
-
- it('emits a DiceLanded event', async () => {
- const log = await getLog(tx, 0)
- assert.equal(log?.topics[1], eventRequestId)
- assert.equal(log?.topics[2], numToBytes32(expectedModResult))
- })
-
- it('sets the correct dice roll result', async () => {
- const response = await vrfD20.house(await personas.Nancy.getAddress())
- assert.equal(response.toString(), expectedHouse)
- })
-
- it('allows someone else to roll', async () => {
- const secondRandomness = 55555
- tx = await vrfD20.rollDice(await personas.Ned.getAddress())
- const log = await getLog(tx, 3)
- eventRequestId = log?.topics?.[1]
- tx = await vrfCoordinator.callBackWithRandomness(
- eventRequestId,
- secondRandomness,
- vrfD20.address,
- )
- })
- })
-
- describe('failure', () => {
- it('does not fulfill when fulfilled by the wrong VRFcoordinator', async () => {
- const vrfCoordinator2 = await vrfCoordinatorMockFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
-
- const tx = await vrfCoordinator2.callBackWithRandomness(
- eventRequestId,
- randomness,
- vrfD20.address,
- )
- const logs = await getLogs(tx)
- assert.equal(logs.length, 0)
- })
- })
- })
-})
diff --git a/contracts/test/v0.7/gasUsage.test.ts b/contracts/test/v0.7/gasUsage.test.ts
deleted file mode 100644
index 97146622d0..0000000000
--- a/contracts/test/v0.7/gasUsage.test.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import { ethers } from 'hardhat'
-import { toBytes32String, toWei } from '../test-helpers/helpers'
-import { Contract, ContractFactory } from 'ethers'
-import { getUsers, Roles } from '../test-helpers/setup'
-import {
- convertFufillParams,
- convertFulfill2Params,
- decodeRunRequest,
-} from '../test-helpers/oracle'
-import { gasDiffLessThan } from '../test-helpers/matchers'
-
-let operatorFactory: ContractFactory
-let oracleFactory: ContractFactory
-let basicConsumerFactory: ContractFactory
-let linkTokenFactory: ContractFactory
-
-let roles: Roles
-
-before(async () => {
- const users = await getUsers()
-
- roles = users.roles
- operatorFactory = await ethers.getContractFactory(
- 'src/v0.7/Operator.sol:Operator',
- roles.defaultAccount,
- )
- oracleFactory = await ethers.getContractFactory(
- 'src/v0.6/Oracle.sol:Oracle',
- roles.defaultAccount,
- )
- basicConsumerFactory = await ethers.getContractFactory(
- 'src/v0.6/tests/BasicConsumer.sol:BasicConsumer',
- roles.defaultAccount,
- )
- linkTokenFactory = await ethers.getContractFactory(
- 'src/v0.4/LinkToken.sol:LinkToken',
- roles.defaultAccount,
- )
-})
-
-describe('Operator Gas Tests [ @skip-coverage ]', () => {
- const specId =
- '0x4c7b7ffb66b344fbaa64995af81e355a00000000000000000000000000000000'
- let link: Contract
- let oracle1: Contract
- let operator1: Contract
- let operator2: Contract
-
- beforeEach(async () => {
- link = await linkTokenFactory.connect(roles.defaultAccount).deploy()
-
- operator1 = await operatorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, await roles.defaultAccount.getAddress())
- await operator1.setAuthorizedSenders([await roles.oracleNode.getAddress()])
-
- operator2 = await operatorFactory
- .connect(roles.defaultAccount)
- .deploy(link.address, await roles.defaultAccount.getAddress())
- await operator2.setAuthorizedSenders([await roles.oracleNode.getAddress()])
-
- oracle1 = await oracleFactory
- .connect(roles.defaultAccount)
- .deploy(link.address)
- await oracle1.setFulfillmentPermission(
- await roles.oracleNode.getAddress(),
- true,
- )
- })
-
- // Test Oracle.fulfillOracleRequest vs Operator.fulfillOracleRequest
- describe('v0.6/Oracle vs v0.7/Operator #fulfillOracleRequest', () => {
- const response = 'Hi Mom!'
- let basicConsumer1: Contract
- let basicConsumer2: Contract
-
- let request1: ReturnType
- let request2: ReturnType
-
- beforeEach(async () => {
- basicConsumer1 = await basicConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, oracle1.address, specId)
- basicConsumer2 = await basicConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator1.address, specId)
-
- const paymentAmount = toWei('1')
- const currency = 'USD'
-
- await link.transfer(basicConsumer1.address, paymentAmount)
- const tx1 = await basicConsumer1.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt1 = await tx1.wait()
- request1 = decodeRunRequest(receipt1.logs?.[3])
-
- await link.transfer(basicConsumer2.address, paymentAmount)
- const tx2 = await basicConsumer2.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt2 = await tx2.wait()
- request2 = decodeRunRequest(receipt2.logs?.[3])
- })
-
- it('uses acceptable gas', async () => {
- const tx1 = await oracle1
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request1, response))
- const tx2 = await operator1
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request2, response))
- const receipt1 = await tx1.wait()
- const receipt2 = await tx2.wait()
- // 38014 vs 40260
- gasDiffLessThan(3900, receipt1, receipt2)
- })
- })
-
- // Test Operator1.fulfillOracleRequest vs Operator2.fulfillOracleRequest2
- // with single word response
- describe('Operator #fulfillOracleRequest vs #fulfillOracleRequest2', () => {
- const response = 'Hi Mom!'
- let basicConsumer1: Contract
- let basicConsumer2: Contract
-
- let request1: ReturnType
- let request2: ReturnType
-
- beforeEach(async () => {
- basicConsumer1 = await basicConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator1.address, specId)
- basicConsumer2 = await basicConsumerFactory
- .connect(roles.consumer)
- .deploy(link.address, operator2.address, specId)
-
- const paymentAmount = toWei('1')
- const currency = 'USD'
-
- await link.transfer(basicConsumer1.address, paymentAmount)
- const tx1 = await basicConsumer1.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt1 = await tx1.wait()
- request1 = decodeRunRequest(receipt1.logs?.[3])
-
- await link.transfer(basicConsumer2.address, paymentAmount)
- const tx2 = await basicConsumer2.requestEthereumPrice(
- currency,
- paymentAmount,
- )
- const receipt2 = await tx2.wait()
- request2 = decodeRunRequest(receipt2.logs?.[3])
- })
-
- it('uses acceptable gas', async () => {
- const tx1 = await operator1
- .connect(roles.oracleNode)
- .fulfillOracleRequest(...convertFufillParams(request1, response))
-
- const responseTypes = ['bytes32']
- const responseValues = [toBytes32String(response)]
- const tx2 = await operator2
- .connect(roles.oracleNode)
- .fulfillOracleRequest2(
- ...convertFulfill2Params(request2, responseTypes, responseValues),
- )
-
- const receipt1 = await tx1.wait()
- const receipt2 = await tx2.wait()
- gasDiffLessThan(1240, receipt1, receipt2)
- })
- })
-})
From b058357980ef75a06602fd26f19db4b0a1a286ce Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Mon, 13 Nov 2023 10:14:24 +0100
Subject: [PATCH 129/327] bump foundry (#11245)
---
.github/workflows/solidity-foundry.yml | 2 +-
contracts/GNUmakefile | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml
index 7c9df79617..90d18ecac2 100644
--- a/.github/workflows/solidity-foundry.yml
+++ b/.github/workflows/solidity-foundry.yml
@@ -58,7 +58,7 @@ jobs:
uses: foundry-rs/foundry-toolchain@v1
with:
# Has to match the `make foundry` version.
- version: nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b
+ version: nightly-09fe3e041369a816365a020f715ad6f94dbce9f2
- name: Run Forge build
if: needs.changes.outputs.changes == 'true'
diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile
index e41d6422c2..e880813867 100644
--- a/contracts/GNUmakefile
+++ b/contracts/GNUmakefile
@@ -38,7 +38,7 @@ mockery: $(mockery) ## Install mockery.
.PHONY: foundry
foundry: ## Install foundry.
- foundryup --version nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b
+ foundryup --version nightly-09fe3e041369a816365a020f715ad6f94dbce9f2
.PHONY: foundry-refresh
foundry-refresh: foundry
From 35e146fcb61e9036b747bd32ee76cf0d039bd344 Mon Sep 17 00:00:00 2001
From: Bartek Tofel
Date: Mon, 13 Nov 2023 14:54:48 +0100
Subject: [PATCH 130/327] Eth2 showcase with log poller (#11214)
* move workflow to correct directory
* streamline on-demand values a bit
* get RPC urls and private keys from secrets
* download and run from inside the test folder
* checkout repo before running tests
* get inputs and mask them
* fix step ordering in workflow
* fix default image tag
* use latest pumba@CTF
* run one test
* fix directory name
* run on powerful runner
* show usage of ethereum env builder with eth2
* update usage of eth2
* adjust to latest
---
integration-tests/docker/test_env/test_env.go | 46 +++++--
.../docker/test_env/test_env_builder.go | 68 +++++++---
.../docker/test_env/test_env_config.go | 10 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
integration-tests/smoke/automation_test.go | 4 +-
integration-tests/smoke/log_poller_test.go | 128 +++++++++++++++++-
.../universal/log_poller/helpers.go | 13 +-
8 files changed, 230 insertions(+), 45 deletions(-)
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index b3fc1c0cf6..4a30487211 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -40,15 +40,16 @@ type CLClusterTestEnv struct {
LogWatch *logwatch.LogWatch
/* components */
- ClCluster *ClCluster
- Geth *test_env.Geth // for tests using --dev networks
- PrivateChain []test_env.PrivateChain // for tests using non-dev networks
- MockAdapter *test_env.Killgrave
- EVMClient blockchain.EVMClient
- ContractDeployer contracts.ContractDeployer
- ContractLoader contracts.ContractLoader
- l zerolog.Logger
- t *testing.T
+ ClCluster *ClCluster
+ PrivateChain []test_env.PrivateChain // for tests using non-dev networks -- unify it with new approach
+ MockAdapter *test_env.Killgrave
+ EVMClient blockchain.EVMClient
+ ContractDeployer contracts.ContractDeployer
+ ContractLoader contracts.ContractLoader
+ RpcProvider test_env.RpcProvider
+ PrivateEthereumConfig *test_env.EthereumNetwork // new approach to private chains, supporting eth1 and eth2
+ l zerolog.Logger
+ t *testing.T
}
func NewTestEnv() (*CLClusterTestEnv, error) {
@@ -59,7 +60,6 @@ func NewTestEnv() (*CLClusterTestEnv, error) {
}
n := []string{network.Name}
return &CLClusterTestEnv{
- Geth: test_env.NewGeth(n),
MockAdapter: test_env.NewKillgrave(n, ""),
Network: network,
l: log.Logger,
@@ -67,11 +67,10 @@ func NewTestEnv() (*CLClusterTestEnv, error) {
}
// WithTestEnvConfig sets the test environment cfg.
-// Sets up the Geth and MockAdapter containers with the provided cfg.
+// Sets up private ethereum chain and MockAdapter containers with the provided cfg.
func (te *CLClusterTestEnv) WithTestEnvConfig(cfg *TestEnvConfig) *CLClusterTestEnv {
te.Cfg = cfg
n := []string{te.Network.Name}
- te.Geth = test_env.NewGeth(n, test_env.WithContainerName(te.Cfg.Geth.ContainerName))
te.MockAdapter = test_env.NewKillgrave(n, te.Cfg.MockAdapter.ImpostersPath, test_env.WithContainerName(te.Cfg.MockAdapter.ContainerName))
return te
}
@@ -79,7 +78,6 @@ func (te *CLClusterTestEnv) WithTestEnvConfig(cfg *TestEnvConfig) *CLClusterTest
func (te *CLClusterTestEnv) WithTestLogger(t *testing.T) *CLClusterTestEnv {
te.t = t
te.l = logging.GetTestLogger(t)
- te.Geth.WithTestLogger(t)
te.MockAdapter.WithTestLogger(t)
return te
}
@@ -128,8 +126,26 @@ func (te *CLClusterTestEnv) StartPrivateChain() error {
return nil
}
-func (te *CLClusterTestEnv) StartGeth() (blockchain.EVMNetwork, test_env.InternalDockerUrls, error) {
- return te.Geth.StartContainer()
+func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *test_env.EthereumNetwork) (blockchain.EVMNetwork, test_env.RpcProvider, error) {
+ // if environment is being restored from a previous state, use the existing config
+ // this might fail terribly if temporary folders with chain data on the host machine were removed
+ if te.Cfg != nil && te.Cfg.EthereumNetwork != nil {
+ builder := test_env.NewEthereumNetworkBuilder()
+ c, err := builder.WithExistingConfig(*te.Cfg.EthereumNetwork).
+ WithTest(te.t).
+ Build()
+ if err != nil {
+ return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err
+ }
+ cfg = &c
+ }
+ n, rpc, err := cfg.Start()
+
+ if err != nil {
+ return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err
+ }
+
+ return n, rpc, nil
}
func (te *CLClusterTestEnv) StartMockAdapter() error {
diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go
index 9f64ab64c9..e97f869d64 100644
--- a/integration-tests/docker/test_env/test_env_builder.go
+++ b/integration-tests/docker/test_env/test_env_builder.go
@@ -31,8 +31,8 @@ const (
)
type CLTestEnvBuilder struct {
- hasLogWatch bool
- hasGeth bool
+ hasLogWatch bool
+ // hasGeth bool
hasKillgrave bool
hasForwarders bool
clNodeConfig *chainlink.Config
@@ -49,6 +49,7 @@ type CLTestEnvBuilder struct {
cleanUpCustomFn func()
chainOptionsFn []ChainOption
evmClientNetworkOption []EVMClientNetworkOption
+ ethereumNetwork *test_env.EthereumNetwork
/* funding */
ETHFunds *big.Float
@@ -118,8 +119,27 @@ func (b *CLTestEnvBuilder) WithFunding(eth *big.Float) *CLTestEnvBuilder {
return b
}
+// deprecated
+// left only for backward compatibility
func (b *CLTestEnvBuilder) WithGeth() *CLTestEnvBuilder {
- b.hasGeth = true
+ ethBuilder := test_env.NewEthereumNetworkBuilder()
+ cfg, err := ethBuilder.
+ WithConsensusType(test_env.ConsensusType_PoW).
+ WithExecutionLayer(test_env.ExecutionLayer_Geth).
+ WithTest(b.t).
+ Build()
+
+ if err != nil {
+ panic(err)
+ }
+
+ b.ethereumNetwork = &cfg
+
+ return b
+}
+
+func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en test_env.EthereumNetwork) *CLTestEnvBuilder {
+ b.ethereumNetwork = &en
return b
}
@@ -191,13 +211,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
return nil, err
}
}
- b.l.Info().
- Bool("hasGeth", b.hasGeth).
- Bool("hasKillgrave", b.hasKillgrave).
- Int("clNodesCount", b.clNodesCount).
- Strs("customNodeCsaKeys", b.customNodeCsaKeys).
- Strs("defaultNodeCsaKeys", b.defaultNodeCsaKeys).
- Msg("Building CL cluster test environment..")
var err error
if b.t != nil {
@@ -259,13 +272,21 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
}
return b.te, nil
}
+
networkConfig := networks.MustGetSelectedNetworksFromEnv()[0]
- var internalDockerUrls test_env.InternalDockerUrls
- if b.hasGeth && networkConfig.Simulated {
- networkConfig, internalDockerUrls, err = b.te.StartGeth()
+ var rpcProvider test_env.RpcProvider
+ if b.ethereumNetwork != nil && networkConfig.Simulated {
+ // TODO here we should save the ethereum network config to te.Cfg, but it doesn't exist at this point
+ // in general it seems we have no methods for saving config to file and we only load it from file
+ // but I don't know how that config file is to be created or whether anyone ever done that
+ var enCfg test_env.EthereumNetwork
+ b.ethereumNetwork.DockerNetworkNames = []string{b.te.Network.Name}
+ networkConfig, rpcProvider, err = b.te.StartEthereumNetwork(b.ethereumNetwork)
if err != nil {
return nil, err
}
+ b.te.RpcProvider = rpcProvider
+ b.te.PrivateEthereumConfig = &enCfg
}
if !b.isNonEVM {
@@ -311,8 +332,8 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
var httpUrls []string
var wsUrls []string
if networkConfig.Simulated {
- httpUrls = []string{internalDockerUrls.HttpUrl}
- wsUrls = []string{internalDockerUrls.WsUrl}
+ httpUrls = rpcProvider.PrivateHttpUrls()
+ wsUrls = rpcProvider.PrivateWsUrsl()
} else {
httpUrls = networkConfig.HTTPURLs
wsUrls = networkConfig.URLs
@@ -341,7 +362,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
b.defaultNodeCsaKeys = nodeCsaKeys
}
- if b.hasGeth && b.clNodesCount > 0 && b.ETHFunds != nil {
+ if b.ethereumNetwork != nil && b.clNodesCount > 0 && b.ETHFunds != nil {
b.te.ParallelTransactions(true)
defer b.te.ParallelTransactions(false)
if err := b.te.FundChainlinkNodes(b.ETHFunds); err != nil {
@@ -349,5 +370,20 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
}
}
+ var enDesc string
+ if b.te.PrivateEthereumConfig != nil {
+ enDesc = b.te.PrivateEthereumConfig.Describe()
+ } else {
+ enDesc = "none"
+ }
+
+ b.l.Info().
+ Str("privateEthereumNetwork", enDesc).
+ Bool("hasKillgrave", b.hasKillgrave).
+ Int("clNodesCount", b.clNodesCount).
+ Strs("customNodeCsaKeys", b.customNodeCsaKeys).
+ Strs("defaultNodeCsaKeys", b.defaultNodeCsaKeys).
+ Msg("Building CL cluster test environment..")
+
return b.te, nil
}
diff --git a/integration-tests/docker/test_env/test_env_config.go b/integration-tests/docker/test_env/test_env_config.go
index 1a0c8d5c86..0902deb0c2 100644
--- a/integration-tests/docker/test_env/test_env_config.go
+++ b/integration-tests/docker/test_env/test_env_config.go
@@ -3,14 +3,16 @@ package test_env
import (
"encoding/json"
+ cte "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
env "github.com/smartcontractkit/chainlink/integration-tests/types/envcommon"
)
type TestEnvConfig struct {
- Networks []string `json:"networks"`
- Geth GethConfig `json:"geth"`
- MockAdapter MockAdapterConfig `json:"mock_adapter"`
- ClCluster *ClCluster `json:"clCluster"`
+ Networks []string `json:"networks"`
+ Geth GethConfig `json:"geth"`
+ MockAdapter MockAdapterConfig `json:"mock_adapter"`
+ ClCluster *ClCluster `json:"clCluster"`
+ EthereumNetwork *cte.EthereumNetwork `json:"private_ethereum_config"`
}
type MockAdapterConfig struct {
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 83657baa01..6a7e7195ff 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,7 +22,7 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-testing-framework v1.18.5
+ github.com/smartcontractkit/chainlink-testing-framework v1.18.6
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index a873f9b7c1..780e81c7ef 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2375,8 +2375,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.5 h1:R0f13AUbon1ltHE/vudkyUnLRGaoeocIDVv+FsHZjno=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.5/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.6 h1:UL3DxsPflSRALP62rsg5v3NdOsa8RHGhHMUImoWDD6k=
+github.com/smartcontractkit/chainlink-testing-framework v1.18.6/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 9e35b24df1..4f969c5d68 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -1070,8 +1070,8 @@ func setupAutomationTestDocker(
var httpUrls []string
var wsUrls []string
if network.Simulated {
- httpUrls = []string{env.Geth.InternalHttpUrl}
- wsUrls = []string{env.Geth.InternalWsUrl}
+ httpUrls = []string{env.RpcProvider.PrivateHttpUrls()[0]}
+ wsUrls = []string{env.RpcProvider.PrivateWsUrsl()[0]}
} else {
httpUrls = network.HTTPURLs
wsUrls = network.URLs
diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go
index 0df7817f1e..36ee2164c4 100644
--- a/integration-tests/smoke/log_poller_test.go
+++ b/integration-tests/smoke/log_poller_test.go
@@ -9,7 +9,7 @@ import (
// consistency test with no network disruptions with approximate emission of 1500-1600 logs per second for ~110-120 seconds
// 6 filters are registered
-func TestLogPollerFewFilters(t *testing.T) {
+func TestLogPollerFewFiltersFixedDepth(t *testing.T) {
cfg := logpoller.Config{
General: &logpoller.General{
Generator: logpoller.GeneratorType_Looped,
@@ -38,9 +38,38 @@ func TestLogPollerFewFilters(t *testing.T) {
logpoller.ExecuteBasicLogPollerTest(t, &cfg)
}
+func TestLogPollerFewFiltersFinalityTag(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 4,
+ UseFinalityTag: true,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ logpoller.ExecuteBasicLogPollerTest(t, &cfg)
+}
+
// consistency test with no network disruptions with approximate emission of 1000-1100 logs per second for ~110-120 seconds
// 900 filters are registered
-func TestLogManyFiltersPoller(t *testing.T) {
+func TestLogManyFiltersPollerFixedDepth(t *testing.T) {
cfg := logpoller.Config{
General: &logpoller.General{
Generator: logpoller.GeneratorType_Looped,
@@ -69,10 +98,39 @@ func TestLogManyFiltersPoller(t *testing.T) {
logpoller.ExecuteBasicLogPollerTest(t, &cfg)
}
+func TestLogManyFiltersPollerFinalityTag(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 300,
+ EventsPerTx: 3,
+ UseFinalityTag: true,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 30,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ logpoller.ExecuteBasicLogPollerTest(t, &cfg)
+}
+
// consistency test that introduces random distruptions by pausing either Chainlink or Postgres containers for random interval of 5-20 seconds
// with approximate emission of 520-550 logs per second for ~110 seconds
// 6 filters are registered
-func TestLogPollerWithChaos(t *testing.T) {
+func TestLogPollerWithChaosFixedDepth(t *testing.T) {
cfg := logpoller.Config{
General: &logpoller.General{
Generator: logpoller.GeneratorType_Looped,
@@ -104,12 +162,74 @@ func TestLogPollerWithChaos(t *testing.T) {
logpoller.ExecuteBasicLogPollerTest(t, &cfg)
}
+func TestLogPollerWithChaosFinalityTag(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 100,
+ UseFinalityTag: true,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ ChaosConfig: &logpoller.ChaosConfig{
+ ExperimentCount: 10,
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+
+ logpoller.ExecuteBasicLogPollerTest(t, &cfg)
+}
+
// consistency test that registers filters after events were emitted and then triggers replay via API
// unfortunately there is no way to make sure that logs that are indexed are only picked up by replay
// and not by backup poller
// with approximate emission of 24 logs per second for ~110 seconds
// 6 filters are registered
-func TestLogPollerReplay(t *testing.T) {
+func TestLogPollerReplayFixedDepth(t *testing.T) {
+ cfg := logpoller.Config{
+ General: &logpoller.General{
+ Generator: logpoller.GeneratorType_Looped,
+ Contracts: 2,
+ EventsPerTx: 4,
+ UseFinalityTag: false,
+ },
+ LoopedConfig: &logpoller.LoopedConfig{
+ ContractConfig: logpoller.ContractConfig{
+ ExecutionCount: 100,
+ },
+ FuzzConfig: logpoller.FuzzConfig{
+ MinEmitWaitTimeMs: 200,
+ MaxEmitWaitTimeMs: 500,
+ },
+ },
+ }
+
+ eventsToEmit := []abi.Event{}
+ for _, event := range logpoller.EmitterABI.Events {
+ eventsToEmit = append(eventsToEmit, event)
+ }
+
+ cfg.General.EventsToEmit = eventsToEmit
+ consistencyTimeout := "5m"
+
+ logpoller.ExecuteLogPollerReplay(t, &cfg, consistencyTimeout)
+}
+
+func TestLogPollerReplayFinalityTag(t *testing.T) {
cfg := logpoller.Config{
General: &logpoller.General{
Generator: logpoller.GeneratorType_Looped,
diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go
index ab7a221955..9f88827bb4 100644
--- a/integration-tests/universal/log_poller/helpers.go
+++ b/integration-tests/universal/log_poller/helpers.go
@@ -1068,9 +1068,20 @@ func setupLogPollerTestDocker(
return network
}
+ ethBuilder := ctf_test_env.NewEthereumNetworkBuilder()
+ cfg, err := ethBuilder.
+ WithConsensusType(ctf_test_env.ConsensusType_PoS).
+ WithConsensusLayer(ctf_test_env.ConsensusLayer_Prysm).
+ WithExecutionLayer(ctf_test_env.ExecutionLayer_Geth).
+ WithBeaconChainConfig(ctf_test_env.BeaconChainConfig{
+ SecondsPerSlot: 8,
+ SlotsPerEpoch: 2,
+ }).
+ Build()
+
env, err = test_env.NewCLTestEnvBuilder().
WithTestLogger(t).
- WithGeth().
+ WithPrivateEthereumNetwork(cfg).
WithCLNodes(clNodesCount).
WithCLNodeConfig(clNodeConfig).
WithFunding(big.NewFloat(chainlinkNodeFunding)).
From de5027383ba3120554e8dc88b5b178973585159b Mon Sep 17 00:00:00 2001
From: ferglor <19188060+ferglor@users.noreply.github.com>
Date: Mon, 13 Nov 2023 15:04:10 +0000
Subject: [PATCH 131/327] Always wait for doCheck to complete before returning
(#10878)
* Always wait for doCheck to complete before returning
Use threadctrl to avail of context cancellation but still rely on a wait group to blocl until the lookups finish
Update tests
* Revert async streamsLookup to fix test
* Rearrange thread control as a test
* Copy index
* WIP
---
.../ocr2keeper/evm21/registry_check_pipeline.go | 5 ++++-
.../plugins/ocr2keeper/evm21/streams_lookup.go | 16 +++++++++++++---
.../ocr2keeper/evm21/streams_lookup_test.go | 15 ++++++++++++++-
3 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
index d353099470..c9752ea14d 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
@@ -41,7 +41,10 @@ func (r *EvmRegistry) CheckUpkeeps(ctx context.Context, keys ...ocr2keepers.Upke
}
chResult := make(chan checkResult, 1)
- go r.doCheck(ctx, keys, chResult)
+
+ r.threadCtrl.Go(func(ctx context.Context) {
+ r.doCheck(ctx, keys, chResult)
+ })
select {
case rs := <-chResult:
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
index 660550afe9..fb2821a74b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
@@ -149,10 +149,15 @@ func (r *EvmRegistry) streamsLookup(ctx context.Context, checkResults []ocr2keep
}
var wg sync.WaitGroup
+
for i, lookup := range lookups {
+ i := i
wg.Add(1)
- go r.doLookup(ctx, &wg, lookup, i, checkResults, lggr)
+ r.threadCtrl.Go(func(ctx context.Context) {
+ r.doLookup(ctx, &wg, lookup, i, checkResults, lggr)
+ })
}
+
wg.Wait()
// don't surface error to plugin bc StreamsLookup process should be self-contained.
@@ -289,14 +294,19 @@ func (r *EvmRegistry) doMercuryRequest(ctx context.Context, sl *StreamsLookup, p
if sl.FeedParamKey == feedIdHex && sl.TimeParamKey == blockNumber {
// only mercury v0.2
for i := range sl.Feeds {
- go r.singleFeedRequest(ctx, ch, i, sl, lggr)
+ i := i
+ r.threadCtrl.Go(func(ctx context.Context) {
+ r.singleFeedRequest(ctx, ch, i, sl, lggr)
+ })
}
} else if sl.FeedParamKey == feedIDs {
// only mercury v0.3
resultLen = 1
isMercuryV03 = true
ch = make(chan MercuryData, resultLen)
- go r.multiFeedsRequest(ctx, ch, sl, lggr)
+ r.threadCtrl.Go(func(ctx context.Context) {
+ r.multiFeedsRequest(ctx, ch, sl, lggr)
+ })
} else {
return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
index 8d7c67d80c..145d701454 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
@@ -25,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -70,7 +71,8 @@ func setupEVMRegistry(t *testing.T) *EvmRegistry {
allowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
},
- hc: mockHttpClient,
+ hc: mockHttpClient,
+ threadCtrl: utils.NewThreadControl(),
}
return r
}
@@ -220,6 +222,7 @@ func TestEvmRegistry_StreamsLookup(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ defer r.Close()
client := new(evmClientMocks.Client)
r.client = client
@@ -362,6 +365,7 @@ func TestEvmRegistry_AllowedToUseMercury(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ defer r.Close()
client := new(evmClientMocks.Client)
r.client = client
@@ -576,9 +580,12 @@ func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ defer r.Close()
+
if tt.pluginRetries != 0 {
r.mercury.pluginRetryCache.Set(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
}
+
hc := mocks.NewHttpClient(t)
for _, blob := range tt.mockChainlinkBlobs {
@@ -812,6 +819,8 @@ func TestEvmRegistry_SingleFeedRequest(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ defer r.Close()
+
hc := mocks.NewHttpClient(t)
mr := MercuryV02Response{ChainlinkBlob: tt.blob}
@@ -1157,6 +1166,8 @@ func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := setupEVMRegistry(t)
+ defer r.Close()
+
if tt.pluginRetries != 0 {
r.mercury.pluginRetryCache.Set(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
}
@@ -1319,6 +1330,8 @@ func TestEvmRegistry_CheckCallback(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
client := new(evmClientMocks.Client)
r := setupEVMRegistry(t)
+ defer r.Close()
+
payload, err := r.abi.Pack("checkCallback", tt.lookup.upkeepId, values, tt.lookup.ExtraData)
require.Nil(t, err)
args := map[string]interface{}{
From 12062831ae01b21c6ea6bc052107ecbe254da6c4 Mon Sep 17 00:00:00 2001
From: Bruno Moura
Date: Mon, 13 Nov 2023 15:04:39 +0000
Subject: [PATCH 132/327] Remove Mercury plugin dependency on raw evm chain.
(#11201)
* mercury: remove dead code
* mercury: Add ChainReader
* mercury: services init
* fix sqlx import
* mercury: error handling
* mod tidy
* mercury: log error from reader
* mercury: ensure a failed observation when reading from chain return an error
* mercury: add test for setLatestBlocks error
* make a happy linter
* Update core/services/relay/evm/mercury_provider.go
Co-authored-by: Sam
---------
Co-authored-by: Sam
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
core/services/ocr2/delegate.go | 6 +-
core/services/ocr2/plugins/mercury/plugin.go | 3 +-
core/services/relay/evm/evm.go | 5 +-
.../evm/mercury/mocks/chain_head_tracker.go | 47 -------------
.../services/relay/evm/mercury/types/types.go | 6 --
.../relay/evm/mercury/v1/data_source.go | 53 +++++++-------
.../relay/evm/mercury/v1/data_source_test.go | 70 +++++++++----------
core/services/relay/evm/mercury_provider.go | 38 ++++++++++
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
14 files changed, 113 insertions(+), 133 deletions(-)
delete mode 100644 core/services/relay/evm/mercury/mocks/chain_head_tracker.go
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 5f881f354e..bb68175ddf 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -304,7 +304,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 1d455305a9..bd3b75d37a 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1464,8 +1464,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 h1:ZBsxdB/5iIpl/tWhXe/RHrOwBG7pbKOMeppy5Zt2BVc=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 h1:28XkPE6YfJ4uabTX9/7sueRV6IKtY4hcm1nIt1e6b20=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 95ec146915..19296c72f0 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -653,10 +653,6 @@ func (d *Delegate) newServicesMercury(
if err != nil {
return nil, ErrRelayNotEnabled{Err: err, Relay: spec.Relay, PluginName: "mercury"}
}
- chain, err := d.legacyChains.Get(rid.ChainID)
- if err != nil {
- return nil, fmt.Errorf("mercury services: failed to get chain %s: %w", rid.ChainID, err)
- }
provider, err2 := relayer.NewPluginProvider(ctx,
types.RelayArgs{
@@ -695,7 +691,7 @@ func (d *Delegate) newServicesMercury(
chEnhancedTelem := make(chan ocrcommon.EnhancedTelemetryMercuryData, 100)
- mercuryServices, err2 := mercury.NewServices(jb, mercuryProvider, d.pipelineRunner, runResults, lggr, oracleArgsNoPlugin, d.cfg.JobPipeline(), chEnhancedTelem, chain, d.mercuryORM, (mercuryutils.FeedID)(*spec.FeedID))
+ mercuryServices, err2 := mercury.NewServices(jb, mercuryProvider, d.pipelineRunner, runResults, lggr, oracleArgsNoPlugin, d.cfg.JobPipeline(), chEnhancedTelem, d.mercuryORM, (mercuryutils.FeedID)(*spec.FeedID))
if ocrcommon.ShouldCollectEnhancedTelemetryMercury(jb) {
enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, chEnhancedTelem, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), synchronization.EnhancedEAMercury), lggr.Named("EnhancedTelemetryMercury"))
diff --git a/core/services/ocr2/plugins/mercury/plugin.go b/core/services/ocr2/plugins/mercury/plugin.go
index 69a3b53c28..ddef1374a4 100644
--- a/core/services/ocr2/plugins/mercury/plugin.go
+++ b/core/services/ocr2/plugins/mercury/plugin.go
@@ -37,7 +37,6 @@ func NewServices(
argsNoPlugin libocr2.MercuryOracleArgs,
cfg Config,
chEnhancedTelem chan ocrcommon.EnhancedTelemetryMercuryData,
- chainHeadTracker types.ChainHeadTracker,
orm types.DataSourceORM,
feedID utils.FeedID,
) ([]job.ServiceCtx, error) {
@@ -66,7 +65,7 @@ func NewServices(
lggr,
runResults,
chEnhancedTelem,
- chainHeadTracker,
+ ocr2Provider.ChainReader(),
ocr2Provider.MercuryServerFetcher(),
pluginConfig.InitialBlockNumber.Ptr(),
feedID,
diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go
index 111e3622b1..aa1d1d774b 100644
--- a/core/services/relay/evm/evm.go
+++ b/core/services/relay/evm/evm.go
@@ -10,10 +10,10 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
+ "github.com/jmoiron/sqlx"
pkgerrors "github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median/evmreportcodec"
@@ -189,7 +189,8 @@ func (r *Relayer) NewMercuryProvider(rargs relaytypes.RelayArgs, pargs relaytype
}
transmitter := mercury.NewTransmitter(lggr, cw.ContractConfigTracker(), client, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.db, r.pgCfg, transmitterCodec)
- return NewMercuryProvider(cw, transmitter, reportCodecV1, reportCodecV2, reportCodecV3, lggr), nil
+ chainReader := NewChainReader(r.chain.HeadTracker())
+ return NewMercuryProvider(cw, transmitter, reportCodecV1, reportCodecV2, reportCodecV3, chainReader, lggr), nil
}
func (r *Relayer) NewFunctionsProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (relaytypes.FunctionsProvider, error) {
diff --git a/core/services/relay/evm/mercury/mocks/chain_head_tracker.go b/core/services/relay/evm/mercury/mocks/chain_head_tracker.go
deleted file mode 100644
index b6f2981cf0..0000000000
--- a/core/services/relay/evm/mercury/mocks/chain_head_tracker.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Code generated by mockery v2.35.4. DO NOT EDIT.
-
-package mocks
-
-import (
- common "github.com/ethereum/go-ethereum/common"
- evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
-
- mock "github.com/stretchr/testify/mock"
-
- types "github.com/smartcontractkit/chainlink/v2/common/types"
-)
-
-// ChainHeadTracker is an autogenerated mock type for the ChainHeadTracker type
-type ChainHeadTracker struct {
- mock.Mock
-}
-
-// HeadTracker provides a mock function with given fields:
-func (_m *ChainHeadTracker) HeadTracker() types.HeadTracker[*evmtypes.Head, common.Hash] {
- ret := _m.Called()
-
- var r0 types.HeadTracker[*evmtypes.Head, common.Hash]
- if rf, ok := ret.Get(0).(func() types.HeadTracker[*evmtypes.Head, common.Hash]); ok {
- r0 = rf()
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).(types.HeadTracker[*evmtypes.Head, common.Hash])
- }
- }
-
- return r0
-}
-
-// NewChainHeadTracker creates a new instance of ChainHeadTracker. 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 NewChainHeadTracker(t interface {
- mock.TestingT
- Cleanup(func())
-}) *ChainHeadTracker {
- mock := &ChainHeadTracker{}
- mock.Mock.Test(t)
-
- t.Cleanup(func() { mock.AssertExpectations(t) })
-
- return mock
-}
diff --git a/core/services/relay/evm/mercury/types/types.go b/core/services/relay/evm/mercury/types/types.go
index 7059689939..49bffb6c29 100644
--- a/core/services/relay/evm/mercury/types/types.go
+++ b/core/services/relay/evm/mercury/types/types.go
@@ -8,15 +8,9 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
)
-//go:generate mockery --quiet --name ChainHeadTracker --output ../mocks/ --case=underscore
-type ChainHeadTracker interface {
- HeadTracker() httypes.HeadTracker
-}
-
type DataSourceORM interface {
LatestReport(ctx context.Context, feedID [32]byte, qopts ...pg.QOpt) (report []byte, err error)
}
diff --git a/core/services/relay/evm/mercury/v1/data_source.go b/core/services/relay/evm/mercury/v1/data_source.go
index 0f8f56f46e..0bdfb67de7 100644
--- a/core/services/relay/evm/mercury/v1/data_source.go
+++ b/core/services/relay/evm/mercury/v1/data_source.go
@@ -16,7 +16,6 @@ import (
relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
@@ -67,7 +66,7 @@ type datasource struct {
mu sync.RWMutex
chEnhancedTelem chan<- ocrcommon.EnhancedTelemetryMercuryData
- chainHeadTracker types.ChainHeadTracker
+ chainReader relaymercury.ChainReader
fetcher Fetcher
initialBlockNumber *int64
@@ -77,8 +76,8 @@ type datasource struct {
var _ relaymercuryv1.DataSource = &datasource{}
-func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec pipeline.Spec, lggr logger.Logger, rr chan *pipeline.Run, enhancedTelemChan chan ocrcommon.EnhancedTelemetryMercuryData, chainHeadTracker types.ChainHeadTracker, fetcher Fetcher, initialBlockNumber *int64, feedID mercuryutils.FeedID) *datasource {
- return &datasource{pr, jb, spec, lggr, rr, orm, reportcodec.ReportCodec{}, feedID, sync.RWMutex{}, enhancedTelemChan, chainHeadTracker, fetcher, initialBlockNumber, insufficientBlocksCount.WithLabelValues(feedID.String()), zeroBlocksCount.WithLabelValues(feedID.String())}
+func NewDataSource(orm types.DataSourceORM, pr pipeline.Runner, jb job.Job, spec pipeline.Spec, lggr logger.Logger, rr chan *pipeline.Run, enhancedTelemChan chan ocrcommon.EnhancedTelemetryMercuryData, chainReader relaymercury.ChainReader, fetcher Fetcher, initialBlockNumber *int64, feedID mercuryutils.FeedID) *datasource {
+ return &datasource{pr, jb, spec, lggr, rr, orm, reportcodec.ReportCodec{}, feedID, sync.RWMutex{}, enhancedTelemChan, chainReader, fetcher, initialBlockNumber, insufficientBlocksCount.WithLabelValues(feedID.String()), zeroBlocksCount.WithLabelValues(feedID.String())}
}
type ErrEmptyLatestReport struct {
@@ -94,7 +93,11 @@ func (e ErrEmptyLatestReport) Error() string {
func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestamp, fetchMaxFinalizedBlockNum bool) (obs relaymercuryv1.Observation, pipelineExecutionErr error) {
// setLatestBlocks must come chronologically before observations, along
// with observationTimestamp, to avoid front-running
- ds.setLatestBlocks(ctx, &obs)
+
+ // Errors are not expected when reading from the underlying ChainReader
+ if err := ds.setLatestBlocks(ctx, &obs); err != nil {
+ return obs, err
+ }
var wg sync.WaitGroup
if fetchMaxFinalizedBlockNum {
@@ -290,8 +293,13 @@ func (ds *datasource) executeRun(ctx context.Context) (*pipeline.Run, pipeline.T
return run, trrs, err
}
-func (ds *datasource) setLatestBlocks(ctx context.Context, obs *relaymercuryv1.Observation) {
- latestBlocks := ds.getLatestBlocks(ctx, nBlocksObservation)
+func (ds *datasource) setLatestBlocks(ctx context.Context, obs *relaymercuryv1.Observation) error {
+ latestBlocks, err := ds.chainReader.LatestHeads(ctx, nBlocksObservation)
+ if err != nil {
+ ds.lggr.Errorw("failed to read latest blocks", "error", err)
+ return err
+ }
+
if len(latestBlocks) < nBlocksObservation {
ds.insufficientBlocksCounter.Inc()
ds.lggr.Warnw("Insufficient blocks", "latestBlocks", latestBlocks, "lenLatestBlocks", len(latestBlocks), "nBlocksObservation", nBlocksObservation)
@@ -299,31 +307,22 @@ func (ds *datasource) setLatestBlocks(ctx context.Context, obs *relaymercuryv1.O
// TODO: remove with https://smartcontract-it.atlassian.net/browse/BCF-2209
if len(latestBlocks) == 0 {
+ obsErr := fmt.Errorf("no blocks available")
ds.zeroBlocksCounter.Inc()
- err := errors.New("no blocks available")
- obs.CurrentBlockNum.Err = err
- obs.CurrentBlockHash.Err = err
- obs.CurrentBlockTimestamp.Err = err
+ obs.CurrentBlockNum.Err = obsErr
+ obs.CurrentBlockHash.Err = obsErr
+ obs.CurrentBlockTimestamp.Err = obsErr
} else {
- obs.CurrentBlockNum.Val = latestBlocks[0].Number
- obs.CurrentBlockHash.Val = latestBlocks[0].Hash.Bytes()
- if latestBlocks[0].Timestamp.IsZero() {
- obs.CurrentBlockTimestamp.Val = 0
- } else {
- obs.CurrentBlockTimestamp.Val = uint64(latestBlocks[0].Timestamp.Unix())
- }
+ obs.CurrentBlockNum.Val = int64(latestBlocks[0].Number)
+ obs.CurrentBlockHash.Val = latestBlocks[0].Hash
+ obs.CurrentBlockTimestamp.Val = latestBlocks[0].Timestamp
}
for _, block := range latestBlocks {
- obs.LatestBlocks = append(obs.LatestBlocks, relaymercuryv1.NewBlock(block.Number, block.Hash.Bytes(), uint64(block.Timestamp.Unix())))
+ obs.LatestBlocks = append(
+ obs.LatestBlocks,
+ relaymercuryv1.NewBlock(int64(block.Number), block.Hash, block.Timestamp))
}
-}
-func (ds *datasource) getLatestBlocks(ctx context.Context, k int) (blocks []*evmtypes.Head) {
- // Use the headtracker's view of the chain, this is very fast since
- // it doesn't make any external network requests, and it is the
- // headtracker's job to ensure it has an up-to-date view of the chain based
- // on responses from all available RPC nodes
- latestHead := ds.chainHeadTracker.HeadTracker().LatestChain()
- return latestHead.AsSlice(k)
+ return nil
}
diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go
index 42983fa002..40542c2631 100644
--- a/core/services/relay/evm/mercury/v1/data_source_test.go
+++ b/core/services/relay/evm/mercury/v1/data_source_test.go
@@ -3,6 +3,7 @@ package mercury_v1
import (
"context"
"fmt"
+ "io"
"math/big"
"math/rand"
"testing"
@@ -18,7 +19,6 @@ import (
relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/assets"
- httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -26,8 +26,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
mercurymocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/types"
mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
reportcodecv1 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/reportcodec"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -52,14 +52,6 @@ func (m *mockFetcher) LatestTimestamp(context.Context) (int64, error) {
return 0, nil
}
-var _ types.ChainHeadTracker = &mockHeadTracker{}
-
-type mockHeadTracker struct {
- h httypes.HeadTracker
-}
-
-func (m *mockHeadTracker) HeadTracker() httypes.HeadTracker { return m.h }
-
type mockORM struct {
report []byte
err error
@@ -69,6 +61,15 @@ func (m *mockORM) LatestReport(ctx context.Context, feedID [32]byte, qopts ...pg
return m.report, m.err
}
+type mockChainReader struct {
+ err error
+ obs []relaymercury.Head
+}
+
+func (m *mockChainReader) LatestHeads(context.Context, int) ([]relaymercury.Head, error) {
+ return m.obs, m.err
+}
+
func TestMercury_Observe(t *testing.T) {
orm := &mockORM{}
lggr := logger.TestLogger(t)
@@ -106,10 +107,7 @@ func TestMercury_Observe(t *testing.T) {
ds.spec = spec
h := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
- ht := &mockHeadTracker{
- h: h,
- }
- ds.chainHeadTracker = ht
+ ds.chainReader = evm.NewChainReader(h)
head := &evmtypes.Head{
Number: int64(rand.Int31()),
@@ -201,7 +199,7 @@ func TestMercury_Observe(t *testing.T) {
t.Run("if no current block available", func(t *testing.T) {
h2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
h2.On("LatestChain").Return((*evmtypes.Head)(nil))
- ht.h = h2
+ ds.chainReader = evm.NewChainReader(h2)
obs, err := ds.Observe(ctx, repts, true)
assert.NoError(t, err)
@@ -212,7 +210,7 @@ func TestMercury_Observe(t *testing.T) {
})
})
- ht.h = h
+ ds.chainReader = evm.NewChainReader(h)
t.Run("when fetchMaxFinalizedBlockNum=false", func(t *testing.T) {
t.Run("when run execution fails, returns error", func(t *testing.T) {
@@ -320,7 +318,7 @@ func TestMercury_Observe(t *testing.T) {
t.Run("when chain length is zero", func(t *testing.T) {
ht2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
ht2.On("LatestChain").Return((*evmtypes.Head)(nil))
- ht.h = ht2
+ ds.chainReader = evm.NewChainReader(ht2)
obs, err := ds.Observe(ctx, repts, true)
assert.NoError(t, err)
@@ -345,7 +343,7 @@ func TestMercury_Observe(t *testing.T) {
ht2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
ht2.On("LatestChain").Return(h6)
- ht.h = ht2
+ ds.chainReader = evm.NewChainReader(ht2)
obs, err := ds.Observe(ctx, repts, true)
assert.NoError(t, err)
@@ -384,7 +382,7 @@ func TestMercury_Observe(t *testing.T) {
ht2 := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
ht2.On("LatestChain").Return(h6)
- ht.h = ht2
+ ds.chainReader = evm.NewChainReader(ht2)
obs, err := ds.Observe(ctx, repts, true)
assert.NoError(t, err)
@@ -398,6 +396,18 @@ func TestMercury_Observe(t *testing.T) {
ht2.AssertExpectations(t)
})
+
+ t.Run("when chain reader returns an error", func(t *testing.T) {
+
+ ds.chainReader = &mockChainReader{
+ err: io.EOF,
+ obs: nil,
+ }
+
+ obs, err := ds.Observe(ctx, repts, true)
+ assert.Error(t, err)
+ assert.Equal(t, obs, relaymercuryv1.Observation{})
+ })
})
}
@@ -418,39 +428,31 @@ func TestMercury_SetLatestBlocks(t *testing.T) {
t.Run("returns head from headtracker if present", func(t *testing.T) {
headTracker := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
- chainHeadTracker := mercurymocks.NewChainHeadTracker(t)
-
- chainHeadTracker.On("HeadTracker").Return(headTracker)
headTracker.On("LatestChain").Return(&h, nil)
-
- ds.chainHeadTracker = chainHeadTracker
+ ds.chainReader = evm.NewChainReader(headTracker)
obs := relaymercuryv1.Observation{}
- ds.setLatestBlocks(context.Background(), &obs)
+ err := ds.setLatestBlocks(context.Background(), &obs)
+ assert.NoError(t, err)
assert.Equal(t, h.Number, obs.CurrentBlockNum.Val)
assert.Equal(t, h.Hash.Bytes(), obs.CurrentBlockHash.Val)
assert.Equal(t, uint64(h.Timestamp.Unix()), obs.CurrentBlockTimestamp.Val)
assert.Len(t, obs.LatestBlocks, 1)
-
- chainHeadTracker.AssertExpectations(t)
headTracker.AssertExpectations(t)
})
t.Run("if headtracker returns nil head", func(t *testing.T) {
headTracker := commonmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
- chainHeadTracker := mercurymocks.NewChainHeadTracker(t)
-
- chainHeadTracker.On("HeadTracker").Return(headTracker)
// This can happen in some cases e.g. RPC node is offline
headTracker.On("LatestChain").Return((*evmtypes.Head)(nil))
- ds.chainHeadTracker = chainHeadTracker
-
+ ds.chainReader = evm.NewChainReader(headTracker)
obs := relaymercuryv1.Observation{}
- ds.setLatestBlocks(context.Background(), &obs)
+ err := ds.setLatestBlocks(context.Background(), &obs)
+ assert.NoError(t, err)
assert.Zero(t, obs.CurrentBlockNum.Val)
assert.Zero(t, obs.CurrentBlockHash.Val)
assert.Zero(t, obs.CurrentBlockTimestamp.Val)
@@ -459,8 +461,6 @@ func TestMercury_SetLatestBlocks(t *testing.T) {
assert.EqualError(t, obs.CurrentBlockTimestamp.Err, "no blocks available")
assert.Len(t, obs.LatestBlocks, 0)
-
- chainHeadTracker.AssertExpectations(t)
headTracker.AssertExpectations(t)
})
}
diff --git a/core/services/relay/evm/mercury_provider.go b/core/services/relay/evm/mercury_provider.go
index 914401c089..bba5e699bc 100644
--- a/core/services/relay/evm/mercury_provider.go
+++ b/core/services/relay/evm/mercury_provider.go
@@ -12,6 +12,7 @@ import (
relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury"
@@ -25,6 +26,7 @@ type mercuryProvider struct {
reportCodecV1 relaymercuryv1.ReportCodec
reportCodecV2 relaymercuryv2.ReportCodec
reportCodecV3 relaymercuryv3.ReportCodec
+ chainReader relaymercury.ChainReader
logger logger.Logger
ms services.MultiStart
@@ -36,6 +38,7 @@ func NewMercuryProvider(
reportCodecV1 relaymercuryv1.ReportCodec,
reportCodecV2 relaymercuryv2.ReportCodec,
reportCodecV3 relaymercuryv3.ReportCodec,
+ chainReader relaymercury.ChainReader,
lggr logger.Logger,
) *mercuryProvider {
return &mercuryProvider{
@@ -44,6 +47,7 @@ func NewMercuryProvider(
reportCodecV1,
reportCodecV2,
reportCodecV3,
+ chainReader,
lggr,
services.MultiStart{},
}
@@ -103,3 +107,37 @@ func (p *mercuryProvider) ContractTransmitter() ocrtypes.ContractTransmitter {
func (p *mercuryProvider) MercuryServerFetcher() relaymercury.MercuryServerFetcher {
return p.transmitter
}
+
+func (p *mercuryProvider) ChainReader() relaymercury.ChainReader {
+ return p.chainReader
+}
+
+var _ relaymercury.ChainReader = (*chainReader)(nil)
+
+type chainReader struct {
+ tracker httypes.HeadTracker
+}
+
+func NewChainReader(h httypes.HeadTracker) relaymercury.ChainReader {
+ return &chainReader{
+ tracker: h,
+ }
+}
+
+func (r *chainReader) LatestHeads(ctx context.Context, k int) ([]relaymercury.Head, error) {
+ evmBlocks := r.tracker.LatestChain().AsSlice(k)
+ if len(evmBlocks) == 0 {
+ return nil, nil
+ }
+
+ blocks := make([]relaymercury.Head, len(evmBlocks))
+ for x := 0; x < len(evmBlocks); x++ {
+ blocks[x] = relaymercury.Head{
+ Number: uint64(evmBlocks[x].BlockNumber()),
+ Hash: evmBlocks[x].Hash.Bytes(),
+ Timestamp: uint64(evmBlocks[x].Timestamp.Unix()),
+ }
+ }
+
+ return blocks, nil
+}
diff --git a/go.mod b/go.mod
index f35077e923..8a4d58469c 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
diff --git a/go.sum b/go.sum
index 2c9d9e5371..1b96c936c5 100644
--- a/go.sum
+++ b/go.sum
@@ -1465,8 +1465,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 h1:ZBsxdB/5iIpl/tWhXe/RHrOwBG7pbKOMeppy5Zt2BVc=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 h1:28XkPE6YfJ4uabTX9/7sueRV6IKtY4hcm1nIt1e6b20=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 6a7e7195ff..b5455838b5 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -387,7 +387,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 780e81c7ef..fc486e5451 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2369,8 +2369,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78 h1:ZBsxdB/5iIpl/tWhXe/RHrOwBG7pbKOMeppy5Zt2BVc=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108205920-694ce17a4a78/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 h1:28XkPE6YfJ4uabTX9/7sueRV6IKtY4hcm1nIt1e6b20=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From 94625ef958b02c3eb759dd10d897b1d9bfc2fe5c Mon Sep 17 00:00:00 2001
From: ferglor <19188060+ferglor@users.noreply.github.com>
Date: Mon, 13 Nov 2023 15:25:50 +0000
Subject: [PATCH 133/327] Add a csv flag to the verifiable load subcommand
(#10833)
---
.../command/keeper/verifiable_load.go | 12 +++++++-
.../handler/keeper_verifiable_load.go | 30 +++++++++++++++----
2 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/core/scripts/chaincli/command/keeper/verifiable_load.go b/core/scripts/chaincli/command/keeper/verifiable_load.go
index 7d77f0d3a3..33acf9bf3b 100644
--- a/core/scripts/chaincli/command/keeper/verifiable_load.go
+++ b/core/scripts/chaincli/command/keeper/verifiable_load.go
@@ -1,6 +1,8 @@
package keeper
import (
+ "log"
+
"github.com/spf13/cobra"
"github.com/smartcontractkit/chainlink/core/scripts/chaincli/config"
@@ -15,6 +17,14 @@ var verifiableLoad = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
cfg := config.New()
hdlr := handler.NewKeeper(cfg)
- hdlr.GetVerifiableLoadStats(cmd.Context())
+ csv, err := cmd.Flags().GetBool("csv")
+ if err != nil {
+ log.Fatal("failed to get verify flag: ", err)
+ }
+ hdlr.GetVerifiableLoadStats(cmd.Context(), csv)
},
}
+
+func init() {
+ verifiableLoad.Flags().BoolP("csv", "c", false, "Specify if stats should be output as CSV")
+}
diff --git a/core/scripts/chaincli/handler/keeper_verifiable_load.go b/core/scripts/chaincli/handler/keeper_verifiable_load.go
index 429a762007..b71a9af338 100644
--- a/core/scripts/chaincli/handler/keeper_verifiable_load.go
+++ b/core/scripts/chaincli/handler/keeper_verifiable_load.go
@@ -2,6 +2,7 @@ package handler
import (
"context"
+ "fmt"
"log"
"math/big"
"sort"
@@ -57,7 +58,7 @@ type upkeepStats struct {
SortedAllDelays []float64
}
-func (k *Keeper) GetVerifiableLoadStats(ctx context.Context) {
+func (k *Keeper) GetVerifiableLoadStats(ctx context.Context, csv bool) {
var v verifiableLoad
var err error
addr := common.HexToAddress(k.cfg.VerifiableLoadContractAddress)
@@ -84,6 +85,10 @@ func (k *Keeper) GetVerifiableLoadStats(ctx context.Context) {
log.Fatalf("failed to get active upkeep IDs from %s: %v", k.cfg.VerifiableLoadContractAddress, err)
}
+ if csv {
+ fmt.Println("upkeep ID,total performs,p50,p90,p95,p99,max delay,total delay blocks,average perform delay")
+ }
+
us := &upkeepStats{BlockNumber: blockNum}
resultsChan := make(chan *upkeepInfo, maxUpkeepNum)
@@ -94,7 +99,7 @@ func (k *Keeper) GetVerifiableLoadStats(ctx context.Context) {
// create a number of workers to process the upkeep ids in batch
for i := 0; i < workerNum; i++ {
wg.Add(1)
- go k.getUpkeepInfo(idChan, resultsChan, v, opts, &wg)
+ go k.getUpkeepInfo(idChan, resultsChan, v, opts, &wg, csv)
}
for _, id := range upkeepIds {
@@ -120,12 +125,16 @@ func (k *Keeper) GetVerifiableLoadStats(ctx context.Context) {
p90, _ := stats.Percentile(us.SortedAllDelays, 90)
p95, _ := stats.Percentile(us.SortedAllDelays, 95)
p99, _ := stats.Percentile(us.SortedAllDelays, 99)
- maxDelay := us.SortedAllDelays[len(us.SortedAllDelays)-1]
+
+ maxDelay := float64(0)
+ if len(us.SortedAllDelays) > 0 {
+ maxDelay = us.SortedAllDelays[len(us.SortedAllDelays)-1]
+ }
log.Printf("For total %d upkeeps: total performs: %d, p50: %f, p90: %f, p95: %f, p99: %f, max delay: %f, total delay blocks: %f, average perform delay: %f\n", len(upkeepIds), us.TotalPerforms, p50, p90, p95, p99, maxDelay, us.TotalDelayBlock, us.TotalDelayBlock/float64(us.TotalPerforms))
log.Printf("All STATS ABOVE ARE CALCULATED AT BLOCK %d", blockNum)
}
-func (k *Keeper) getUpkeepInfo(idChan chan *big.Int, resultsChan chan *upkeepInfo, v verifiableLoad, opts *bind.CallOpts, wg *sync.WaitGroup) {
+func (k *Keeper) getUpkeepInfo(idChan chan *big.Int, resultsChan chan *upkeepInfo, v verifiableLoad, opts *bind.CallOpts, wg *sync.WaitGroup, csv bool) {
defer wg.Done()
for id := range idChan {
@@ -171,9 +180,18 @@ func (k *Keeper) getUpkeepInfo(idChan chan *big.Int, resultsChan chan *upkeepInf
p90, _ := stats.Percentile(info.SortedAllDelays, 90)
p95, _ := stats.Percentile(info.SortedAllDelays, 95)
p99, _ := stats.Percentile(info.SortedAllDelays, 99)
- maxDelay := info.SortedAllDelays[len(info.SortedAllDelays)-1]
- log.Printf("upkeep ID %s has %d performs in total. p50: %f, p90: %f, p95: %f, p99: %f, max delay: %f, total delay blocks: %d, average perform delay: %f\n", id, info.TotalPerforms, p50, p90, p95, p99, maxDelay, uint64(info.TotalDelayBlock), info.TotalDelayBlock/float64(info.TotalPerforms))
+ maxDelay := float64(0)
+
+ if len(info.SortedAllDelays) > 0 {
+ maxDelay = info.SortedAllDelays[len(info.SortedAllDelays)-1]
+ }
+
+ if csv {
+ fmt.Printf("%s,%d,%f,%f,%f,%f,%f,%d,%f\n", id, info.TotalPerforms, p50, p90, p95, p99, maxDelay, uint64(info.TotalDelayBlock), info.TotalDelayBlock/float64(info.TotalPerforms))
+ } else {
+ log.Printf("upkeep ID %s has %d performs in total. p50: %f, p90: %f, p95: %f, p99: %f, max delay: %f, total delay blocks: %d, average perform delay: %f\n", id, info.TotalPerforms, p50, p90, p95, p99, maxDelay, uint64(info.TotalDelayBlock), info.TotalDelayBlock/float64(info.TotalPerforms))
+ }
resultsChan <- info
}
}
From 0ba7e9a7cd402ed558835a39d0ced4e7c2b39732 Mon Sep 17 00:00:00 2001
From: george-dorin <120329946+george-dorin@users.noreply.github.com>
Date: Mon, 13 Nov 2023 17:37:45 +0200
Subject: [PATCH 134/327] EVM GRPC provider (#11208)
* Initial draft
* Add median provider checks
* Move provider-server to relay
* Bump chainlink-relay version
* Add tests
* Add comment explaining why the code lives inside the newServicesGenericPlugin method
* Fix formatting
* Fix lint
---
core/services/ocr2/delegate.go | 23 ++++++-
core/services/relay/grpc_provider_server.go | 68 +++++++++++++++++++
.../relay/grpc_provider_server_test.go | 27 ++++++++
core/services/relay/relay_test.go | 26 +++++++
4 files changed, 141 insertions(+), 3 deletions(-)
create mode 100644 core/services/relay/grpc_provider_server.go
create mode 100644 core/services/relay/grpc_provider_server_test.go
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 19296c72f0..9905ed6ae6 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -590,9 +590,26 @@ func (d *Delegate) newServicesGenericPlugin(
}
errorLog := &errorLog{jobID: jb.ID, recordError: d.jobORM.RecordError}
+ var providerClientConn grpc.ClientConnInterface
providerConn, ok := provider.(connProvider)
- if !ok {
- return nil, errors.New("provider not supported: the provider is not a LOOPP provider")
+ if ok {
+ providerClientConn = providerConn.ClientConn()
+ } else {
+ //We chose to deal with the difference between a LOOP provider and an embedded provider here rather than
+ //in NewServerAdapter because this has a smaller blast radius, as the scope of this workaround is to
+ //enable the medianpoc for EVM and not touch the other providers.
+ //TODO: remove this workaround when the EVM relayer is running inside of an LOOPP
+ d.lggr.Info("provider is not a LOOPP provider, switching to provider server")
+
+ ps, err2 := relay.NewProviderServer(provider, types.OCR2PluginType(cconf.ProviderType), d.lggr)
+ if err2 != nil {
+ return nil, fmt.Errorf("cannot start EVM provider server: %s", err)
+ }
+ providerClientConn, err2 = ps.GetConn()
+ if err2 != nil {
+ return nil, fmt.Errorf("cannot connect to EVM provider server: %s", err)
+ }
+ srvs = append(srvs, ps)
}
pluginConfig := types.ReportingPluginServiceConfig{
@@ -606,7 +623,7 @@ func (d *Delegate) newServicesGenericPlugin(
pr := generic.NewPipelineRunnerAdapter(pluginLggr, jb, d.pipelineRunner)
ta := generic.NewTelemetryAdapter(d.monitoringEndpointGen)
- plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerConn.ClientConn(), pr, ta, errorLog)
+ plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerClientConn, pr, ta, errorLog)
oracleArgs.ReportingPluginFactory = plugin
srvs = append(srvs, plugin)
diff --git a/core/services/relay/grpc_provider_server.go b/core/services/relay/grpc_provider_server.go
new file mode 100644
index 0000000000..943af0e636
--- /dev/null
+++ b/core/services/relay/grpc_provider_server.go
@@ -0,0 +1,68 @@
+package relay
+
+import (
+ "context"
+ "net"
+
+ "go.uber.org/multierr"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+type ProviderServer struct {
+ s *grpc.Server
+ lis net.Listener
+ lggr logger.Logger
+ conns []*grpc.ClientConn
+}
+
+func (p *ProviderServer) Start(ctx context.Context) error {
+ p.serve()
+ return nil
+}
+
+func (p *ProviderServer) Close() error {
+ var err error
+ for _, c := range p.conns {
+ err = multierr.Combine(err, c.Close())
+ }
+ p.s.Stop()
+ return err
+}
+
+func (p *ProviderServer) GetConn() (*grpc.ClientConn, error) {
+ cc, err := grpc.Dial(p.lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ p.conns = append(p.conns, cc)
+ return cc, err
+}
+
+// NewProviderServer creates a GRPC server that will wrap a provider, this is a workaround to test the Node API PoC until the EVM relayer is loopifyed
+func NewProviderServer(p types.PluginProvider, pType types.OCR2PluginType, lggr logger.Logger) (*ProviderServer, error) {
+ lis, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ return nil, err
+ }
+ ps := ProviderServer{
+ s: grpc.NewServer(),
+ lis: lis,
+ lggr: lggr.Named("EVM.ProviderServer"),
+ }
+ err = loop.RegisterStandAloneProvider(ps.s, p, pType)
+ if err != nil {
+ return nil, err
+ }
+
+ return &ps, nil
+}
+
+func (p *ProviderServer) serve() {
+ go func() {
+ if err := p.s.Serve(p.lis); err != nil {
+ p.lggr.Errorf("Failed to serve EVM provider server: %v", err)
+ }
+ }()
+}
diff --git a/core/services/relay/grpc_provider_server_test.go b/core/services/relay/grpc_provider_server_test.go
new file mode 100644
index 0000000000..e7ee8d7f15
--- /dev/null
+++ b/core/services/relay/grpc_provider_server_test.go
@@ -0,0 +1,27 @@
+package relay
+
+import (
+ "context"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+func TestProviderServer(t *testing.T) {
+ r := &mockRelayer{}
+ sa := NewServerAdapter(r, mockRelayerExt{})
+ mp, _ := sa.NewPluginProvider(context.Background(), types.RelayArgs{ProviderType: string(types.Median)}, types.PluginArgs{})
+
+ lggr := logger.TestLogger(t)
+ _, err := NewProviderServer(mp, "unsupported-type", lggr)
+ require.Error(t, err)
+
+ ps, err := NewProviderServer(staticMedianProvider{}, types.Median, lggr)
+ require.NoError(t, err)
+
+ _, err = ps.GetConn()
+ require.NoError(t, err)
+}
diff --git a/core/services/relay/relay_test.go b/core/services/relay/relay_test.go
index d3a9477349..5bcd14c64a 100644
--- a/core/services/relay/relay_test.go
+++ b/core/services/relay/relay_test.go
@@ -4,6 +4,8 @@ import (
"context"
"testing"
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
@@ -61,6 +63,30 @@ type staticMedianProvider struct {
types.MedianProvider
}
+func (s staticMedianProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester {
+ return nil
+}
+
+func (s staticMedianProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker {
+ return nil
+}
+
+func (s staticMedianProvider) ContractTransmitter() ocrtypes.ContractTransmitter {
+ return nil
+}
+
+func (s staticMedianProvider) ReportCodec() median.ReportCodec {
+ return nil
+}
+
+func (s staticMedianProvider) MedianContract() median.MedianContract {
+ return nil
+}
+
+func (s staticMedianProvider) OnchainConfigCodec() median.OnchainConfigCodec {
+ return nil
+}
+
type staticFunctionsProvider struct {
types.FunctionsProvider
}
From b66b7233ed5b9f432e621b62c213daf45f365574 Mon Sep 17 00:00:00 2001
From: Tate
Date: Mon, 13 Nov 2023 09:06:03 -0700
Subject: [PATCH 135/327] [TT-500][TT-682]Add build and lint to
integration-tests (#11221)
* Add build and lint to integration-tests
* Fix the build to actually build all the test files
* Add needs for the new job so it will affect required steps
* Review comments
* fix build and lint errors
* bump lint and go versions
* lint weirdness in migration test
* Wire the test context in the VRFV2SoakTest Run function to a parent context tied to the test.
* Merge conflict fix and improved .golangci lint file with fixes for those
* One more .golangci cleanup
* Fix newly added lint errors
* add build to integration-tests makefile
---
.github/actions/golangci-lint/action.yml | 2 +-
.github/workflows/integration-tests.yml | 72 ++++--
.../on-demand-vrfv2plus-performance-test.yml | 2 +-
.tool-versions | 4 +-
GNUmakefile | 2 +-
integration-tests/.golangci.yml | 78 +++++++
integration-tests/.tool-versions | 3 +-
integration-tests/Makefile | 6 +
integration-tests/actions/actions.go | 1 -
integration-tests/actions/actions_local.go | 2 +-
.../actions/automation_ocr_helpers.go | 5 +-
integration-tests/actions/ocr2_helpers.go | 7 +-
.../actions/ocr2_helpers_local.go | 11 +-
.../ocr2vrf_actions/ocr2vrf_config_helpers.go | 7 +-
.../actions/ocr2vrf_actions/ocr2vrf_steps.go | 8 +-
integration-tests/actions/ocr_helpers.go | 1 -
.../actions/ocr_helpers_local.go | 3 +-
.../actions/operator_forwarder_helpers.go | 18 +-
.../actions/vrfv2plus/vrfv2plus_steps.go | 5 +-
.../chaos/automation_chaos_test.go | 15 +-
integration-tests/chaos/ocr2vrf_chaos_test.go | 7 +-
integration-tests/chaos/ocr_chaos_test.go | 8 +-
integration-tests/client/chainlink_k8s.go | 2 +-
.../contracts/contract_deployer.go | 32 +--
.../contracts/contract_loader.go | 1 +
.../contracts/contract_vrf_models.go | 13 +-
.../contracts/ethereum_contracts.go | 15 +-
.../contracts/ethereum_keeper_contracts.go | 95 ++++----
integration-tests/contracts/test_contracts.go | 1 +
integration-tests/docker/cmd/test_env.go | 7 +-
integration-tests/docker/test_env/cl_node.go | 102 +--------
integration-tests/docker/test_env/test_env.go | 5 +-
.../docker/test_env/test_env_builder.go | 4 +-
integration-tests/load/functions/config.go | 4 +-
.../load/functions/functions_test.go | 5 +-
integration-tests/load/functions/gateway.go | 5 +-
.../load/functions/gateway_gun.go | 9 +-
.../load/functions/onchain_monitoring.go | 5 +-
.../load/functions/request_gun.go | 19 +-
integration-tests/load/functions/setup.go | 3 +-
.../load/log_poller/log_poller_test.go | 3 +-
integration-tests/load/vrfv2/cmd/dashboard.go | 3 +-
integration-tests/load/vrfv2/config.go | 1 +
integration-tests/load/vrfv2/gun.go | 5 +-
.../load/vrfv2/onchain_monitoring.go | 12 +-
integration-tests/load/vrfv2/vrfv2_test.go | 3 +-
integration-tests/load/vrfv2/vu.go | 3 +-
.../load/vrfv2plus/cmd/dashboard.go | 3 +-
integration-tests/load/vrfv2plus/config.go | 4 +
integration-tests/load/vrfv2plus/gun.go | 10 +-
.../load/vrfv2plus/onchain_monitoring.go | 8 +-
.../load/vrfv2plus/vrfv2plus_test.go | 22 +-
.../migration/upgrade_version_test.go | 5 +-
integration-tests/performance/cron_test.go | 3 +-
.../performance/directrequest_test.go | 4 +-
integration-tests/performance/flux_test.go | 10 +-
integration-tests/performance/keeper_test.go | 10 +-
integration-tests/performance/ocr_test.go | 8 +-
integration-tests/performance/vrf_test.go | 6 +-
.../reorg/automation_reorg_test.go | 16 +-
.../reorg/log_poller_maybe_reorg_test.go | 1 +
integration-tests/reorg/reorg_test.go | 8 +-
integration-tests/runner_helpers.go | 4 +-
integration-tests/smoke/automation_test.go | 120 +++++-----
integration-tests/smoke/flux_test.go | 10 +-
integration-tests/smoke/forwarder_ocr_test.go | 6 +-
.../smoke/forwarders_ocr2_test.go | 6 +-
integration-tests/smoke/keeper_test.go | 92 ++++----
integration-tests/smoke/log_poller_test.go | 1 +
integration-tests/smoke/ocr2_test.go | 6 +-
integration-tests/smoke/ocr2vrf_test.go | 11 +-
integration-tests/smoke/ocr_test.go | 6 +-
integration-tests/smoke/runlog_test.go | 4 +-
integration-tests/smoke/vrf_test.go | 6 +-
integration-tests/smoke/vrfv2_test.go | 6 +-
integration-tests/smoke/vrfv2plus_test.go | 89 ++++----
.../testreporters/keeper_benchmark.go | 4 +-
integration-tests/testreporters/ocr.go | 4 +-
integration-tests/testreporters/profile.go | 2 +-
integration-tests/testreporters/vrfv2plus.go | 5 +-
.../testsetups/keeper_benchmark.go | 10 +-
integration-tests/testsetups/ocr.go | 17 +-
integration-tests/testsetups/vrfv2.go | 6 +-
integration-tests/types/envcommon/common.go | 4 +-
.../universal/log_poller/config.go | 27 +--
integration-tests/universal/log_poller/gun.go | 7 +-
.../universal/log_poller/helpers.go | 212 ++++++++----------
.../universal/log_poller/scenarios.go | 26 +--
integration-tests/utils/cl_node_jobs.go | 5 +-
integration-tests/utils/common.go | 19 ++
integration-tests/utils/log.go | 19 --
integration-tests/utils/templates/secrets.go | 1 +
92 files changed, 759 insertions(+), 718 deletions(-)
create mode 100644 integration-tests/.golangci.yml
delete mode 100644 integration-tests/utils/log.go
diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml
index 97755fa46e..055960ff28 100644
--- a/.github/actions/golangci-lint/action.yml
+++ b/.github/actions/golangci-lint/action.yml
@@ -53,7 +53,7 @@ runs:
- name: golangci-lint
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
with:
- version: v1.55.0
+ version: v1.55.2
# We already cache these directories in setup-go
skip-pkg-cache: true
skip-build-cache: true
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index ba66a53ab6..9294dceae6 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -64,6 +64,36 @@ jobs:
outputs:
src: ${{ steps.changes.outputs.src }}
+ build-lint-integration-tests:
+ name: Build and Lint integration-tests
+ runs-on: ubuntu20.04-16cores-64GB
+ steps:
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Setup Go
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
+ with:
+ test_download_vendor_packages_command: cd ./integration-tests && go mod download
+ go_mod_path: ./integration-tests/go.mod
+ cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
+ cache_restore_only: "true"
+ - name: Build Go
+ run: |
+ cd ./integration-tests
+ go build ./...
+ SELECTED_NETWORKS=SIMULATED go test -run=^# ./...
+ - name: Lint Go
+ uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
+ with:
+ version: v1.55.2
+ # We already cache these directories in setup-go
+ skip-pkg-cache: true
+ skip-build-cache: true
+ # only-new-issues is only applicable to PRs, otherwise it is always set to false
+ only-new-issues: false # disabled for PRs due to unreliability
+ args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml
+ working-directory: ./integration-tests
+
build-chainlink:
environment: integration
permissions:
@@ -174,7 +204,7 @@ jobs:
pull-requests: write
id-token: write
contents: read
- needs: [build-chainlink, changes, compare-tests]
+ needs: [build-chainlink, changes, compare-tests, build-lint-integration-tests]
env:
SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2
CHAINLINK_COMMIT_SHA: ${{ github.sha }}
@@ -242,7 +272,7 @@ jobs:
pull-requests: write
id-token: write
contents: read
- needs: [build-chainlink, changes]
+ needs: [build-chainlink, changes, build-lint-integration-tests]
env:
SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2
CHAINLINK_COMMIT_SHA: ${{ github.sha }}
@@ -356,16 +386,16 @@ jobs:
run: |
PORT_BASE=3001
MAX_PORT=8000
-
+
# Use PR number as offset. Given GitHub PRs are incremental, this guarantees uniqueness for at least 5000 PRs.
OFFSET=$GITHUB_PR_NUMBER
echo "PR Number: $OFFSET"
-
+
# Ensure that we don't exceed the max port
if (( OFFSET > (MAX_PORT - PORT_BASE) )); then
OFFSET=$((OFFSET % (MAX_PORT - PORT_BASE)))
fi
-
+
# Map the offset to the port range
REMOTE_PORT=$((PORT_BASE + OFFSET))
echo "REMOTE_PORT=$REMOTE_PORT" >> $GITHUB_OUTPUT
@@ -376,25 +406,25 @@ jobs:
TRACING_SSH_SERVER: ${{ secrets.TRACING_SSH_SERVER }}
REMOTE_PORT: ${{ steps.generate-port.outputs.REMOTE_PORT }}
run: |
- eval $(ssh-agent)
- echo "test"
- echo "$TRACING_SSH_KEY" | wc -c
- echo "$TRACING_SSH_KEY" | tr -d '\r' | wc -c
- echo "$TRACING_SSH_KEY" | tr -d '\r' | base64 --decode | ssh-add -
- # f: background process
- # N: do not execute a remote command
- # R: remote port forwarding
- ssh -o StrictHostKeyChecking=no -f -N -R $REMOTE_PORT:127.0.0.1:3000 user-gha@$TRACING_SSH_SERVER
- echo "To view Grafana locally:"
- echo "ssh -N -L 8000:localhost:$REMOTE_PORT user-gha@$TRACING_SSH_SERVER"
- echo "Then visit http://localhost:8000 in a browser."
- echo "If you are unable to connect, check with the security team that you have access to the tracing server."
+ eval $(ssh-agent)
+ echo "test"
+ echo "$TRACING_SSH_KEY" | wc -c
+ echo "$TRACING_SSH_KEY" | tr -d '\r' | wc -c
+ echo "$TRACING_SSH_KEY" | tr -d '\r' | base64 --decode | ssh-add -
+ # f: background process
+ # N: do not execute a remote command
+ # R: remote port forwarding
+ ssh -o StrictHostKeyChecking=no -f -N -R $REMOTE_PORT:127.0.0.1:3000 user-gha@$TRACING_SSH_SERVER
+ echo "To view Grafana locally:"
+ echo "ssh -N -L 8000:localhost:$REMOTE_PORT user-gha@$TRACING_SSH_SERVER"
+ echo "Then visit http://localhost:8000 in a browser."
+ echo "If you are unable to connect, check with the security team that you have access to the tracing server."
- name: Show Grafana Logs
if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
run: |
- docker logs grafana
- docker logs tempo
- docker logs otel-collector
+ docker logs grafana
+ docker logs tempo
+ docker logs otel-collector
- name: Set sleep time to use in future steps
if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
run: |
diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
index c51f7f5a2f..b4f9f46de0 100644
--- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml
+++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
@@ -54,7 +54,7 @@ on:
useExistingEnv:
description: Set `true` to use existing environment or `false` to deploy CL node and all contracts
required: false
- default: false
+ default: "false"
configBase64:
description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env)
required: false
diff --git a/.tool-versions b/.tool-versions
index 87910cf6d6..c60396ccb8 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1,7 +1,7 @@
-golang 1.21.1
+golang 1.21.4
mockery 2.35.4
nodejs 16.16.0
postgres 13.3
helm 3.10.3
zig 0.10.1
-golangci-lint 1.55.0
+golangci-lint 1.55.2
diff --git a/GNUmakefile b/GNUmakefile
index 69d82da6c8..2801f94968 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -138,7 +138,7 @@ config-docs: ## Generate core node configuration documentation
.PHONY: golangci-lint
golangci-lint: ## Run golangci-lint for all issues.
[ -d "./golangci-lint" ] || mkdir ./golangci-lint && \
- docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.55.0 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 > ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt
+ docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.55.2 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 > ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt
GORELEASER_CONFIG ?= .goreleaser.yaml
diff --git a/integration-tests/.golangci.yml b/integration-tests/.golangci.yml
new file mode 100644
index 0000000000..d22b26b826
--- /dev/null
+++ b/integration-tests/.golangci.yml
@@ -0,0 +1,78 @@
+run:
+ timeout: 15m
+linters:
+ enable:
+ - exhaustive
+ - exportloopref
+ - revive
+ - goimports
+ - gosec
+ - misspell
+ - rowserrcheck
+ - errorlint
+linters-settings:
+ exhaustive:
+ default-signifies-exhaustive: true
+ goimports:
+ local-prefixes: github.com/smartcontractkit/chainlink
+ golint:
+ min-confidence: 0.999
+ gosec:
+ excludes:
+ - G101
+ govet:
+ # report about shadowed variables
+ check-shadowing: true
+ revive:
+ confidence: 0.8
+ rules:
+ - name: blank-imports
+ - name: context-as-argument
+ - name: context-keys-type
+ - name: dot-imports
+ - name: error-return
+ - name: error-strings
+ - name: error-naming
+ - name: if-return
+ - name: increment-decrement
+ # - name: var-naming // doesn't work with some generated names
+ - name: var-declaration
+ - name: package-comments
+ - name: range
+ - name: receiver-naming
+ - name: time-naming
+ - name: unexported-return
+ - name: indent-error-flow
+ - name: errorf
+ - name: empty-block
+ - name: superfluous-else
+ - name: unused-parameter
+ - name: unreachable-code
+ - name: redefines-builtin-id
+ - name: waitgroup-by-value
+ - name: unconditional-recursion
+ - name: struct-tag
+ - name: string-format
+ - name: string-of-int
+ - name: range-val-address
+ - name: range-val-in-closure
+ - name: modifies-value-receiver
+ - name: modifies-parameter
+ - name: identical-branches
+ - name: get-return
+ # - name: flag-parameter // probably one we should work on doing better at in the future
+ # - name: early-return // probably one we should work on doing better at in the future
+ - name: defer
+ - name: constant-logical-expr
+ - name: confusing-naming
+ - name: confusing-results
+ - name: bool-literal-in-expr
+ - name: atomic
+issues:
+ exclude-rules:
+ - text: "^G404: Use of weak random number generator"
+ linters:
+ - gosec
+ - linters:
+ - govet
+ text: "declaration of \"err\" shadows"
diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions
index 68b6d99419..47b73e9de1 100644
--- a/integration-tests/.tool-versions
+++ b/integration-tests/.tool-versions
@@ -1,4 +1,5 @@
-golang 1.21.1
+golang 1.21.4
k3d 5.4.6
kubectl 1.25.5
nodejs 18.13.0
+golangci-lint 1.55.2
diff --git a/integration-tests/Makefile b/integration-tests/Makefile
index 257331afcf..fb4bfa74f3 100644
--- a/integration-tests/Makefile
+++ b/integration-tests/Makefile
@@ -56,6 +56,12 @@ install_gotestfmt:
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
set -euo pipefail
+lint:
+ golangci-lint --color=always run ./... --fix -v
+
+build:
+ @go build ./... && SELECTED_NETWORKS=SIMULATED go test -run=^# ./...
+
# Builds the test image
# tag: the tag for the test image being built, example: tag=tate
# base_tag: the tag for the base-test-image to use, example: base_tag=latest
diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go
index bacf5a9dbf..02a2523477 100644
--- a/integration-tests/actions/actions.go
+++ b/integration-tests/actions/actions.go
@@ -254,7 +254,6 @@ func GetMockserverInitializerDataForOTPE(
func TeardownSuite(
t *testing.T,
env *environment.Environment,
- logsFolderPath string,
chainlinkNodes []*client.ChainlinkK8sClient,
optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics
failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level
diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go
index f5d2a9035f..d4913cabd8 100644
--- a/integration-tests/actions/actions_local.go
+++ b/integration-tests/actions/actions_local.go
@@ -17,7 +17,7 @@ func UpgradeChainlinkNodeVersionsLocal(
return fmt.Errorf("unable to upgrade node version, found empty image and version, must provide either a new image or a new version")
}
for _, node := range nodes {
- if err := node.UpgradeVersion(node.NodeConfig, newImage, newVersion); err != nil {
+ if err := node.UpgradeVersion(newImage, newVersion); err != nil {
return err
}
}
diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go
index 998b1ee89c..e1635902db 100644
--- a/integration-tests/actions/automation_ocr_helpers.go
+++ b/integration-tests/actions/automation_ocr_helpers.go
@@ -14,14 +14,15 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
- "github.com/smartcontractkit/chainlink-testing-framework/logging"
ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
+ "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go
index aead74f2bd..02ce73e813 100644
--- a/integration-tests/actions/ocr2_helpers.go
+++ b/integration-tests/actions/ocr2_helpers.go
@@ -15,14 +15,15 @@ import (
"golang.org/x/sync/errgroup"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go
index b3fe6eb041..65e0a466be 100644
--- a/integration-tests/actions/ocr2_helpers_local.go
+++ b/integration-tests/actions/ocr2_helpers_local.go
@@ -12,6 +12,12 @@ import (
"github.com/google/uuid"
"github.com/lib/pq"
"github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "golang.org/x/sync/errgroup"
+ "gopkg.in/guregu/null.v4"
+
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
@@ -19,11 +25,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "golang.org/x/sync/errgroup"
- "gopkg.in/guregu/null.v4"
)
func CreateOCRv2JobsLocal(
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go
index ce69396432..e424aaa11b 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go
@@ -16,9 +16,6 @@ import (
"go.dedis.ch/kyber/v3/group/edwards25519"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-testing-framework/logging"
- "github.com/smartcontractkit/chainlink/v2/core/services/job"
- "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/ocr2vrf/altbn_128"
@@ -26,6 +23,10 @@ import (
"github.com/smartcontractkit/ocr2vrf/ocr2vrf"
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink/v2/core/services/job"
+ "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
+
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
)
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
index c123aaff6a..72d668076e 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
@@ -22,6 +22,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func SetAndWaitForVRFBeaconProcessToFinish(t *testing.T, ocr2VRFPluginConfig *OCR2VRFPluginConfig, vrfBeacon contracts.VRFBeacon) {
@@ -172,7 +173,7 @@ func FundVRFCoordinatorV3Subscription(t *testing.T, linkToken contracts.LinkToke
require.NoError(t, err, "Error waiting for TXs to complete")
}
-func DeployOCR2VRFContracts(t *testing.T, contractDeployer contracts.ContractDeployer, chainClient blockchain.EVMClient, linkToken contracts.LinkToken, mockETHLinkFeed contracts.MockETHLINKFeed, beaconPeriodBlocksCount *big.Int, keyID string) (contracts.DKG, contracts.VRFCoordinatorV3, contracts.VRFBeacon, contracts.VRFBeaconConsumer) {
+func DeployOCR2VRFContracts(t *testing.T, contractDeployer contracts.ContractDeployer, chainClient blockchain.EVMClient, linkToken contracts.LinkToken, beaconPeriodBlocksCount *big.Int, keyID string) (contracts.DKG, contracts.VRFCoordinatorV3, contracts.VRFBeacon, contracts.VRFBeaconConsumer) {
dkg, err := contractDeployer.DeployDKG()
require.NoError(t, err, "Error deploying DKG Contract")
@@ -272,14 +273,14 @@ func RequestRandomnessFulfillmentAndWaitForFulfilment(
}
func getRequestId(t *testing.T, consumer contracts.VRFBeaconConsumer, receipt *types.Receipt, confirmationDelay *big.Int) *big.Int {
- periodBlocks, err := consumer.IBeaconPeriodBlocks(nil)
+ periodBlocks, err := consumer.IBeaconPeriodBlocks(utils.TestContext(t))
require.NoError(t, err, "Error getting Beacon Period block count")
blockNumber := receipt.BlockNumber
periodOffset := new(big.Int).Mod(blockNumber, periodBlocks)
nextBeaconOutputHeight := new(big.Int).Sub(new(big.Int).Add(blockNumber, periodBlocks), periodOffset)
- requestID, err := consumer.GetRequestIdsBy(nil, nextBeaconOutputHeight, confirmationDelay)
+ requestID, err := consumer.GetRequestIdsBy(utils.TestContext(t), nextBeaconOutputHeight, confirmationDelay)
require.NoError(t, err, "Error getting requestID from consumer contract")
return requestID
@@ -305,7 +306,6 @@ func SetupOCR2VRFUniverse(
contractDeployer,
chainClient,
linkToken,
- mockETHLinkFeed,
ocr2vrf_constants.BeaconPeriodBlocksCount,
ocr2vrf_constants.KeyID,
)
diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go
index cfc8cfe589..4f713dcdd6 100644
--- a/integration-tests/actions/ocr_helpers.go
+++ b/integration-tests/actions/ocr_helpers.go
@@ -27,7 +27,6 @@ func DeployOCRContracts(
numberOfContracts int,
linkTokenContract contracts.LinkToken,
contractDeployer contracts.ContractDeployer,
- bootstrapNode *client.ChainlinkK8sClient,
workerNodes []*client.ChainlinkK8sClient,
client blockchain.EVMClient,
) ([]contracts.OffchainAggregator, error) {
diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go
index 5836ee7945..e6dd5ae77f 100644
--- a/integration-tests/actions/ocr_helpers_local.go
+++ b/integration-tests/actions/ocr_helpers_local.go
@@ -10,9 +10,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/rs/zerolog"
+ "golang.org/x/sync/errgroup"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
- "golang.org/x/sync/errgroup"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
diff --git a/integration-tests/actions/operator_forwarder_helpers.go b/integration-tests/actions/operator_forwarder_helpers.go
index 37b50c4fa9..a1d7135416 100644
--- a/integration-tests/actions/operator_forwarder_helpers.go
+++ b/integration-tests/actions/operator_forwarder_helpers.go
@@ -1,7 +1,6 @@
package actions
import (
- "context"
"math/big"
"testing"
@@ -17,6 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func DeployForwarderContracts(
@@ -67,7 +67,7 @@ func AcceptAuthorizedReceiversOperator(
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for events in nodes shouldn't fail")
- senders, err := forwarderInstance.GetAuthorizedSenders(context.Background())
+ senders, err := forwarderInstance.GetAuthorizedSenders(utils.TestContext(t))
require.NoError(t, err, "Getting authorized senders shouldn't fail")
var nodesAddrs []string
for _, o := range nodeAddresses {
@@ -75,20 +75,18 @@ func AcceptAuthorizedReceiversOperator(
}
require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses")
- owner, err := forwarderInstance.Owner(context.Background())
+ owner, err := forwarderInstance.Owner(utils.TestContext(t))
require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail")
require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator")
}
func ProcessNewEvent(
t *testing.T,
- eventSub geth.Subscription,
operatorCreated chan *operator_factory.OperatorFactoryOperatorCreated,
authorizedForwarderCreated chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated,
event *types.Log,
eventDetails *abi.Event,
operatorFactoryInstance contracts.OperatorFactory,
- contractABI *abi.ABI,
chainClient blockchain.EVMClient,
) {
l := logging.GetTestLogger(t)
@@ -141,7 +139,7 @@ func SubscribeOperatorFactoryEvents(
l := logging.GetTestLogger(t)
contractABI, err := operator_factory.OperatorFactoryMetaData.GetAbi()
require.NoError(t, err, "Getting contract abi for OperatorFactory shouldn't fail")
- latestBlockNum, err := chainClient.LatestBlockNumber(context.Background())
+ latestBlockNum, err := chainClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail")
query := geth.FilterQuery{
FromBlock: big.NewInt(0).SetUint64(latestBlockNum),
@@ -149,7 +147,7 @@ func SubscribeOperatorFactoryEvents(
}
eventLogs := make(chan types.Log)
- sub, err := chainClient.SubscribeFilterLogs(context.Background(), query, eventLogs)
+ sub, err := chainClient.SubscribeFilterLogs(utils.TestContext(t), query, eventLogs)
require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail")
go func() {
defer sub.Unsubscribe()
@@ -160,14 +158,14 @@ func SubscribeOperatorFactoryEvents(
l.Error().Err(err).Msg("Error while watching for new contract events. Retrying Subscription")
sub.Unsubscribe()
- sub, err = chainClient.SubscribeFilterLogs(context.Background(), query, eventLogs)
+ sub, err = chainClient.SubscribeFilterLogs(utils.TestContext(t), query, eventLogs)
require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail")
case vLog := <-eventLogs:
eventDetails, err := contractABI.EventByID(vLog.Topics[0])
require.NoError(t, err, "Getting event details for OperatorFactory instance shouldn't fail")
go ProcessNewEvent(
- t, sub, operatorCreated, authorizedForwarderCreated, &vLog,
- eventDetails, operatorFactoryInstance, contractABI, chainClient,
+ t, operatorCreated, authorizedForwarderCreated, &vLog,
+ eventDetails, operatorFactoryInstance, chainClient,
)
if eventDetails.Name == "AuthorizedForwarderCreated" || eventDetails.Name == "OperatorCreated" {
remainingExpectedEvents--
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index e964623fb2..28fb2635ff 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -15,6 +15,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/rs/zerolog"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
@@ -802,7 +803,7 @@ func WaitForRequestCountEqualToFulfilmentCount(consumer contracts.VRFv2PlusLoadT
fmt.Errorf("timeout waiting for rand request and fulfilments to be equal AFTER performance test was executed. Request Count: %d, Fulfilment Count: %d",
metrics.RequestCount.Uint64(), metrics.FulfilmentCount.Uint64())
case <-ticker.C:
- go getLoadTestMetrics(consumer, metricsChannel, metricsErrorChannel)
+ go retreiveLoadTestMetrics(consumer, metricsChannel, metricsErrorChannel)
case metrics = <-metricsChannel:
if metrics.RequestCount.Cmp(metrics.FulfilmentCount) == 0 {
ticker.Stop()
@@ -852,7 +853,7 @@ func ReturnFundsForFulfilledRequests(client blockchain.EVMClient, coordinator co
return nil
}
-func getLoadTestMetrics(
+func retreiveLoadTestMetrics(
consumer contracts.VRFv2PlusLoadTestConsumer,
metricsChannel chan *contracts.VRFLoadTestMetrics,
metricsErrorChannel chan error,
diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go
index 22c9e742f3..6ebf14d806 100644
--- a/integration-tests/chaos/automation_chaos_test.go
+++ b/integration-tests/chaos/automation_chaos_test.go
@@ -1,7 +1,6 @@
package chaos
import (
- "context"
"fmt"
"math/big"
"testing"
@@ -25,6 +24,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -116,6 +116,7 @@ func TestAutomationChaos(t *testing.T) {
}
for name, registryVersion := range registryVersions {
+ registryVersion := registryVersion
t.Run(name, func(t *testing.T) {
t.Parallel()
@@ -176,9 +177,9 @@ func TestAutomationChaos(t *testing.T) {
},
}
- for n, tst := range testCases {
- name := n
- testCase := tst
+ for name, testCase := range testCases {
+ name := name
+ testCase := testCase
t.Run(fmt.Sprintf("Automation_%s", name), func(t *testing.T) {
t.Parallel()
network := networks.MustGetSelectedNetworksFromEnv()[0] // Need a new copy of the network for each test
@@ -223,7 +224,7 @@ func TestAutomationChaos(t *testing.T) {
if chainClient != nil {
chainClient.GasStats().PrintStats()
}
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
@@ -268,7 +269,7 @@ func TestAutomationChaos(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(it_utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
@@ -283,7 +284,7 @@ func TestAutomationChaos(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(it_utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 10
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go
index ba75974f01..8739a5960a 100644
--- a/integration-tests/chaos/ocr2vrf_chaos_test.go
+++ b/integration-tests/chaos/ocr2vrf_chaos_test.go
@@ -25,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCR2VRFChaos(t *testing.T) {
@@ -149,7 +150,7 @@ func TestOCR2VRFChaos(t *testing.T) {
require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail")
t.Cleanup(func() {
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
@@ -185,7 +186,7 @@ func TestOCR2VRFChaos(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(nil, requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err)
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
@@ -212,7 +213,7 @@ func TestOCR2VRFChaos(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(nil, requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err, "Error getting Randomness result from Consumer Contract")
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go
index 599fad8ddc..76e25d9200 100644
--- a/integration-tests/chaos/ocr_chaos_test.go
+++ b/integration-tests/chaos/ocr_chaos_test.go
@@ -1,7 +1,6 @@
package chaos
import (
- "context"
"fmt"
"math/big"
"os"
@@ -27,6 +26,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -164,7 +164,7 @@ func TestOCRChaos(t *testing.T) {
if chainClient != nil {
chainClient.GasStats().PrintStats()
}
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
@@ -180,7 +180,7 @@ func TestOCRChaos(t *testing.T) {
err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(10))
require.NoError(t, err)
- ocrInstances, err := actions.DeployOCRContracts(1, lt, cd, bootstrapNode, workerNodes, chainClient)
+ ocrInstances, err := actions.DeployOCRContracts(1, lt, cd, workerNodes, chainClient)
require.NoError(t, err)
err = chainClient.WaitForEvents()
require.NoError(t, err)
@@ -195,7 +195,7 @@ func TestOCRChaos(t *testing.T) {
err := ocr.RequestNewRound()
require.NoError(t, err, "Error requesting new round")
}
- round, err := ocrInstances[0].GetLatestRound(context.Background())
+ round, err := ocrInstances[0].GetLatestRound(it_utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred())
l.Info().Int64("RoundID", round.RoundId.Int64()).Msg("Latest OCR Round")
if round.RoundId.Int64() == chaosStartRound && !chaosApplied {
diff --git a/integration-tests/client/chainlink_k8s.go b/integration-tests/client/chainlink_k8s.go
index 3fbf9eaf73..27fd956103 100644
--- a/integration-tests/client/chainlink_k8s.go
+++ b/integration-tests/client/chainlink_k8s.go
@@ -63,7 +63,7 @@ func (c *ChainlinkK8sClient) UpgradeVersion(testEnvironment *environment.Environ
},
},
}
- testEnvironment, err := testEnvironment.UpdateHelm(c.ChartName, upgradeVals)
+ _, err := testEnvironment.UpdateHelm(c.ChartName, upgradeVals)
return err
}
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index 916971f82d..45195d327e 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -12,11 +12,12 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper"
+ "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark"
@@ -868,22 +869,21 @@ func (e *EthereumContractDeployer) LoadKeeperRegistrar(address common.Address, r
client: e.client,
registrar20: instance.(*keeper_registrar_wrapper2_0.KeeperRegistrar),
}, err
- } else {
- instance, err := e.client.LoadContract("AutomationRegistrar", address, func(
- address common.Address,
- backend bind.ContractBackend,
- ) (interface{}, error) {
- return registrar21.NewAutomationRegistrar(address, backend)
- })
- if err != nil {
- return nil, err
- }
- return &EthereumKeeperRegistrar{
- address: &address,
- client: e.client,
- registrar21: instance.(*registrar21.AutomationRegistrar),
- }, err
}
+ instance, err := e.client.LoadContract("AutomationRegistrar", address, func(
+ address common.Address,
+ backend bind.ContractBackend,
+ ) (interface{}, error) {
+ return registrar21.NewAutomationRegistrar(address, backend)
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &EthereumKeeperRegistrar{
+ address: &address,
+ client: e.client,
+ registrar21: instance.(*registrar21.AutomationRegistrar),
+ }, err
}
func (e *EthereumContractDeployer) DeployKeeperRegistry(
diff --git a/integration-tests/contracts/contract_loader.go b/integration-tests/contracts/contract_loader.go
index cfe7a35467..9a2f20226d 100644
--- a/integration-tests/contracts/contract_loader.go
+++ b/integration-tests/contracts/contract_loader.go
@@ -2,6 +2,7 @@ package contracts
import (
"errors"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics"
diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go
index c82924143b..baee2ccd92 100644
--- a/integration-tests/contracts/contract_vrf_models.go
+++ b/integration-tests/contracts/contract_vrf_models.go
@@ -262,12 +262,13 @@ type RequestStatus struct {
}
type LoadTestRequestStatus struct {
- Fulfilled bool
- RandomWords []*big.Int
- requestTimestamp *big.Int
- fulfilmentTimestamp *big.Int
- requestBlockNumber *big.Int
- fulfilmentBlockNumber *big.Int
+ Fulfilled bool
+ RandomWords []*big.Int
+ // Currently Unused November 8, 2023, Mignt be used in near future, will remove if not.
+ // requestTimestamp *big.Int
+ // fulfilmentTimestamp *big.Int
+ // requestBlockNumber *big.Int
+ // fulfilmentBlockNumber *big.Int
}
type VRFLoadTestMetrics struct {
diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go
index cde6e325f2..9cb858fe00 100644
--- a/integration-tests/contracts/ethereum_contracts.go
+++ b/integration-tests/contracts/ethereum_contracts.go
@@ -16,6 +16,11 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
+ "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
+ ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper"
+ ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client"
@@ -43,10 +48,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock"
- "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
- "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
- ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper"
- ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types"
"github.com/smartcontractkit/chainlink/integration-tests/client"
eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
@@ -939,7 +940,7 @@ func (f *EthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, e
return payment, nil
}
-func (f *EthereumFluxAggregator) RequestNewRound(ctx context.Context) error {
+func (f *EthereumFluxAggregator) RequestNewRound(_ context.Context) error {
opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet())
if err != nil {
return err
@@ -978,7 +979,7 @@ func (f *EthereumFluxAggregator) WatchSubmissionReceived(ctx context.Context, ev
}
}
-func (f *EthereumFluxAggregator) SetRequesterPermissions(ctx context.Context, addr common.Address, authorized bool, roundsDelay uint32) error {
+func (f *EthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error {
opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet())
if err != nil {
return err
@@ -1019,7 +1020,7 @@ func (f *EthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, e
}
func (f *EthereumFluxAggregator) WithdrawPayment(
- ctx context.Context,
+ _ context.Context,
from common.Address,
to common.Address,
amount *big.Int) error {
diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go
index 135b016ee5..2c0250e745 100644
--- a/integration-tests/contracts/ethereum_keeper_contracts.go
+++ b/integration-tests/contracts/ethereum_keeper_contracts.go
@@ -250,25 +250,25 @@ func (rcs *KeeperRegistrySettings) EncodeOnChainConfig(registrar string, registr
encodedOnchainConfig, err := utilsABI.Methods["_onChainConfig"].Inputs.Pack(&onchainConfigStruct)
return encodedOnchainConfig, err
- } else {
- configType := goabi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)")
- onchainConfig, err := goabi.Encode(map[string]interface{}{
- "paymentPremiumPPB": rcs.PaymentPremiumPPB,
- "flatFeeMicroLink": rcs.FlatFeeMicroLINK,
- "checkGasLimit": rcs.CheckGasLimit,
- "stalenessSeconds": rcs.StalenessSeconds,
- "gasCeilingMultiplier": rcs.GasCeilingMultiplier,
- "minUpkeepSpend": rcs.MinUpkeepSpend,
- "maxPerformGas": rcs.MaxPerformGas,
- "maxCheckDataSize": rcs.MaxCheckDataSize,
- "maxPerformDataSize": rcs.MaxPerformDataSize,
- "fallbackGasPrice": rcs.FallbackGasPrice,
- "fallbackLinkPrice": rcs.FallbackLinkPrice,
- "transcoder": common.Address{},
- "registrar": registrar,
- }, configType)
- return onchainConfig, err
}
+ configType := goabi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)")
+ onchainConfig, err := goabi.Encode(map[string]interface{}{
+ "paymentPremiumPPB": rcs.PaymentPremiumPPB,
+ "flatFeeMicroLink": rcs.FlatFeeMicroLINK,
+ "checkGasLimit": rcs.CheckGasLimit,
+ "stalenessSeconds": rcs.StalenessSeconds,
+ "gasCeilingMultiplier": rcs.GasCeilingMultiplier,
+ "minUpkeepSpend": rcs.MinUpkeepSpend,
+ "maxPerformGas": rcs.MaxPerformGas,
+ "maxCheckDataSize": rcs.MaxCheckDataSize,
+ "maxPerformDataSize": rcs.MaxPerformDataSize,
+ "fallbackGasPrice": rcs.FallbackGasPrice,
+ "fallbackLinkPrice": rcs.FallbackLinkPrice,
+ "transcoder": common.Address{},
+ "registrar": registrar,
+ }, configType)
+ return onchainConfig, err
+
}
func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address {
@@ -276,6 +276,7 @@ func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address {
Pending: false,
}
+ //nolint: exhaustive
switch v.version {
case ethereum.RegistryVersion_2_1:
ownerAddress, _ := v.registry2_1.Owner(callOpts)
@@ -283,6 +284,8 @@ func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address {
case ethereum.RegistryVersion_2_0:
ownerAddress, _ := v.registry2_0.Owner(callOpts)
return ownerAddress
+ case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1, ethereum.RegistryVersion_1_2, ethereum.RegistryVersion_1_3:
+ return common.HexToAddress(v.client.GetDefaultWallet().Address())
}
return common.HexToAddress(v.client.GetDefaultWallet().Address())
@@ -664,7 +667,7 @@ func (v *EthereumKeeperRegistry) GetKeeperInfo(ctx context.Context, keeperAddr s
info, err = v.registry1_2.GetKeeperInfo(opts, common.HexToAddress(keeperAddr))
case ethereum.RegistryVersion_1_3:
info, err = v.registry1_3.GetKeeperInfo(opts, common.HexToAddress(keeperAddr))
- case ethereum.RegistryVersion_2_0:
+ case ethereum.RegistryVersion_2_0, ethereum.RegistryVersion_2_1:
// this is not used anywhere
return nil, fmt.Errorf("not supported")
}
@@ -710,6 +713,8 @@ func (v *EthereumKeeperRegistry) SetKeepers(keepers []string, payees []string, o
ocrConfig.OffchainConfigVersion,
ocrConfig.OffchainConfig,
)
+ case ethereum.RegistryVersion_2_1:
+ return fmt.Errorf("not supported")
}
if err != nil {
@@ -760,6 +765,8 @@ func (v *EthereumKeeperRegistry) RegisterUpkeep(target string, gasLimit uint32,
checkData,
nil, //offchain config
)
+ case ethereum.RegistryVersion_2_1:
+ return fmt.Errorf("not supported")
}
if err != nil {
@@ -877,6 +884,8 @@ func (v *EthereumKeeperRegistry) GetKeeperList(ctx context.Context) ([]string, e
return []string{}, err
}
list = state.Transmitters
+ case ethereum.RegistryVersion_2_1:
+ return nil, fmt.Errorf("not supported")
}
if err != nil {
@@ -1112,6 +1121,7 @@ func (v *EthereumKeeperRegistry) ParseUpkeepPerformedLog(log *types.Log) (*Upkee
// ParseStaleUpkeepReportLog Parses Stale upkeep report log
func (v *EthereumKeeperRegistry) ParseStaleUpkeepReportLog(log *types.Log) (*StaleUpkeepReportLog, error) {
+ //nolint:exhaustive
switch v.version {
case ethereum.RegistryVersion_2_0:
parsedLog, err := v.registry2_0.ParseStaleUpkeepReport(*log)
@@ -1129,7 +1139,6 @@ func (v *EthereumKeeperRegistry) ParseStaleUpkeepReportLog(log *types.Log) (*Sta
return &StaleUpkeepReportLog{
Id: parsedLog.Id,
}, nil
-
}
return nil, fmt.Errorf("keeper registry version %d is not supported", v.version)
}
@@ -1850,7 +1859,7 @@ func (v *EthereumKeeperConsumerPerformance) GetUpkeepCount(ctx context.Context)
return eligible, err
}
-func (v *EthereumKeeperConsumerPerformance) SetCheckGasToBurn(ctx context.Context, gas *big.Int) error {
+func (v *EthereumKeeperConsumerPerformance) SetCheckGasToBurn(_ context.Context, gas *big.Int) error {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
return err
@@ -1862,7 +1871,7 @@ func (v *EthereumKeeperConsumerPerformance) SetCheckGasToBurn(ctx context.Contex
return v.client.ProcessTransaction(tx)
}
-func (v *EthereumKeeperConsumerPerformance) SetPerformGasToBurn(ctx context.Context, gas *big.Int) error {
+func (v *EthereumKeeperConsumerPerformance) SetPerformGasToBurn(_ context.Context, gas *big.Int) error {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
return err
@@ -1897,7 +1906,7 @@ func (v *EthereumKeeperPerformDataCheckerConsumer) Counter(ctx context.Context)
return cnt, nil
}
-func (v *EthereumKeeperPerformDataCheckerConsumer) SetExpectedData(ctx context.Context, expectedData []byte) error {
+func (v *EthereumKeeperPerformDataCheckerConsumer) SetExpectedData(_ context.Context, expectedData []byte) error {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
return err
@@ -2041,31 +2050,23 @@ func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byt
common.HexToAddress(senderAddr),
)
- if err != nil {
- return nil, err
- }
- return req, nil
- } else {
- req, err := registrarABI.Pack(
- "register",
- name,
- email,
- common.HexToAddress(upkeepAddr),
- gasLimit,
- common.HexToAddress(adminAddr),
- uint8(0), // trigger type
- checkData,
- []byte{}, // triggerConfig
- []byte{}, // offchainConfig
- amount,
- common.HexToAddress(senderAddr),
- )
-
- if err != nil {
- return nil, err
- }
- return req, nil
+ return req, err
}
+ req, err := registrarABI.Pack(
+ "register",
+ name,
+ email,
+ common.HexToAddress(upkeepAddr),
+ gasLimit,
+ common.HexToAddress(adminAddr),
+ uint8(0), // trigger type
+ checkData,
+ []byte{}, // triggerConfig
+ []byte{}, // offchainConfig
+ amount,
+ common.HexToAddress(senderAddr),
+ )
+ return req, err
}
registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.ABI))
if err != nil {
diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go
index ccdd2989e4..3080668da6 100644
--- a/integration-tests/contracts/test_contracts.go
+++ b/integration-tests/contracts/test_contracts.go
@@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/rs/zerolog"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
diff --git a/integration-tests/docker/cmd/test_env.go b/integration-tests/docker/cmd/test_env.go
index f760f45f8d..5fe2001350 100644
--- a/integration-tests/docker/cmd/test_env.go
+++ b/integration-tests/docker/cmd/test_env.go
@@ -9,10 +9,11 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
"github.com/spf13/cobra"
"github.com/testcontainers/testcontainers-go"
+
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
)
func main() {
@@ -31,7 +32,7 @@ func main() {
Use: "cl-cluster",
Short: "Basic CL cluster",
RunE: func(cmd *cobra.Command, args []string) error {
- utils.SetupCoreDockerEnvLogger()
+ log.Logger = logging.GetLogger(nil, "CORE_DOCKER_ENV_LOG_LEVEL")
log.Info().Msg("Starting CL cluster test environment..")
_, err := test_env.NewCLTestEnvBuilder().
diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go
index 6e74e54a4f..3c0a6d3af7 100644
--- a/integration-tests/docker/test_env/cl_node.go
+++ b/integration-tests/docker/test_env/cl_node.go
@@ -1,15 +1,11 @@
package test_env
import (
- "context"
- "crypto/ed25519"
- "encoding/hex"
"fmt"
"math/big"
"net/url"
"os"
"strings"
- "sync"
"testing"
"time"
@@ -29,8 +25,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/logwatch"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/utils"
@@ -118,7 +112,7 @@ func (n *ClNode) SetTestLogger(t *testing.T) {
// Restart restarts only CL node, DB container is reused
func (n *ClNode) Restart(cfg *chainlink.Config) error {
- if err := n.Container.Terminate(context.Background()); err != nil {
+ if err := n.Container.Terminate(utils.TestContext(n.t)); err != nil {
return err
}
n.NodeConfig = cfg
@@ -126,7 +120,7 @@ func (n *ClNode) Restart(cfg *chainlink.Config) error {
}
// UpgradeVersion restarts the cl node with new image and version
-func (n *ClNode) UpgradeVersion(cfg *chainlink.Config, newImage, newVersion string) error {
+func (n *ClNode) UpgradeVersion(newImage, newVersion string) error {
if newVersion == "" {
return fmt.Errorf("new version is empty")
}
@@ -142,9 +136,9 @@ func (n *ClNode) PrimaryETHAddress() (string, error) {
return n.API.PrimaryEthAddress()
}
-func (n *ClNode) AddBootstrapJob(verifierAddr common.Address, fromBlock uint64, chainId int64,
+func (n *ClNode) AddBootstrapJob(verifierAddr common.Address, chainId int64,
feedId [32]byte) (*client.Job, error) {
- spec := utils.BuildBootstrapSpec(verifierAddr, chainId, fromBlock, feedId)
+ spec := utils.BuildBootstrapSpec(verifierAddr, chainId, feedId)
return n.API.MustCreateJob(spec)
}
@@ -196,7 +190,7 @@ func (n *ClNode) AddMercuryOCRJob(verifierAddr common.Address, fromBlock uint64,
}
func (n *ClNode) GetContainerName() string {
- name, err := n.Container.Name(context.Background())
+ name, err := n.Container.Name(utils.TestContext(n.t))
if err != nil {
return ""
}
@@ -288,15 +282,15 @@ func (n *ClNode) StartContainer() error {
return fmt.Errorf("%s err: %w", ErrStartCLNodeContainer, err)
}
if n.lw != nil {
- if err := n.lw.ConnectContainer(context.Background(), container, "cl-node", true); err != nil {
+ if err := n.lw.ConnectContainer(utils.TestContext(n.t), container, "cl-node", true); err != nil {
return err
}
}
- clEndpoint, err := test_env.GetEndpoint(context.Background(), container, "http")
+ clEndpoint, err := test_env.GetEndpoint(utils.TestContext(n.t), container, "http")
if err != nil {
return err
}
- ip, err := container.ContainerIP(context.Background())
+ ip, err := container.ContainerIP(utils.TestContext(n.t))
if err != nil {
return err
}
@@ -414,83 +408,3 @@ func (n *ClNode) getContainerRequest(secrets string) (
},
}, nil
}
-
-func GetOracleIdentities(chainlinkNodes []*ClNode) ([]int, []confighelper.OracleIdentityExtra) {
- S := make([]int, len(chainlinkNodes))
- oracleIdentities := make([]confighelper.OracleIdentityExtra, len(chainlinkNodes))
- sharedSecretEncryptionPublicKeys := make([]ocrtypes.ConfigEncryptionPublicKey, len(chainlinkNodes))
- var wg sync.WaitGroup
- for i, cl := range chainlinkNodes {
- wg.Add(1)
- go func(i int, cl *ClNode) error {
- defer wg.Done()
-
- ocr2Keys, err := cl.API.MustReadOCR2Keys()
- if err != nil {
- return err
- }
- var ocr2Config client.OCR2KeyAttributes
- for _, key := range ocr2Keys.Data {
- if key.Attributes.ChainType == string(chaintype.EVM) {
- ocr2Config = key.Attributes
- break
- }
- }
-
- keys, err := cl.API.MustReadP2PKeys()
- if err != nil {
- return err
- }
- p2pKeyID := keys.Data[0].Attributes.PeerID
-
- offchainPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.OffChainPublicKey, "ocr2off_evm_"))
- if err != nil {
- return err
- }
-
- offchainPkBytesFixed := [ed25519.PublicKeySize]byte{}
- copy(offchainPkBytesFixed[:], offchainPkBytes)
- if err != nil {
- return err
- }
-
- configPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.ConfigPublicKey, "ocr2cfg_evm_"))
- if err != nil {
- return err
- }
-
- configPkBytesFixed := [ed25519.PublicKeySize]byte{}
- copy(configPkBytesFixed[:], configPkBytes)
- if err != nil {
- return err
- }
-
- onchainPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.OnChainPublicKey, "ocr2on_evm_"))
- if err != nil {
- return err
- }
-
- csaKeys, _, err := cl.API.ReadCSAKeys()
- if err != nil {
- return err
- }
-
- sharedSecretEncryptionPublicKeys[i] = configPkBytesFixed
- oracleIdentities[i] = confighelper.OracleIdentityExtra{
- OracleIdentity: confighelper.OracleIdentity{
- OnchainPublicKey: onchainPkBytes,
- OffchainPublicKey: offchainPkBytesFixed,
- PeerID: p2pKeyID,
- TransmitAccount: ocrtypes.Account(csaKeys.Data[0].ID),
- },
- ConfigEncryptionPublicKey: configPkBytesFixed,
- }
- S[i] = 1
-
- return nil
- }(i, cl)
- }
- wg.Wait()
-
- return S, oracleIdentities
-}
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index 4a30487211..9987bab2fe 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -1,7 +1,6 @@
package test_env
import (
- "context"
"encoding/json"
"fmt"
"io"
@@ -53,7 +52,7 @@ type CLClusterTestEnv struct {
}
func NewTestEnv() (*CLClusterTestEnv, error) {
- utils.SetupCoreDockerEnvLogger()
+ log.Logger = logging.GetLogger(nil, "CORE_DOCKER_ENV_LOG_LEVEL")
network, err := docker.CreateNetwork(log.Logger)
if err != nil {
return nil, err
@@ -267,7 +266,7 @@ func (te *CLClusterTestEnv) collectTestLogs() error {
return err
}
defer logFile.Close()
- logReader, err := node.Container.Logs(context.Background())
+ logReader, err := node.Container.Logs(utils.TestContext(te.t))
if err != nil {
return err
}
diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go
index e97f869d64..77c5669015 100644
--- a/integration-tests/docker/test_env/test_env_builder.go
+++ b/integration-tests/docker/test_env/test_env_builder.go
@@ -188,7 +188,7 @@ func (b *CLTestEnvBuilder) WithCustomCleanup(customFn func()) *CLTestEnvBuilder
type ChainOption = func(*evmcfg.Chain) *evmcfg.Chain
func (b *CLTestEnvBuilder) WithChainOptions(opts ...ChainOption) *CLTestEnvBuilder {
- b.chainOptionsFn = make([]ChainOption, 0, 0)
+ b.chainOptionsFn = make([]ChainOption, 0)
b.chainOptionsFn = append(b.chainOptionsFn, opts...)
return b
@@ -197,7 +197,7 @@ func (b *CLTestEnvBuilder) WithChainOptions(opts ...ChainOption) *CLTestEnvBuild
type EVMClientNetworkOption = func(*blockchain.EVMNetwork) *blockchain.EVMNetwork
func (b *CLTestEnvBuilder) EVMClientNetworkOptions(opts ...EVMClientNetworkOption) *CLTestEnvBuilder {
- b.evmClientNetworkOption = make([]EVMClientNetworkOption, 0, 0)
+ b.evmClientNetworkOption = make([]EVMClientNetworkOption, 0)
b.evmClientNetworkOption = append(b.evmClientNetworkOption, opts...)
return b
diff --git a/integration-tests/load/functions/config.go b/integration-tests/load/functions/config.go
index 451d01a6c8..ad7e7446af 100644
--- a/integration-tests/load/functions/config.go
+++ b/integration-tests/load/functions/config.go
@@ -7,6 +7,7 @@ import (
"github.com/pelletier/go-toml/v2"
"github.com/rs/zerolog/log"
+
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
@@ -118,8 +119,7 @@ func ReadConfig() (*PerformanceConfig, error) {
return nil, fmt.Errorf(
"ensure variables are set:\nMUMBAI_KEYS variable, private keys, comma separated\nSELECTED_NETWORKS=MUMBAI\nMUMBAI_URLS variable, websocket urls, comma separated",
)
- } else {
- cfg.MumbaiPrivateKey = mpk
}
+ cfg.MumbaiPrivateKey = mpk
return cfg, nil
}
diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go
index 7822035208..dc52846d3c 100644
--- a/integration-tests/load/functions/functions_test.go
+++ b/integration-tests/load/functions/functions_test.go
@@ -1,10 +1,11 @@
package loadfunctions
import (
- "github.com/smartcontractkit/wasp"
- "github.com/stretchr/testify/require"
"testing"
"time"
+
+ "github.com/smartcontractkit/wasp"
+ "github.com/stretchr/testify/require"
)
func TestFunctionsLoad(t *testing.T) {
diff --git a/integration-tests/load/functions/gateway.go b/integration-tests/load/functions/gateway.go
index 78b0f14cf1..ac5f895ac1 100644
--- a/integration-tests/load/functions/gateway.go
+++ b/integration-tests/load/functions/gateway.go
@@ -14,10 +14,11 @@ import (
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/go-resty/resty/v2"
"github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
+
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions"
"github.com/smartcontractkit/chainlink/v2/core/services/s4"
- "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
)
type RPCResponse struct {
@@ -115,7 +116,7 @@ func UploadS4Secrets(rc *resty.Client, s4Cfg *S4SecretsCfg) (uint8, uint64, erro
log.Debug().Interface("Result", result).Msg("S4 secrets_set response result")
for _, nodeResponse := range result.Result.Body.Payload.NodeResponses {
if !nodeResponse.Body.Payload.Success {
- return 0, 0, fmt.Errorf("node response was not succesful")
+ return 0, 0, fmt.Errorf("node response was not successful")
}
}
return uint8(envelope.SlotID), envelope.Version, nil
diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go
index fd13922d0a..3dafb458a5 100644
--- a/integration-tests/load/functions/gateway_gun.go
+++ b/integration-tests/load/functions/gateway_gun.go
@@ -3,14 +3,15 @@ package loadfunctions
import (
"crypto/ecdsa"
"fmt"
- "github.com/go-resty/resty/v2"
- "github.com/rs/zerolog/log"
- "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
- "github.com/smartcontractkit/wasp"
"math/rand"
"os"
"strconv"
"time"
+
+ "github.com/go-resty/resty/v2"
+ "github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
+ "github.com/smartcontractkit/wasp"
)
/* SingleFunctionCallGun is a gun that constantly requests randomness for one feed */
diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go
index 0a8b4cef46..c4b4bdb78c 100644
--- a/integration-tests/load/functions/onchain_monitoring.go
+++ b/integration-tests/load/functions/onchain_monitoring.go
@@ -1,10 +1,11 @@
package loadfunctions
import (
- "github.com/rs/zerolog/log"
- "github.com/smartcontractkit/wasp"
"testing"
"time"
+
+ "github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/wasp"
)
/* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */
diff --git a/integration-tests/load/functions/request_gun.go b/integration-tests/load/functions/request_gun.go
index d9987eaa75..bd4cf5f35a 100644
--- a/integration-tests/load/functions/request_gun.go
+++ b/integration-tests/load/functions/request_gun.go
@@ -13,16 +13,15 @@ const (
)
type SingleFunctionCallGun struct {
- ft *FunctionsTest
- mode TestMode
- times uint32
- source string
- slotID uint8
- slotVersion uint64
- encryptedSecrets []byte
- args []string
- subscriptionId uint64
- jobId [32]byte
+ ft *FunctionsTest
+ mode TestMode
+ times uint32
+ source string
+ slotID uint8
+ slotVersion uint64
+ args []string
+ subscriptionId uint64
+ jobId [32]byte
}
func NewSingleFunctionCallGun(
diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go
index 81bc660b35..c0be47ca83 100644
--- a/integration-tests/load/functions/setup.go
+++ b/integration-tests/load/functions/setup.go
@@ -12,9 +12,10 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/go-resty/resty/v2"
"github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/integration-tests/load/log_poller/log_poller_test.go b/integration-tests/load/log_poller/log_poller_test.go
index ec67815832..04366848f0 100644
--- a/integration-tests/load/log_poller/log_poller_test.go
+++ b/integration-tests/load/log_poller/log_poller_test.go
@@ -5,8 +5,9 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
- lp_helpers "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
"github.com/stretchr/testify/require"
+
+ lp_helpers "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
)
func TestLoadTestLogPoller(t *testing.T) {
diff --git a/integration-tests/load/vrfv2/cmd/dashboard.go b/integration-tests/load/vrfv2/cmd/dashboard.go
index 3035da0422..0fb7be2b78 100644
--- a/integration-tests/load/vrfv2/cmd/dashboard.go
+++ b/integration-tests/load/vrfv2/cmd/dashboard.go
@@ -1,6 +1,8 @@
package main
import (
+ "os"
+
"github.com/K-Phoen/grabana/dashboard"
"github.com/K-Phoen/grabana/logs"
"github.com/K-Phoen/grabana/row"
@@ -8,7 +10,6 @@ import (
"github.com/K-Phoen/grabana/timeseries"
"github.com/K-Phoen/grabana/timeseries/axis"
"github.com/smartcontractkit/wasp"
- "os"
)
func main() {
diff --git a/integration-tests/load/vrfv2/config.go b/integration-tests/load/vrfv2/config.go
index 0c62cc351b..0a595f753c 100644
--- a/integration-tests/load/vrfv2/config.go
+++ b/integration-tests/load/vrfv2/config.go
@@ -7,6 +7,7 @@ import (
"github.com/pelletier/go-toml/v2"
"github.com/rs/zerolog/log"
+
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go
index d6a8977738..8100baaa7f 100644
--- a/integration-tests/load/vrfv2/gun.go
+++ b/integration-tests/load/vrfv2/gun.go
@@ -1,9 +1,10 @@
package loadvrfv2
import (
+ "github.com/smartcontractkit/wasp"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants"
- "github.com/smartcontractkit/wasp"
)
/* SingleHashGun is a gun that constantly requests randomness for one feed */
@@ -21,7 +22,7 @@ func SingleFeedGun(contracts *vrfv2_actions.VRFV2Contracts, keyHash [32]byte) *S
}
// Call implements example gun call, assertions on response bodies should be done here
-func (m *SingleHashGun) Call(l *wasp.Generator) *wasp.CallResult {
+func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.CallResult {
err := m.contracts.LoadTestConsumer.RequestRandomness(
m.keyHash,
vrfConst.SubID,
diff --git a/integration-tests/load/vrfv2/onchain_monitoring.go b/integration-tests/load/vrfv2/onchain_monitoring.go
index b4503d27fa..879c7089e1 100644
--- a/integration-tests/load/vrfv2/onchain_monitoring.go
+++ b/integration-tests/load/vrfv2/onchain_monitoring.go
@@ -1,12 +1,14 @@
package loadvrfv2
import (
- "context"
- "github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
- "github.com/smartcontractkit/wasp"
"testing"
"time"
+
+ "github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/wasp"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
/* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */
@@ -34,7 +36,7 @@ func MonitorLoadStats(t *testing.T, vrfv2Contracts *vrfv2_actions.VRFV2Contracts
}
for {
time.Sleep(1 * time.Second)
- metrics, err := vrfv2Contracts.LoadTestConsumer.GetLoadTestMetrics(context.Background())
+ metrics, err := vrfv2Contracts.LoadTestConsumer.GetLoadTestMetrics(utils.TestContext(t))
if err != nil {
log.Error().Err(err).Msg(ErrMetrics)
}
diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go
index a9fb80a72a..44325965bd 100644
--- a/integration-tests/load/vrfv2/vrfv2_test.go
+++ b/integration-tests/load/vrfv2/vrfv2_test.go
@@ -3,9 +3,10 @@ package loadvrfv2
import (
"testing"
- "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
"github.com/smartcontractkit/wasp"
"github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
)
func TestVRFV2Load(t *testing.T) {
diff --git a/integration-tests/load/vrfv2/vu.go b/integration-tests/load/vrfv2/vu.go
index 4658388d40..7eb02ae330 100644
--- a/integration-tests/load/vrfv2/vu.go
+++ b/integration-tests/load/vrfv2/vu.go
@@ -4,11 +4,12 @@ import (
"fmt"
"time"
+ "github.com/smartcontractkit/wasp"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants"
"github.com/smartcontractkit/chainlink/integration-tests/client"
- "github.com/smartcontractkit/wasp"
)
/* JobVolumeVU is a "virtual user" that creates a VRFv2 job and constantly requesting new randomness only for this job instance */
diff --git a/integration-tests/load/vrfv2plus/cmd/dashboard.go b/integration-tests/load/vrfv2plus/cmd/dashboard.go
index 9a0ba682a1..049ee9ff2e 100644
--- a/integration-tests/load/vrfv2plus/cmd/dashboard.go
+++ b/integration-tests/load/vrfv2plus/cmd/dashboard.go
@@ -1,6 +1,8 @@
package main
import (
+ "os"
+
"github.com/K-Phoen/grabana/dashboard"
"github.com/K-Phoen/grabana/logs"
"github.com/K-Phoen/grabana/row"
@@ -8,7 +10,6 @@ import (
"github.com/K-Phoen/grabana/timeseries"
"github.com/K-Phoen/grabana/timeseries/axis"
"github.com/smartcontractkit/wasp"
- "os"
)
func main() {
diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go
index cba3fdcde5..96dbf99c6b 100644
--- a/integration-tests/load/vrfv2plus/config.go
+++ b/integration-tests/load/vrfv2plus/config.go
@@ -7,6 +7,7 @@ import (
"github.com/pelletier/go-toml/v2"
"github.com/rs/zerolog/log"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
@@ -100,6 +101,9 @@ func ReadConfig() (*PerformanceConfig, error) {
}
} else {
d, err = base64.StdEncoding.DecodeString(rawConfig)
+ if err != nil {
+ return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err)
+ }
}
err = toml.Unmarshal(d, &cfg)
if err != nil {
diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go
index 21be1c74ca..8ab278b73e 100644
--- a/integration-tests/load/vrfv2plus/gun.go
+++ b/integration-tests/load/vrfv2plus/gun.go
@@ -1,12 +1,14 @@
package loadvrfv2plus
import (
+ "math/big"
+ "math/rand"
+
"github.com/rs/zerolog"
+ "github.com/smartcontractkit/wasp"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
- "github.com/smartcontractkit/wasp"
- "math/big"
- "math/rand"
)
/* SingleHashGun is a gun that constantly requests randomness for one feed */
@@ -36,7 +38,7 @@ func NewSingleHashGun(
}
// Call implements example gun call, assertions on response bodies should be done here
-func (m *SingleHashGun) Call(l *wasp.Generator) *wasp.CallResult {
+func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.CallResult {
//todo - should work with multiple consumers and consumers having different keyhashes and wallets
//randomly increase/decrease randomness request count per TX
diff --git a/integration-tests/load/vrfv2plus/onchain_monitoring.go b/integration-tests/load/vrfv2plus/onchain_monitoring.go
index c56d835234..c911546af0 100644
--- a/integration-tests/load/vrfv2plus/onchain_monitoring.go
+++ b/integration-tests/load/vrfv2plus/onchain_monitoring.go
@@ -2,11 +2,13 @@ package loadvrfv2plus
import (
"context"
- "github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink/integration-tests/contracts"
- "github.com/smartcontractkit/wasp"
"testing"
"time"
+
+ "github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/wasp"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
)
/* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */
diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
index 4d3de014bc..e7734fee0d 100644
--- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go
+++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
@@ -1,20 +1,22 @@
package loadvrfv2plus
import (
- "context"
- "github.com/ethereum/go-ethereum/common"
- "github.com/kelseyhightower/envconfig"
- "github.com/rs/zerolog/log"
- "github.com/smartcontractkit/chainlink-testing-framework/logging"
- "github.com/smartcontractkit/chainlink/integration-tests/testreporters"
- "github.com/smartcontractkit/wasp"
- "github.com/stretchr/testify/require"
"math/big"
"os"
"sync"
"testing"
"time"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/kelseyhightower/envconfig"
+ "github.com/rs/zerolog/log"
+ "github.com/smartcontractkit/wasp"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink/integration-tests/testreporters"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
@@ -97,7 +99,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
Str("Returning funds from SubID", subID.String()).
Str("Returning funds to", eoaWalletAddress).
Msg("Canceling subscription and returning funds to subscription owner")
- pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(context.Background(), subID)
+ pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(utils.TestContext(t), subID)
if err != nil {
l.Error().Err(err).Msg("Error checking if pending requests exist")
}
@@ -228,7 +230,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test")
for _, subID := range subIDs {
- subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err, "error getting subscription information for subscription %s", subID.String())
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
}
diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go
index bf97f43d05..c851f36ec6 100644
--- a/integration-tests/migration/upgrade_version_test.go
+++ b/integration-tests/migration/upgrade_version_test.go
@@ -1,13 +1,12 @@
package migration
import (
+ "os"
"testing"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/stretchr/testify/require"
- "os"
-
+ "github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
)
diff --git a/integration-tests/performance/cron_test.go b/integration-tests/performance/cron_test.go
index e700a66e1f..7e90d29221 100644
--- a/integration-tests/performance/cron_test.go
+++ b/integration-tests/performance/cron_test.go
@@ -20,7 +20,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
@@ -44,7 +43,7 @@ func CleanupPerformanceTest(
if chainClient != nil {
chainClient.GasStats().PrintStats()
}
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, &testReporter, zapcore.PanicLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, &testReporter, zapcore.PanicLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
}
diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go
index d229f9fb3e..1a3f1d2a01 100644
--- a/integration-tests/performance/directrequest_test.go
+++ b/integration-tests/performance/directrequest_test.go
@@ -1,7 +1,6 @@
package performance
import (
- "context"
"fmt"
"math/big"
"strings"
@@ -25,6 +24,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
"github.com/google/uuid"
)
@@ -108,7 +108,7 @@ func TestDirectRequestPerformance(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
gom.Eventually(func(g gomega.Gomega) {
- d, err := consumer.Data(context.Background())
+ d, err := consumer.Data(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail")
g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil")
l.Debug().Int64("Data", d.Int64()).Msg("Found on chain")
diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go
index be536450a7..18b13ab907 100644
--- a/integration-tests/performance/flux_test.go
+++ b/integration-tests/performance/flux_test.go
@@ -1,7 +1,6 @@
package performance
import (
- "context"
"fmt"
"math/big"
"strings"
@@ -26,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestFluxPerformance(t *testing.T) {
@@ -83,7 +83,7 @@ func TestFluxPerformance(t *testing.T) {
require.NoError(t, err, "Setting oracle options in the Flux Aggregator contract shouldn't fail")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- oracles, err := fluxInstance.GetOracles(context.Background())
+ oracles, err := fluxInstance.GetOracles(utils.TestContext(t))
require.NoError(t, err, "Getting oracle details from the Flux aggregator contract shouldn't fail")
l.Info().Str("Oracles", strings.Join(oracles, ",")).Msg("Oracles set")
@@ -120,7 +120,7 @@ func TestFluxPerformance(t *testing.T) {
chainClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound)
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err := fluxInstance.GetContractData(context.Background())
+ data, err := fluxInstance.GetContractData(utils.TestContext(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
l.Info().Interface("Data", data).Msg("Round data")
require.Equal(t, int64(1e5), data.LatestRoundData.Answer.Int64(),
@@ -140,7 +140,7 @@ func TestFluxPerformance(t *testing.T) {
require.NoError(t, err, "Setting value path in mock server shouldn't fail")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err = fluxInstance.GetContractData(context.Background())
+ data, err = fluxInstance.GetContractData(utils.TestContext(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
require.Equal(t, int64(1e10), data.LatestRoundData.Answer.Int64(),
"Expected latest round answer to be %d, but found %d", int64(1e10), data.LatestRoundData.Answer.Int64())
@@ -153,7 +153,7 @@ func TestFluxPerformance(t *testing.T) {
l.Info().Interface("data", data).Msg("Round data")
for _, oracleAddr := range nodeAddresses {
- payment, _ := fluxInstance.WithdrawablePayment(context.Background(), oracleAddr)
+ payment, _ := fluxInstance.WithdrawablePayment(utils.TestContext(t), oracleAddr)
require.Equal(t, int64(2), payment.Int64(),
"Expected flux aggregator contract's withdrawable payment to be %d, but found %d", int64(2), payment.Int64())
}
diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go
index cd9818f99d..8e273a96f6 100644
--- a/integration-tests/performance/keeper_test.go
+++ b/integration-tests/performance/keeper_test.go
@@ -2,7 +2,6 @@ package performance
//revive:disable:dot-imports
import (
- "context"
"fmt"
"math/big"
"strings"
@@ -26,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var keeperDefaultRegistryConfig = contracts.KeeperRegistrySettings{
@@ -74,7 +74,7 @@ func TestKeeperPerformance(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
"Expected consumer counter to be greater than 10, but got %d", counter.Int64())
@@ -84,7 +84,7 @@ func TestKeeperPerformance(t *testing.T) {
// Cancel all the registered upkeeps via the registry
for i := 0; i < len(upkeepIDs); i++ {
- err := registry.CancelUpkeep(upkeepIDs[i])
+ err = registry.CancelUpkeep(upkeepIDs[i])
require.NoError(t, err, "Could not cancel upkeep at index %d", i)
}
@@ -95,7 +95,7 @@ func TestKeeperPerformance(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterCancellation[i], err = consumers[i].Counter(context.Background())
+ countersAfterCancellation[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Index", i).Int64("Upkeeps Performed", countersAfterCancellation[i].Int64()).Msg("Cancelled Upkeep")
}
@@ -103,7 +103,7 @@ func TestKeeperPerformance(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant because the upkeep was cancelled, so it shouldn't increase anymore
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterCancellation[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go
index e81cc91cf7..47879cebb8 100644
--- a/integration-tests/performance/ocr_test.go
+++ b/integration-tests/performance/ocr_test.go
@@ -1,7 +1,6 @@
package performance
import (
- "context"
"fmt"
"math/big"
"strings"
@@ -25,6 +24,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCRBasic(t *testing.T) {
@@ -53,7 +53,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(.05))
require.NoError(t, err, "Error funding Chainlink nodes")
- ocrInstances, err := actions.DeployOCRContracts(1, linkTokenContract, contractDeployer, bootstrapNode, workerNodes, chainClient)
+ ocrInstances, err := actions.DeployOCRContracts(1, linkTokenContract, contractDeployer, workerNodes, chainClient)
require.NoError(t, err)
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
@@ -64,7 +64,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(1, ocrInstances, chainClient, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -73,7 +73,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(2, ocrInstances, chainClient, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
diff --git a/integration-tests/performance/vrf_test.go b/integration-tests/performance/vrf_test.go
index eeaceffaaf..7a38a45495 100644
--- a/integration-tests/performance/vrf_test.go
+++ b/integration-tests/performance/vrf_test.go
@@ -1,7 +1,6 @@
package performance
import (
- "context"
"fmt"
"math/big"
"strings"
@@ -23,6 +22,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFBasic(t *testing.T) {
@@ -97,7 +97,7 @@ func TestVRFBasic(t *testing.T) {
encodedProvingKeys := make([][2]*big.Int, 0)
encodedProvingKeys = append(encodedProvingKeys, provingKey)
- requestHash, err := coordinator.HashOfKey(context.Background(), encodedProvingKeys[0])
+ requestHash, err := coordinator.HashOfKey(utils.TestContext(t), encodedProvingKeys[0])
require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail")
err = consumer.RequestRandomness(requestHash, big.NewInt(1))
require.NoError(t, err, "Requesting randomness shouldn't fail")
@@ -108,7 +108,7 @@ func TestVRFBasic(t *testing.T) {
jobRuns, err := chainlinkNodes[0].MustReadRunsByJob(job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
- out, err := consumer.RandomnessOutput(context.Background())
+ out, err := consumer.RandomnessOutput(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
// Checks that the job has actually run
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go
index 697ae28ce3..58cd147201 100644
--- a/integration-tests/reorg/automation_reorg_test.go
+++ b/integration-tests/reorg/automation_reorg_test.go
@@ -2,7 +2,6 @@ package reorg
//revive:disable:dot-imports
import (
- "context"
"fmt"
"math/big"
"testing"
@@ -19,12 +18,12 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -133,6 +132,8 @@ func TestAutomationReorg(t *testing.T) {
}
for name, registryVersion := range registryVersions {
+ name := name
+ registryVersion := registryVersion
t.Run(name, func(t *testing.T) {
t.Parallel()
network := networks.MustGetSelectedNetworksFromEnv()[0]
@@ -167,7 +168,7 @@ func TestAutomationReorg(t *testing.T) {
// Register cleanup for any test
t.Cleanup(func() {
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
@@ -209,7 +210,7 @@ func TestAutomationReorg(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(it_utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
@@ -240,7 +241,7 @@ func TestAutomationReorg(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(it_utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 10
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
@@ -250,13 +251,14 @@ func TestAutomationReorg(t *testing.T) {
}, "5m", "1s").Should(gomega.Succeed())
l.Info().Msg("Upkeep performed during unstable chain, waiting for reorg to finish")
- rc.WaitDepthReached()
+ err = rc.WaitDepthReached()
+ require.NoError(t, err)
l.Info().Msg("Reorg finished, chain should be stable now. Expecting upkeeps to keep getting performed")
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 20
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(it_utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 20
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
diff --git a/integration-tests/reorg/log_poller_maybe_reorg_test.go b/integration-tests/reorg/log_poller_maybe_reorg_test.go
index 0176fdbbdd..d319e39aa2 100644
--- a/integration-tests/reorg/log_poller_maybe_reorg_test.go
+++ b/integration-tests/reorg/log_poller_maybe_reorg_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
+
logpoller "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
)
diff --git a/integration-tests/reorg/reorg_test.go b/integration-tests/reorg/reorg_test.go
index f92becfa50..d5fefdbc56 100644
--- a/integration-tests/reorg/reorg_test.go
+++ b/integration-tests/reorg/reorg_test.go
@@ -1,7 +1,6 @@
package reorg
import (
- "context"
"fmt"
"math/big"
"os"
@@ -22,15 +21,16 @@ import (
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/onsi/gomega"
"github.com/rs/zerolog/log"
+
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
const (
@@ -85,7 +85,7 @@ func CleanupReorgTest(
if chainClient != nil {
chainClient.GasStats().PrintStats()
}
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
}
@@ -221,7 +221,7 @@ func TestDirectRequestReorg(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
gom.Eventually(func(g gomega.Gomega) {
- d, err := consumer.Data(context.Background())
+ d, err := consumer.Data(it_utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail")
g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil")
log.Debug().Int64("Data", d.Int64()).Msg("Found on chain")
diff --git a/integration-tests/runner_helpers.go b/integration-tests/runner_helpers.go
index 43268a703a..def2ebdc1d 100644
--- a/integration-tests/runner_helpers.go
+++ b/integration-tests/runner_helpers.go
@@ -122,7 +122,7 @@ func collectBranchesAndTags(results chan []string, errChan chan error) {
go func() {
stdOut, stdErr, err := gh.Exec("api", fmt.Sprintf("repos/%s/branches", chainlinkRepo), "-q", ".[][\"name\"]", "--paginate")
if err != nil {
- errChan <- fmt.Errorf("%v: %s", err, stdErr.String())
+ errChan <- fmt.Errorf("%w: %s", err, stdErr.String())
}
branches := strings.Split(stdOut.String(), "\n")
cleanBranches := []string{}
@@ -139,7 +139,7 @@ func collectBranchesAndTags(results chan []string, errChan chan error) {
go func() {
stdOut, stdErr, err := gh.Exec("api", fmt.Sprintf("repos/%s/tags", chainlinkRepo), "-q", ".[][\"name\"]", "--paginate")
if err != nil {
- errChan <- fmt.Errorf("%v: %s", err, stdErr.String())
+ errChan <- fmt.Errorf("%w: %s", err, stdErr.String())
}
tags := strings.Split(stdOut.String(), "\n")
cleanTags := []string{}
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 4f969c5d68..1a093a8815 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"encoding/json"
"fmt"
"math/big"
@@ -32,7 +31,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var utilsABI = cltypes.MustGetABI(automation_utils_2_1.AutomationUtilsABI)
@@ -110,7 +109,6 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
upgradeImage string
upgradeVersion string
err error
- testName = "basic-upkeep"
)
if nodeUpgrade {
upgradeImage = os.Getenv("UPGRADE_IMAGE")
@@ -118,7 +116,6 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
if len(upgradeImage) == 0 || len(upgradeVersion) == 0 {
t.Fatal("UPGRADE_IMAGE and UPGRADE_VERSION must be set to upgrade nodes")
}
- testName = "node-upgrade"
}
// Use the name to determine if this is a log trigger or mercury
@@ -128,7 +125,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
isMercury := isMercuryV02 || isMercuryV03
chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupAutomationTestDocker(
- t, testName, registryVersion, defaultOCRRegistryConfig, nodeUpgrade, isMercuryV02, isMercuryV03,
+ t, registryVersion, defaultOCRRegistryConfig, isMercuryV02, isMercuryV03,
)
consumers, upkeepIDs := actions.DeployConsumers(
@@ -172,7 +169,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Number of upkeeps performed")
@@ -187,13 +184,14 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
expect := 5
// Upgrade the nodes one at a time and check that the upkeeps are still being performed
for i := 0; i < 5; i++ {
- actions.UpgradeChainlinkNodeVersionsLocal(upgradeImage, upgradeVersion, testEnv.ClCluster.Nodes[i])
+ err = actions.UpgradeChainlinkNodeVersionsLocal(upgradeImage, upgradeVersion, testEnv.ClCluster.Nodes[i])
+ require.NoError(t, err, "Error when upgrading node %d", i)
time.Sleep(time.Second * 10)
expect = expect + 5
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are increasing by 5 in each step within 5 minutes
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)),
@@ -216,7 +214,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterCancellation[i], err = consumers[i].Counter(context.Background())
+ countersAfterCancellation[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeep Count", countersAfterCancellation[i].Int64()).Int("Upkeep Index", i).Msg("Cancelled upkeep")
}
@@ -225,7 +223,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant (At most increase by 1 to account for stale performs) because the upkeep was cancelled
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterCancellation[i].Int64()+1),
"Expected consumer counter to remain less than or equal to %d, but got %d",
@@ -241,7 +239,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
l := logging.GetTestLogger(t)
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "set-trigger-config", ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, false, false, false,
+ t, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, false, false,
)
consumers, upkeepIDs := actions.DeployConsumers(
@@ -271,7 +269,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Number of upkeeps performed")
@@ -328,7 +326,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
time.Sleep(10 * time.Second)
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterSetNoMatch[i], err = consumers[i].Counter(context.Background())
+ countersAfterSetNoMatch[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeep Count", countersAfterSetNoMatch[i].Int64()).Int("Upkeep Index", i).Msg("Upkeep")
}
@@ -338,7 +336,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant (At most increase by 2 to account for stale performs) because the upkeep trigger config is not met
bufferCount := int64(2)
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterSetNoMatch[i].Int64()+bufferCount),
"Expected consumer counter to remain less than or equal to %d, but got %d",
@@ -374,7 +372,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterSetMatch[i], err = consumers[i].Counter(context.Background())
+ countersAfterSetMatch[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeep Count", countersAfterSetMatch[i].Int64()).Int("Upkeep Index", i).Msg("Upkeep")
}
@@ -393,7 +391,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := int64(5)
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Number of upkeeps performed")
@@ -416,7 +414,7 @@ func TestAutomationAddFunds(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "add-funds", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(1), automationDefaultUpkeepGasLimit, false, false)
@@ -424,7 +422,7 @@ func TestAutomationAddFunds(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
// Since the upkeep is currently underfunded, check that it doesn't get executed
gom.Consistently(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(context.Background())
+ counter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
"Expected consumer counter to remain zero, but got %d", counter.Int64())
@@ -444,7 +442,7 @@ func TestAutomationAddFunds(t *testing.T) {
// Now the new upkeep should be performing because we added enough funds
gom.Eventually(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(context.Background())
+ counter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -467,7 +465,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
t.Parallel()
l := logging.GetTestLogger(t)
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "pause-unpause", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false)
@@ -476,7 +474,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)),
"Expected consumer counter to be greater than 5, but got %d", counter.Int64())
@@ -496,7 +494,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterPause[i], err = consumers[i].Counter(context.Background())
+ countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Upkeep Index", i).Int64("Upkeeps Performed", countersAfterPause[i].Int64()).Msg("Paused Upkeep")
}
@@ -505,7 +503,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// In most cases counters should remain constant, but there might be a straggling perform tx which
// gets committed later and increases counter by 1
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterPause[i].Int64()+1),
"Expected consumer counter not have increased more than %d, but got %d",
@@ -525,7 +523,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5 + numbers of performing before pause
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", countersAfterPause[i].Int64()+1),
"Expected consumer counter to be greater than %d, but got %d", countersAfterPause[i].Int64()+1, counter.Int64())
@@ -550,7 +548,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
t.Parallel()
l := logging.GetTestLogger(t)
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "register-upkeep", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false)
@@ -561,7 +559,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
// store the value of their initial counters in order to compare later on that the value increased.
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -581,7 +579,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
// Test that the newly registered upkeep is also performing.
gom.Eventually(func(g gomega.Gomega) {
- counter, err := newUpkeep.Counter(context.Background())
+ counter, err := newUpkeep.Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling newly deployed upkeep's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -590,7 +588,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(context.Background())
+ currentCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().
@@ -621,7 +619,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "pause-registry", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false)
@@ -630,7 +628,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
// Observe that the upkeeps which are initially registered are performing
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d")
@@ -646,7 +644,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
// Store how many times each upkeep performed once the registry was successfully paused
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterPause[i], err = consumers[i].Counter(context.Background())
+ countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
}
@@ -654,7 +652,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
// because they are no longer getting serviced
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterPause[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -679,7 +677,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
t.Parallel()
l := logging.GetTestLogger(t)
chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "keeper-nodes-down", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false)
@@ -691,7 +689,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// Watch upkeeps being performed and store their counters in order to compare them later in the test
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -710,7 +708,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// Assert that upkeeps are still performed and their counters have increased
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(context.Background())
+ currentCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", initialCounters[i].Int64()),
"Expected counter to have increased from initial value of %s, but got %s",
@@ -731,7 +729,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// See how many times each upkeep was executed
var countersAfterNoMoreNodes = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterNoMoreNodes[i], err = consumers[i].Counter(context.Background())
+ countersAfterNoMoreNodes[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Upkeep Index", i).Int64("Performed", countersAfterNoMoreNodes[i].Int64()).Msg("Upkeeps Performed")
}
@@ -740,7 +738,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// all the nodes were taken down
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterNoMoreNodes[i].Int64()+1),
"Expected consumer counter to not have increased more than %d, but got %d",
@@ -764,7 +762,7 @@ func TestAutomationPerformSimulation(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "perform-simulation", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumersPerformance, _ := actions.DeployPerformanceConsumers(
@@ -789,7 +787,7 @@ func TestAutomationPerformSimulation(t *testing.T) {
// Initially performGas is set high, so performUpkeep reverts and no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
// Consumer count should remain at 0
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.Equal(int64(0)),
"Expected consumer counter to remain constant at %d, but got %d", 0, cnt.Int64(),
@@ -797,14 +795,14 @@ func TestAutomationPerformSimulation(t *testing.T) {
}, "2m", "1s").Should(gomega.Succeed()) // ~1m for setup, 1m assertion
// Set performGas on consumer to be low, so that performUpkeep starts becoming successful
- err := consumerPerformance.SetPerformGasToBurn(context.Background(), big.NewInt(100000))
+ err := consumerPerformance.SetPerformGasToBurn(utils.TestContext(t), big.NewInt(100000))
require.NoError(t, err, "Perform gas should be set successfully on consumer")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for set perform gas tx")
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -828,7 +826,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
t.Parallel()
l := logging.GetTestLogger(t)
chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "gas-limit", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
consumersPerformance, upkeepIDs := actions.DeployPerformanceConsumers(
@@ -854,7 +852,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
// Initially performGas is set higher than defaultUpkeepGasLimit, so no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.Equal(int64(0)),
@@ -870,7 +868,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -878,19 +876,19 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
}, "2m", "1s").Should(gomega.Succeed()) // ~1m to perform once, 1m buffer
// Now increase the checkGasBurn on consumer, upkeep should stop performing
- err = consumerPerformance.SetCheckGasToBurn(context.Background(), big.NewInt(3000000))
+ err = consumerPerformance.SetCheckGasToBurn(utils.TestContext(t), big.NewInt(3000000))
require.NoError(t, err, "Check gas burn should be set successfully on consumer")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for SetCheckGasToBurn tx")
// Get existing performed count
- existingCnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ existingCnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
require.NoError(t, err, "Calling consumer's counter shouldn't fail")
l.Info().Int64("Upkeep counter", existingCnt.Int64()).Msg("Upkeep counter when check gas increased")
// In most cases count should remain constant, but it might increase by upto 1 due to pending perform
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.BeNumerically("<=", existingCnt.Int64()+1),
@@ -898,7 +896,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
)
}, "1m", "1s").Should(gomega.Succeed())
- existingCnt, err = consumerPerformance.GetUpkeepCount(context.Background())
+ existingCnt, err = consumerPerformance.GetUpkeepCount(utils.TestContext(t))
require.NoError(t, err, "Calling consumer's counter shouldn't fail")
existingCntInt := existingCnt.Int64()
l.Info().Int64("Upkeep counter", existingCntInt).Msg("Upkeep counter when consistently block finished")
@@ -918,7 +916,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
// Upkeep should start performing again, and it should get regularly performed
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", existingCntInt),
"Expected consumer counter to be greater than %d, but got %d", existingCntInt, cnt.Int64(),
@@ -942,7 +940,7 @@ func TestUpdateCheckData(t *testing.T) {
t.Parallel()
l := logging.GetTestLogger(t)
chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker(
- t, "update-check-data", registryVersion, defaultOCRRegistryConfig, false, false, false,
+ t, registryVersion, defaultOCRRegistryConfig, false, false,
)
performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerConsumers(
@@ -962,7 +960,7 @@ func TestUpdateCheckData(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
// expect the counter to remain 0 because perform data does not match
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(context.Background())
+ counter, err := performDataChecker[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker"+
" for upkeep at index "+strconv.Itoa(i))
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
@@ -981,7 +979,7 @@ func TestUpdateCheckData(t *testing.T) {
// retrieve new check data for all upkeeps
for i := 0; i < len(upkeepIDs); i++ {
- upkeep, err := registry.GetUpkeepInfo(context.Background(), upkeepIDs[i])
+ upkeep, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepIDs[i])
require.NoError(t, err, "Failed to get upkeep info at index %d", i)
require.Equal(t, []byte(automationExpectedData), upkeep.CheckData, "Upkeep data not as expected")
}
@@ -989,7 +987,7 @@ func TestUpdateCheckData(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(context.Background())
+ counter, err := performDataChecker[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker counter"+
" for upkeep at index "+strconv.Itoa(i))
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -1007,10 +1005,8 @@ type TestConfig struct {
func setupAutomationTestDocker(
t *testing.T,
- testName string,
registryVersion ethereum.KeeperRegistryVersion,
registryConfig contracts.KeeperRegistrySettings,
- statefulDb bool,
isMercuryV02 bool,
isMercuryV03 bool,
) (
@@ -1032,11 +1028,11 @@ func setupAutomationTestDocker(
// build the node config
clNodeConfig := node.NewConfig(node.NewBaseConfig())
syncInterval := models.MustMakeDuration(5 * time.Minute)
- clNodeConfig.Feature.LogPoller = it_utils.Ptr[bool](true)
- clNodeConfig.OCR2.Enabled = it_utils.Ptr[bool](true)
- clNodeConfig.Keeper.TurnLookBack = it_utils.Ptr[int64](int64(0))
+ clNodeConfig.Feature.LogPoller = utils.Ptr[bool](true)
+ clNodeConfig.OCR2.Enabled = utils.Ptr[bool](true)
+ clNodeConfig.Keeper.TurnLookBack = utils.Ptr[int64](int64(0))
clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval
- clNodeConfig.Keeper.Registry.PerformGasOverhead = it_utils.Ptr[uint32](uint32(150000))
+ clNodeConfig.Keeper.Registry.PerformGasOverhead = utils.Ptr[uint32](uint32(150000))
clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"}
clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"}
@@ -1086,11 +1082,13 @@ func setupAutomationTestDocker(
if isMercuryV02 {
output := `{"chainlinkBlob":"0x0001c38d71fed6c320b90e84b6f559459814d068e2a1700adc931ca9717d4fe70000000000000000000000000000000000000000000000000000000001a80b52b4bf1233f9cb71144a253a1791b202113c4ab4a92fa1b176d684b4959666ff8200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004254432d5553442d415242495452554d2d544553544e4554000000000000000000000000000000000000000000000000000000000000000000000000645570be000000000000000000000000000000000000000000000000000002af2b818dc5000000000000000000000000000000000000000000000000000002af2426faf3000000000000000000000000000000000000000000000000000002af32dc209700000000000000000000000000000000000000000000000000000000012130f8df0a9745bb6ad5e2df605e158ba8ad8a33ef8a0acf9851f0f01668a3a3f2b68600000000000000000000000000000000000000000000000000000000012130f60000000000000000000000000000000000000000000000000000000000000002c4a7958dce105089cf5edb68dad7dcfe8618d7784eb397f97d5a5fade78c11a58275aebda478968e545f7e3657aba9dcbe8d44605e4c6fde3e24edd5e22c94270000000000000000000000000000000000000000000000000000000000000002459c12d33986018a8959566d145225f0c4a4e61a9a3f50361ccff397899314f0018162cf10cd89897635a0bb62a822355bd199d09f4abe76e4d05261bb44733d"}`
- env.MockAdapter.SetStringValuePath("/client", []string{http.MethodGet, http.MethodPost}, map[string]string{"Content-Type": "application/json"}, output)
+ err = env.MockAdapter.SetStringValuePath("/client", []string{http.MethodGet, http.MethodPost}, map[string]string{"Content-Type": "application/json"}, output)
+ require.NoError(t, err)
}
if isMercuryV03 {
output := `{"reports":[{"feedID":"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000","validFromTimestamp":0,"observationsTimestamp":0,"fullReport":"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"}]}`
- env.MockAdapter.SetStringValuePath("/api/v1/reports/bulk", []string{http.MethodGet, http.MethodPost}, map[string]string{"Content-Type": "application/json"}, output)
+ err = env.MockAdapter.SetStringValuePath("/api/v1/reports/bulk", []string{http.MethodGet, http.MethodPost}, map[string]string{"Content-Type": "application/json"}, output)
+ require.NoError(t, err)
}
} else {
env, err = test_env.NewCLTestEnvBuilder().
diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go
index 8c2b3638bf..2997ff1c74 100644
--- a/integration-tests/smoke/flux_test.go
+++ b/integration-tests/smoke/flux_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"net/http"
@@ -19,6 +18,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestFluxBasic(t *testing.T) {
@@ -74,7 +74,7 @@ func TestFluxBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- oracles, err := fluxInstance.GetOracles(context.Background())
+ oracles, err := fluxInstance.GetOracles(utils.TestContext(t))
require.NoError(t, err, "Getting oracle details from the Flux aggregator contract shouldn't fail")
l.Info().Str("Oracles", strings.Join(oracles, ",")).Msg("Oracles set")
@@ -108,7 +108,7 @@ func TestFluxBasic(t *testing.T) {
env.EVMClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound)
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err := fluxInstance.GetContractData(context.Background())
+ data, err := fluxInstance.GetContractData(utils.TestContext(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
require.Equal(t, int64(1e5), data.LatestRoundData.Answer.Int64(),
"Expected latest round answer to be %d, but found %d", int64(1e5), data.LatestRoundData.Answer.Int64())
@@ -127,7 +127,7 @@ func TestFluxBasic(t *testing.T) {
require.NoError(t, err, "Setting value path in mock server shouldn't fail")
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err = fluxInstance.GetContractData(context.Background())
+ data, err = fluxInstance.GetContractData(utils.TestContext(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
require.Equal(t, int64(1e10), data.LatestRoundData.Answer.Int64(),
"Expected latest round answer to be %d, but found %d", int64(1e10), data.LatestRoundData.Answer.Int64())
@@ -140,7 +140,7 @@ func TestFluxBasic(t *testing.T) {
l.Info().Interface("data", data).Msg("Round data")
for _, oracleAddr := range nodeAddresses {
- payment, _ := fluxInstance.WithdrawablePayment(context.Background(), oracleAddr)
+ payment, _ := fluxInstance.WithdrawablePayment(utils.TestContext(t), oracleAddr)
require.Equal(t, int64(2), payment.Int64(),
"Expected flux aggregator contract's withdrawable payment to be %d, but found %d", int64(2), payment.Int64())
}
diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go
index 727b83a601..7203e03178 100644
--- a/integration-tests/smoke/forwarder_ocr_test.go
+++ b/integration-tests/smoke/forwarder_ocr_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"math/big"
"testing"
@@ -12,6 +11,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestForwarderOCRBasic(t *testing.T) {
@@ -72,7 +72,7 @@ func TestForwarderOCRBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
- answer, err := ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -83,7 +83,7 @@ func TestForwarderOCRBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
- answer, err = ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go
index baa5a781f6..be87eb5629 100644
--- a/integration-tests/smoke/forwarders_ocr2_test.go
+++ b/integration-tests/smoke/forwarders_ocr2_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"net/http"
@@ -17,6 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestForwarderOCR2Basic(t *testing.T) {
@@ -92,7 +92,7 @@ func TestForwarderOCR2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(1, ocrInstances, env.EVMClient, time.Minute*10, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Getting latest answer from OCRv2 contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCRw contract to be 5 but got %d", answer.Int64())
@@ -103,7 +103,7 @@ func TestForwarderOCR2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(int64(i), ocrInstances, env.EVMClient, time.Minute*10, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Error getting latest OCRv2 answer")
require.Equal(t, int64(ocrRoundVal), answer.Int64(), fmt.Sprintf("Expected latest answer from OCRv2 contract to be %d but got %d", ocrRoundVal, answer.Int64()))
}
diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go
index d42944fd55..b28ab1ff10 100644
--- a/integration-tests/smoke/keeper_test.go
+++ b/integration-tests/smoke/keeper_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"strconv"
@@ -23,6 +22,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
const (
@@ -109,7 +109,7 @@ func TestKeeperBasicSmoke(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
"Expected consumer counter to be greater than 10, but got %d", counter.Int64())
@@ -131,7 +131,7 @@ func TestKeeperBasicSmoke(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterCancellation[i], err = consumers[i].Counter(context.Background())
+ countersAfterCancellation[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Index", i).Int64("Upkeeps Performed", countersAfterCancellation[i].Int64()).Msg("Cancelled Upkeep")
}
@@ -139,7 +139,7 @@ func TestKeeperBasicSmoke(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant because the upkeep was cancelled, so it shouldn't increase anymore
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterCancellation[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -187,11 +187,11 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
// Wait for upkeep to be performed twice by different keepers (buddies)
gom.Eventually(func(g gomega.Gomega) error {
- counter, err := consumers[0].Counter(context.Background())
+ counter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed")
- upkeepInfo, err := registry.GetUpkeepInfo(context.Background(), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -205,7 +205,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
}, "1m", "1s").Should(gomega.Succeed())
gom.Eventually(func(g gomega.Gomega) error {
- upkeepInfo, err := registry.GetUpkeepInfo(context.Background(), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -219,7 +219,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
// Expect no new keepers to perform for a while
gom.Consistently(func(g gomega.Gomega) {
- upkeepInfo, err := registry.GetUpkeepInfo(context.Background(), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -235,11 +235,11 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
// Expect a new keeper to perform
gom.Eventually(func(g gomega.Gomega) error {
- counter, err := consumers[0].Counter(context.Background())
+ counter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Num upkeeps performed")
- upkeepInfo, err := registry.GetUpkeepInfo(context.Background(), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -296,7 +296,7 @@ func TestKeeperSimulation(t *testing.T) {
// Initially performGas is set high, so performUpkeep reverts and no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
// Consumer count should remain at 0
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.Equal(int64(0)),
@@ -304,20 +304,20 @@ func TestKeeperSimulation(t *testing.T) {
)
// Not even reverted upkeeps should be performed. Last keeper for the upkeep should be 0 address
- upkeepInfo, err := registry.GetUpkeepInfo(context.Background(), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
g.Expect(upkeepInfo.LastKeeper).Should(gomega.Equal(actions.ZeroAddress.String()), "Last keeper should be zero address")
}, "1m", "1s").Should(gomega.Succeed())
// Set performGas on consumer to be low, so that performUpkeep starts becoming successful
- err = consumerPerformance.SetPerformGasToBurn(context.Background(), big.NewInt(100000))
+ err = consumerPerformance.SetPerformGasToBurn(utils.TestContext(t), big.NewInt(100000))
require.NoError(t, err, "Error setting PerformGasToBurn")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting to set PerformGasToBurn")
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) error {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -368,7 +368,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// Initially performGas is set higher than defaultUpkeepGasLimit, so no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.Equal(int64(0)),
@@ -384,7 +384,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) error {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -393,13 +393,13 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
}, "1m", "1s").Should(gomega.Succeed())
// Now increase the checkGasBurn on consumer, upkeep should stop performing
- err = consumerPerformance.SetCheckGasToBurn(context.Background(), big.NewInt(3000000))
+ err = consumerPerformance.SetCheckGasToBurn(utils.TestContext(t), big.NewInt(3000000))
require.NoError(t, err, "Error setting CheckGasToBurn")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for SetCheckGasToBurn tx")
// Get existing performed count
- existingCnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ existingCnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
require.NoError(t, err, "Error calling consumer's counter")
l.Info().Int64("Upkeep counter", existingCnt.Int64()).Msg("Check Gas Increased")
@@ -407,7 +407,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// gets committed later. Since every keeper node cannot have more than 1 straggling tx, it
// is sufficient to check that the upkeep count does not increase by more than 6.
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.BeNumerically("<=", existingCnt.Int64()+numUpkeepsAllowedForStragglingTxs),
@@ -415,7 +415,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
)
}, "3m", "1s").Should(gomega.Succeed())
- existingCnt, err = consumerPerformance.GetUpkeepCount(context.Background())
+ existingCnt, err = consumerPerformance.GetUpkeepCount(utils.TestContext(t))
require.NoError(t, err, "Error calling consumer's counter")
existingCntInt := existingCnt.Int64()
l.Info().Int64("Upkeep counter", existingCntInt).Msg("Upkeep counter when consistently block finished")
@@ -430,7 +430,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// Upkeep should start performing again, and it should get regularly performed
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(context.Background())
+ cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", existingCntInt),
"Expected consumer counter to be greater than %d, but got %d", existingCntInt, cnt.Int64(),
@@ -478,7 +478,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) {
// store the value of their initial counters in order to compare later on that the value increased.
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+
" for upkeep at index "+strconv.Itoa(i))
@@ -500,7 +500,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) {
// Test that the newly registered upkeep is also performing.
gom.Eventually(func(g gomega.Gomega) error {
- counter, err := newUpkeep.Counter(context.Background())
+ counter, err := newUpkeep.Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling newly deployed upkeep's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -510,7 +510,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(context.Background())
+ currentCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().
@@ -563,7 +563,7 @@ func TestKeeperAddFunds(t *testing.T) {
// Since the upkeep is currently underfunded, check that it doesn't get executed
gom.Consistently(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(context.Background())
+ counter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
"Expected consumer counter to remain zero, but got %d", counter.Int64())
@@ -583,7 +583,7 @@ func TestKeeperAddFunds(t *testing.T) {
// Now the new upkeep should be performing because we added enough funds
gom.Eventually(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(context.Background())
+ counter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -628,7 +628,7 @@ func TestKeeperRemove(t *testing.T) {
// Make sure the upkeeps are running before we remove a keeper
gom.Eventually(func(g gomega.Gomega) error {
for upkeepID := 0; upkeepID < len(upkeepIDs); upkeepID++ {
- counter, err := consumers[upkeepID].Counter(context.Background())
+ counter, err := consumers[upkeepID].Counter(utils.TestContext(t))
initialCounters[upkeepID] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+
" for upkeep with ID "+strconv.Itoa(upkeepID))
@@ -637,7 +637,7 @@ func TestKeeperRemove(t *testing.T) {
return nil
}, "1m", "1s").Should(gomega.Succeed())
- keepers, err := registry.GetKeeperList(context.Background())
+ keepers, err := registry.GetKeeperList(utils.TestContext(t))
require.NoError(t, err, "Error getting list of Keepers")
// Remove the first keeper from the list
@@ -660,7 +660,7 @@ func TestKeeperRemove(t *testing.T) {
// The upkeeps should still perform and their counters should have increased compared to the first check
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Cmp(initialCounters[i]) == 1, "Expected consumer counter to be greater "+
"than initial counter which was %s, but got %s", initialCounters[i], counter)
@@ -705,7 +705,7 @@ func TestKeeperPauseRegistry(t *testing.T) {
// Observe that the upkeeps which are initially registered are performing
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d")
@@ -722,7 +722,7 @@ func TestKeeperPauseRegistry(t *testing.T) {
// Store how many times each upkeep performed once the registry was successfully paused
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterPause[i], err = consumers[i].Counter(context.Background())
+ countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Error retrieving consumer at index %d", i)
}
@@ -730,7 +730,7 @@ func TestKeeperPauseRegistry(t *testing.T) {
// because they are no longer getting serviced
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Error retrieving consumer contract at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterPause[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -791,7 +791,7 @@ func TestKeeperMigrateRegistry(t *testing.T) {
// Check that the first upkeep from the first registry is performing (before being migrated)
gom.Eventually(func(g gomega.Gomega) error {
- counterBeforeMigration, err := consumers[0].Counter(context.Background())
+ counterBeforeMigration, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counterBeforeMigration.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %s", counterBeforeMigration)
@@ -810,12 +810,12 @@ func TestKeeperMigrateRegistry(t *testing.T) {
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting to pause first registry")
- counterAfterMigration, err := consumers[0].Counter(context.Background())
+ counterAfterMigration, err := consumers[0].Counter(utils.TestContext(t))
require.NoError(t, err, "Error calling consumer's counter")
// Check that once we migrated the upkeep, the counter has increased
gom.Eventually(func(g gomega.Gomega) error {
- currentCounter, err := consumers[0].Counter(context.Background())
+ currentCounter, err := consumers[0].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", counterAfterMigration.Int64()),
"Expected counter to have increased, but stayed constant at %s", counterAfterMigration)
@@ -860,7 +860,7 @@ func TestKeeperNodeDown(t *testing.T) {
// Watch upkeeps being performed and store their counters in order to compare them later in the test
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -882,7 +882,7 @@ func TestKeeperNodeDown(t *testing.T) {
// Assert that upkeeps are still performed and their counters have increased
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(context.Background())
+ currentCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", initialCounters[i].Int64()),
"Expected counter to have increased from initial value of %s, but got %s",
@@ -908,7 +908,7 @@ func TestKeeperNodeDown(t *testing.T) {
// See how many times each upkeep was executed
var countersAfterNoMoreNodes = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterNoMoreNodes[i], err = consumers[i].Counter(context.Background())
+ countersAfterNoMoreNodes[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Error retrieving consumer counter %d", i)
l.Info().
Int("Index", i).
@@ -921,7 +921,7 @@ func TestKeeperNodeDown(t *testing.T) {
// so a +6 on the upper limit side should be sufficient.
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=",
countersAfterNoMoreNodes[i].Int64()+numUpkeepsAllowedForStragglingTxs,
@@ -964,7 +964,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)),
"Expected consumer counter to be greater than 5, but got %d", counter.Int64())
@@ -985,7 +985,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterPause[i], err = consumers[i].Counter(context.Background())
+ countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Error retrieving upkeep count at index %d", i)
l.Info().
Int("Index", i).
@@ -998,7 +998,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
// In most cases counters should remain constant, but there might be a straggling perform tx which
// gets committed later. Since every keeper node cannot have more than 1 straggling tx, it
// is sufficient to check that the upkeep count does not increase by more than 6.
- latestCounter, err := consumers[i].Counter(context.Background())
+ latestCounter, err := consumers[i].Counter(utils.TestContext(t))
require.NoError(t, err, "Error retrieving counter at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterPause[i].Int64()+numUpkeepsAllowedForStragglingTxs),
"Expected consumer counter not have increased more than %d, but got %d",
@@ -1018,7 +1018,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5 + numbers of performing before pause
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(context.Background())
+ counter, err := consumers[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+
" for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)+countersAfterPause[i].Int64()),
@@ -1055,7 +1055,7 @@ func TestKeeperUpdateCheckData(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
// expect the counter to remain 0 because perform data does not match
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(context.Background())
+ counter, err := performDataChecker[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
"Expected perform data checker counter to be 0, but got %d", counter.Int64())
@@ -1073,7 +1073,7 @@ func TestKeeperUpdateCheckData(t *testing.T) {
// retrieve new check data for all upkeeps
for i := 0; i < len(upkeepIDs); i++ {
- upkeep, err := registry.GetUpkeepInfo(context.Background(), upkeepIDs[i])
+ upkeep, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepIDs[i])
require.NoError(t, err, "Error getting upkeep info from index %d", i)
require.Equal(t, []byte(keeperExpectedData), upkeep.CheckData, "Check data not as expected")
}
@@ -1081,7 +1081,7 @@ func TestKeeperUpdateCheckData(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(context.Background())
+ counter, err := performDataChecker[i].Counter(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)),
"Expected perform data checker counter to be greater than 5, but got %d", counter.Int64())
diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go
index 36ee2164c4..03a287ee6b 100644
--- a/integration-tests/smoke/log_poller_test.go
+++ b/integration-tests/smoke/log_poller_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
+
logpoller "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller"
)
diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go
index a6dcdcd139..5950e9febb 100644
--- a/integration-tests/smoke/ocr2_test.go
+++ b/integration-tests/smoke/ocr2_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"net/http"
@@ -16,6 +15,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// Tests a basic OCRv2 median feed
@@ -73,7 +73,7 @@ func TestOCRv2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l)
require.NoError(t, err, "Error starting new OCR2 round")
- roundData, err := aggregatorContracts[0].GetRound(context.Background(), big.NewInt(1))
+ roundData, err := aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(1))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 5 but got %d",
@@ -85,7 +85,7 @@ func TestOCRv2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l)
require.NoError(t, err)
- roundData, err = aggregatorContracts[0].GetRound(context.Background(), big.NewInt(2))
+ roundData, err = aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(2))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 10 but got %d",
diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go
index 912c121d07..57bd5412b1 100644
--- a/integration-tests/smoke/ocr2vrf_test.go
+++ b/integration-tests/smoke/ocr2vrf_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"strings"
@@ -16,7 +15,6 @@ import (
eth "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions"
@@ -24,6 +22,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCR2VRFRedeemModel(t *testing.T) {
@@ -45,7 +44,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) {
require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail")
t.Cleanup(func() {
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
@@ -81,7 +80,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(context.Background(), requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err)
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
@@ -107,7 +106,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) {
require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail")
t.Cleanup(func() {
- err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient)
+ err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
@@ -142,7 +141,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(context.Background(), requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err, "Error getting Randomness result from Consumer Contract")
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness Fulfillment retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness Fulfillment retrieved from Consumer contract give an answer other than 0")
diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go
index 8952f00d76..45205565e2 100644
--- a/integration-tests/smoke/ocr_test.go
+++ b/integration-tests/smoke/ocr_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"math/big"
"testing"
@@ -11,6 +10,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCRBasic(t *testing.T) {
@@ -46,7 +46,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -55,7 +55,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(context.Background())
+ answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go
index f29cb4bc89..20389da378 100644
--- a/integration-tests/smoke/runlog_test.go
+++ b/integration-tests/smoke/runlog_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"net/http"
@@ -16,6 +15,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestRunLogBasic(t *testing.T) {
@@ -87,7 +87,7 @@ func TestRunLogBasic(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
gom.Eventually(func(g gomega.Gomega) {
- d, err := consumer.Data(context.Background())
+ d, err := consumer.Data(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail")
g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil")
l.Debug().Int64("Data", d.Int64()).Msg("Found on chain")
diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go
index 444d1ce20e..61d2c5cdd7 100644
--- a/integration-tests/smoke/vrf_test.go
+++ b/integration-tests/smoke/vrf_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"testing"
@@ -17,6 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv1"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFBasic(t *testing.T) {
@@ -81,7 +81,7 @@ func TestVRFBasic(t *testing.T) {
encodedProvingKeys := make([][2]*big.Int, 0)
encodedProvingKeys = append(encodedProvingKeys, provingKey)
- requestHash, err := contracts.Coordinator.HashOfKey(context.Background(), encodedProvingKeys[0])
+ requestHash, err := contracts.Coordinator.HashOfKey(utils.TestContext(t), encodedProvingKeys[0])
require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail")
err = contracts.Consumer.RequestRandomness(requestHash, big.NewInt(1))
require.NoError(t, err, "Requesting randomness shouldn't fail")
@@ -92,7 +92,7 @@ func TestVRFBasic(t *testing.T) {
jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
- out, err := contracts.Consumer.RandomnessOutput(context.Background())
+ out, err := contracts.Consumer.RandomnessOutput(utils.TestContext(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
// Checks that the job has actually run
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go
index c960bb6c69..714ed752a3 100644
--- a/integration-tests/smoke/vrfv2_test.go
+++ b/integration-tests/smoke/vrfv2_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"math/big"
"testing"
"time"
@@ -16,6 +15,7 @@ import (
vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFv2Basic(t *testing.T) {
@@ -97,11 +97,11 @@ func TestVRFv2Basic(t *testing.T) {
jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfV2jobs[0].Job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically("==", 1))
- lastRequestID, err = vrfv2Contracts.LoadTestConsumer.GetLastRequestId(context.Background())
+ lastRequestID, err = vrfv2Contracts.LoadTestConsumer.GetLastRequestId(utils.TestContext(t))
l.Debug().Interface("Last Request ID", lastRequestID).Msg("Last Request ID Received")
g.Expect(err).ShouldNot(gomega.HaveOccurred())
- status, err := vrfv2Contracts.LoadTestConsumer.GetRequestStatus(context.Background(), lastRequestID)
+ status, err := vrfv2Contracts.LoadTestConsumer.GetRequestStatus(utils.TestContext(t), lastRequestID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(status.Fulfilled).Should(gomega.BeTrue())
l.Debug().Interface("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go
index 3510a1505a..cfeca0a66a 100644
--- a/integration-tests/smoke/vrfv2plus_test.go
+++ b/integration-tests/smoke/vrfv2plus_test.go
@@ -1,7 +1,6 @@
package smoke
import (
- "context"
"fmt"
"math/big"
"testing"
@@ -55,7 +54,7 @@ func TestVRFv2Plus(t *testing.T) {
subID := subIDs[0]
- subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
@@ -83,7 +82,7 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err, "error getting subscription information")
subBalanceAfterRequest := subscription.Balance
require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest)
@@ -92,7 +91,7 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error reading job runs")
require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data))
- status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
+ status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, status.Fulfilled)
l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
@@ -125,7 +124,7 @@ func TestVRFv2Plus(t *testing.T) {
)
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceWei := new(big.Int).Sub(subNativeTokenBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err)
subBalanceAfterRequest := subscription.NativeBalance
require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest)
@@ -134,7 +133,7 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error reading job runs")
require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data))
- status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
+ status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, status.Fulfilled)
l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
@@ -162,10 +161,10 @@ func TestVRFv2Plus(t *testing.T) {
testConfig := vrfv2PlusConfig
var isNativeBilling = false
- wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(context.Background(), wrapperContracts.LoadTestConsumers[0].Address())
+ wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(utils.TestContext(t), wrapperContracts.LoadTestConsumers[0].Address())
require.NoError(t, err, "error getting wrapper consumer balance")
- wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceBeforeRequest := wrapperSubscription.Balance
@@ -182,18 +181,18 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceAfterRequest := wrapperSubscription.Balance
require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest)
- consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
+ consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, consumerStatus.Fulfilled)
expectedWrapperConsumerJuelsBalance := new(big.Int).Sub(wrapperConsumerJuelsBalanceBeforeRequest, consumerStatus.Paid)
- wrapperConsumerJuelsBalanceAfterRequest, err := linkToken.BalanceOf(context.Background(), wrapperContracts.LoadTestConsumers[0].Address())
+ wrapperConsumerJuelsBalanceAfterRequest, err := linkToken.BalanceOf(utils.TestContext(t), wrapperContracts.LoadTestConsumers[0].Address())
require.NoError(t, err, "error getting wrapper consumer balance")
require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest)
@@ -211,10 +210,10 @@ func TestVRFv2Plus(t *testing.T) {
testConfig := vrfv2PlusConfig
var isNativeBilling = true
- wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
+ wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
require.NoError(t, err, "error getting wrapper consumer balance")
- wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceBeforeRequest := wrapperSubscription.NativeBalance
@@ -231,18 +230,18 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceWei := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), wrapperSubID)
+ wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceAfterRequest := wrapperSubscription.NativeBalance
require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest)
- consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(context.Background(), randomWordsFulfilledEvent.RequestId)
+ consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, consumerStatus.Fulfilled)
expectedWrapperConsumerWeiBalance := new(big.Int).Sub(wrapperConsumerBalanceBeforeRequestWei, consumerStatus.Paid)
- wrapperConsumerBalanceAfterRequestWei, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
+ wrapperConsumerBalanceAfterRequestWei, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
require.NoError(t, err, "error getting wrapper consumer balance")
require.Equal(t, expectedWrapperConsumerWeiBalance, wrapperConsumerBalanceAfterRequestWei)
@@ -273,13 +272,13 @@ func TestVRFv2Plus(t *testing.T) {
testWalletAddress, err := actions.GenerateWallet()
require.NoError(t, err)
- testWalletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), testWalletAddress)
+ testWalletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), testWalletAddress)
require.NoError(t, err)
- testWalletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(context.Background(), testWalletAddress.String())
+ testWalletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), testWalletAddress.String())
require.NoError(t, err)
- subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
subBalanceLink := subscriptionForCancelling.Balance
@@ -318,14 +317,14 @@ func TestVRFv2Plus(t *testing.T) {
require.Equal(t, subBalanceNative, subscriptionCanceledEvent.AmountNative, "SubscriptionCanceled event native amount is not equal to sub amount while canceling subscription")
require.Equal(t, subBalanceLink, subscriptionCanceledEvent.AmountLink, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription")
- testWalletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), testWalletAddress)
+ testWalletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), testWalletAddress)
require.NoError(t, err)
- testWalletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(context.Background(), testWalletAddress.String())
+ testWalletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), testWalletAddress.String())
require.NoError(t, err)
//Verify that sub was deleted from Coordinator
- _, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
subFundsReturnedNativeActual := new(big.Int).Sub(testWalletBalanceNativeAfterSubCancelling, testWalletBalanceNativeBeforeSubCancelling)
@@ -367,17 +366,17 @@ func TestVRFv2Plus(t *testing.T) {
subIDForCancelling := subIDsForCancelling[0]
- subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetails(l, subscriptionForCancelling, subIDForCancelling, vrfv2PlusContracts.Coordinator)
- activeSubscriptionIdsBeforeSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ activeSubscriptionIdsBeforeSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err)
require.True(t, utils.BigIntSliceContains(activeSubscriptionIdsBeforeSubCancellation, subIDForCancelling))
- pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(context.Background(), subIDForCancelling)
+ pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(utils.TestContext(t), subIDForCancelling)
require.NoError(t, err)
require.False(t, pendingRequestsExist, "Pending requests should not exist")
@@ -409,17 +408,17 @@ func TestVRFv2Plus(t *testing.T) {
require.Error(t, err, "error should occur for waiting for fulfilment due to low sub balance")
- pendingRequestsExist, err = vrfv2PlusContracts.Coordinator.PendingRequestsExist(context.Background(), subIDForCancelling)
+ pendingRequestsExist, err = vrfv2PlusContracts.Coordinator.PendingRequestsExist(utils.TestContext(t), subIDForCancelling)
require.NoError(t, err)
require.True(t, pendingRequestsExist, "Pending requests should exist after unfulfilled rand requests due to low sub balance")
- walletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ walletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- walletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ walletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
require.NoError(t, err)
- subscriptionForCancelling, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ subscriptionForCancelling, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
subBalanceLink := subscriptionForCancelling.Balance
@@ -458,14 +457,14 @@ func TestVRFv2Plus(t *testing.T) {
require.Equal(t, subBalanceNative, subscriptionCanceledEvent.AmountNative, "SubscriptionCanceled event native amount is not equal to sub amount while canceling subscription")
require.Equal(t, subBalanceLink, subscriptionCanceledEvent.AmountLink, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription")
- walletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ walletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- walletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ walletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
require.NoError(t, err)
//Verify that sub was deleted from Coordinator
- _, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subIDForCancelling)
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
fmt.Println("err", err)
require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
@@ -494,7 +493,7 @@ func TestVRFv2Plus(t *testing.T) {
//require.Equal(t, subFundsReturnedNativeExpected, subFundsReturnedNativeActual, "Returned funds are not equal to sub balance that was cancelled")
require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled")
- activeSubscriptionIdsAfterSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ activeSubscriptionIdsAfterSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err, "error getting active subscription ids")
require.False(
@@ -543,10 +542,10 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err)
amountToWithdrawLink := fulfilledEventLink.Payment
- defaultWalletBalanceNativeBeforeOracleWithdraw, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ defaultWalletBalanceNativeBeforeOracleWithdraw, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
require.NoError(t, err)
l.Info().
@@ -575,10 +574,10 @@ func TestVRFv2Plus(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete)
- defaultWalletBalanceNativeAfterOracleWithdraw, err := env.EVMClient.BalanceAt(context.Background(), common.HexToAddress(defaultWalletAddress))
+ defaultWalletBalanceNativeAfterOracleWithdraw, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(context.Background(), defaultWalletAddress)
+ defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
require.NoError(t, err)
//not possible to verify exact amount of Native/LINK returned as defaultWallet is used in other tests in parallel which might affect the balance
@@ -618,17 +617,17 @@ func TestVRFv2PlusMigration(t *testing.T) {
subID := subIDs[0]
- subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
- activeSubIdsOldCoordinatorBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ activeSubIdsOldCoordinatorBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err, "error occurred getting active sub ids")
require.Len(t, activeSubIdsOldCoordinatorBeforeMigration, 1, "Active Sub Ids length is not equal to 1")
require.Equal(t, subID, activeSubIdsOldCoordinatorBeforeMigration[0])
- oldSubscriptionBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ oldSubscriptionBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err, "error getting subscription information")
//Migration Process
@@ -699,14 +698,14 @@ func TestVRFv2PlusMigration(t *testing.T) {
migratedCoordinatorLinkTotalBalanceAfterMigration, migratedCoordinatorEthTotalBalanceAfterMigration, err := vrfv2plus.GetUpgradedCoordinatorTotalBalance(newCoordinator)
require.NoError(t, err)
- migratedSubscription, err := newCoordinator.GetSubscription(context.Background(), subID)
+ migratedSubscription, err := newCoordinator.GetSubscription(utils.TestContext(t), subID)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetailsAfterMigration(l, newCoordinator, subID, migratedSubscription)
//Verify that Coordinators were updated in Consumers
for _, consumer := range vrfv2PlusContracts.LoadTestConsumers {
- coordinatorAddressInConsumerAfterMigration, err := consumer.GetCoordinator(context.Background())
+ coordinatorAddressInConsumerAfterMigration, err := consumer.GetCoordinator(utils.TestContext(t))
require.NoError(t, err, "error getting Coordinator from Consumer contract")
require.Equal(t, newCoordinator.Address(), coordinatorAddressInConsumerAfterMigration.String())
l.Debug().
@@ -722,13 +721,13 @@ func TestVRFv2PlusMigration(t *testing.T) {
require.Equal(t, oldSubscriptionBeforeMigration.Consumers, migratedSubscription.Consumers)
//Verify that old sub was deleted from old Coordinator
- _, err = vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID)
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
- _, err = vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ _, err = vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
require.Error(t, err, "error not occurred getting active sub ids. Should occur since it should revert when sub id array is empty")
- activeSubIdsMigratedCoordinator, err := newCoordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0))
+ activeSubIdsMigratedCoordinator, err := newCoordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err, "error occurred getting active sub ids")
require.Len(t, activeSubIdsMigratedCoordinator, 1, "Active Sub Ids length is not equal to 1 for Migrated Coordinator after migration")
require.Equal(t, subID, activeSubIdsMigratedCoordinator[0])
diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go
index c800eb37be..e9f2eaad7c 100644
--- a/integration-tests/testreporters/keeper_benchmark.go
+++ b/integration-tests/testreporters/keeper_benchmark.go
@@ -183,7 +183,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error {
}
for contractIndex, report := range k.Reports {
- avg, median, ninetyPct, ninetyNinePct, max := intListStats(report.AllCheckDelays)
+ avg, median, ninetyPct, ninetyNinePct, max = intListStats(report.AllCheckDelays)
err = keeperReportWriter.Write([]string{
fmt.Sprint(contractIndex),
report.RegistryAddress,
@@ -305,6 +305,8 @@ func (k *KeeperBenchmarkTestReporter) SendSlackNotification(t *testing.T, slackC
}
// intListStats helper calculates some statistics on an int list: avg, median, 90pct, 99pct, max
+//
+//nolint:revive
func intListStats(in []int64) (float64, int64, int64, int64, int64) {
length := len(in)
if length == 0 {
diff --git a/integration-tests/testreporters/ocr.go b/integration-tests/testreporters/ocr.go
index a04718ea22..abbb261fa7 100644
--- a/integration-tests/testreporters/ocr.go
+++ b/integration-tests/testreporters/ocr.go
@@ -67,9 +67,7 @@ func (e *OCRRoundState) Time() time.Time {
// CSV returns a CSV representation of the test state and all events
func (e *OCRRoundState) CSV() [][]string {
rows := [][]string{{e.StartTime.Format("2006-01-02 15:04:05.00 MST"), fmt.Sprintf("Expecting new Answer: %d", e.Answer)}}
- for _, anomaly := range e.anomalies {
- rows = append(rows, anomaly)
- }
+ rows = append(rows, e.anomalies...)
return rows
}
diff --git a/integration-tests/testreporters/profile.go b/integration-tests/testreporters/profile.go
index 9ac7713e94..ab9dec138e 100644
--- a/integration-tests/testreporters/profile.go
+++ b/integration-tests/testreporters/profile.go
@@ -54,7 +54,7 @@ func (c *ChainlinkProfileTestReporter) WriteReport(folderLocation string) error
}
// SendNotification hasn't been implemented for this test
-func (c *ChainlinkProfileTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client) error {
+func (c *ChainlinkProfileTestReporter) SendSlackNotification(_ *testing.T, _ *slack.Client) error {
log.Warn().Msg("No Slack notification integration for Chainlink profile tests")
return nil
}
diff --git a/integration-tests/testreporters/vrfv2plus.go b/integration-tests/testreporters/vrfv2plus.go
index 83d4678dfd..38220ca882 100644
--- a/integration-tests/testreporters/vrfv2plus.go
+++ b/integration-tests/testreporters/vrfv2plus.go
@@ -2,12 +2,13 @@ package testreporters
import (
"fmt"
- "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
"math/big"
"os"
"testing"
"time"
+ "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
+
"github.com/slack-go/slack"
"github.com/smartcontractkit/chainlink-testing-framework/testreporters"
@@ -53,7 +54,7 @@ func (o *VRFV2PlusTestReporter) SendSlackNotification(t *testing.T, slackClient
headerText = fmt.Sprintf(":x: VRF %s Test FAILED :x:", o.TestType)
}
- messageBlocks := testreporters.SlackNotifyBlocks(headerText, fmt.Sprintf("%s", os.Getenv("SELECTED_NETWORKS")), []string{
+ messageBlocks := testreporters.SlackNotifyBlocks(headerText, os.Getenv("SELECTED_NETWORKS"), []string{
fmt.Sprintf(
"Summary\n"+
"Perf Test Type: %s\n"+
diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go
index f786cca9bb..bb6c582c13 100644
--- a/integration-tests/testsetups/keeper_benchmark.go
+++ b/integration-tests/testsetups/keeper_benchmark.go
@@ -37,6 +37,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// KeeperBenchmarkTest builds a test to check that chainlink nodes are able to upkeep a specified amount of Upkeep
@@ -229,7 +230,7 @@ func (k *KeeperBenchmarkTest) Run() {
"NumberOfRegistries": len(k.keeperRegistries),
}
inputs := k.Inputs
- startingBlock, err := k.chainClient.LatestBlockNumber(context.Background())
+ startingBlock, err := k.chainClient.LatestBlockNumber(utils.TestContext(k.t))
require.NoError(k.t, err, "Error getting latest block number")
k.startingBlock = big.NewInt(0).SetUint64(startingBlock)
startTime := time.Now()
@@ -305,7 +306,7 @@ func (k *KeeperBenchmarkTest) Run() {
err = fmt.Errorf("initial error") // to ensure our for loop runs at least once
)
for err != nil { // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats.
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ ctx, cancel := context.WithTimeout(utils.TestContext(k.t), timeout)
logs, err = k.chainClient.FilterLogs(ctx, filterQuery)
cancel()
if err != nil {
@@ -407,12 +408,13 @@ func (k *KeeperBenchmarkTest) observeUpkeepEvents() {
FromBlock: k.startingBlock,
}
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ ctx, cancel := context.WithTimeout(utils.TestContext(k.t), 5*time.Second)
sub, err := k.chainClient.SubscribeFilterLogs(ctx, filterQuery, eventLogs)
cancel()
require.NoError(k.t, err, "Subscribing to upkeep performed events log shouldn't fail")
interruption := make(chan os.Signal, 1)
+ //nolint:staticcheck //ignore SA1016 we need to send the os.Kill signal
signal.Notify(interruption, os.Kill, os.Interrupt, syscall.SIGTERM)
go func() {
@@ -429,7 +431,7 @@ func (k *KeeperBenchmarkTest) observeUpkeepEvents() {
Str("Backoff", backoff.String()).
Msg("Error while subscribing to Keeper Event Logs. Resubscribing...")
- ctx, cancel := context.WithTimeout(context.Background(), backoff)
+ ctx, cancel := context.WithTimeout(utils.TestContext(k.t), backoff)
sub, err = k.chainClient.SubscribeFilterLogs(ctx, filterQuery, eventLogs)
cancel()
if err != nil {
diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go
index ee8116f3f9..3fb9dd9844 100644
--- a/integration-tests/testsetups/ocr.go
+++ b/integration-tests/testsetups/ocr.go
@@ -42,6 +42,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
const (
@@ -163,7 +164,7 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) {
}
// LoadEnvironment loads an existing test environment using the provided URLs
-func (o *OCRSoakTest) LoadEnvironment(chainlinkURLs []string, chainURL, mockServerURL string) {
+func (o *OCRSoakTest) LoadEnvironment(chainlinkURLs []string, mockServerURL string) {
var (
network = networks.MustGetSelectedNetworksFromEnv()[0]
err error
@@ -241,7 +242,6 @@ func (o *OCRSoakTest) Setup() {
o.Inputs.NumberOfContracts,
linkTokenContract,
contractDeployer,
- o.bootstrapNode,
o.workerNodes,
o.chainClient,
)
@@ -258,7 +258,7 @@ func (o *OCRSoakTest) Setup() {
// Run starts the OCR soak test
func (o *OCRSoakTest) Run() {
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
+ ctx, cancel := context.WithTimeout(utils.TestContext(o.t), time.Second*5)
latestBlockNum, err := o.chainClient.LatestBlockNumber(ctx)
cancel()
require.NoError(o.t, err, "Error getting current block number")
@@ -343,7 +343,7 @@ func (o *OCRSoakTest) SaveState() error {
if err != nil {
return err
}
- // #nosec G306 - let everyone read
+ //nolint:gosec // G306 - let everyone read
if err = os.WriteFile(saveFileLocation, data, 0644); err != nil {
return err
}
@@ -468,6 +468,7 @@ func (o *OCRSoakTest) Interrupted() bool {
func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) {
endTest := time.After(testDuration)
interruption := make(chan os.Signal, 1)
+ //nolint:staticcheck //ignore SA1016 we need to send the os.Kill signal
signal.Notify(interruption, os.Kill, os.Interrupt, syscall.SIGTERM)
lastValue := 0
newRoundTrigger := time.NewTimer(0) // Want to trigger a new round ASAP
@@ -558,7 +559,7 @@ func (o *OCRSoakTest) setFilterQuery() {
// WARNING: Should only be used for observation and logging. This is not a reliable way to collect events.
func (o *OCRSoakTest) observeOCREvents() error {
eventLogs := make(chan types.Log)
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ ctx, cancel := context.WithTimeout(utils.TestContext(o.t), 5*time.Second)
eventSub, err := o.chainClient.SubscribeFilterLogs(ctx, o.filterQuery, eventLogs)
cancel()
if err != nil {
@@ -592,7 +593,7 @@ func (o *OCRSoakTest) observeOCREvents() error {
Str("Backoff", backoff.String()).
Interface("Query", o.filterQuery).
Msg("Error while subscribed to OCR Logs. Resubscribing")
- ctx, cancel = context.WithTimeout(context.Background(), backoff)
+ ctx, cancel = context.WithTimeout(utils.TestContext(o.t), backoff)
eventSub, err = o.chainClient.SubscribeFilterLogs(ctx, o.filterQuery, eventLogs)
cancel()
if err != nil {
@@ -645,12 +646,12 @@ func (o *OCRSoakTest) collectEvents() error {
timeout := time.Second * 15
o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events")
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ ctx, cancel := context.WithTimeout(utils.TestContext(o.t), timeout)
contractEvents, err := o.chainClient.FilterLogs(ctx, o.filterQuery)
cancel()
for err != nil {
o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events")
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ ctx, cancel := context.WithTimeout(utils.TestContext(o.t), timeout)
contractEvents, err = o.chainClient.FilterLogs(ctx, o.filterQuery)
cancel()
if err != nil {
diff --git a/integration-tests/testsetups/vrfv2.go b/integration-tests/testsetups/vrfv2.go
index 194c7ff4e6..8c5fde7216 100644
--- a/integration-tests/testsetups/vrfv2.go
+++ b/integration-tests/testsetups/vrfv2.go
@@ -22,6 +22,7 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// VRFV2SoakTest defines a typical VRFV2 soak test
@@ -87,7 +88,8 @@ func (v *VRFV2SoakTest) Run(t *testing.T) {
Msg("Starting VRFV2 Soak Test")
// set the requests to only run for a certain amount of time
- testContext, testCancel := context.WithTimeout(context.Background(), v.Inputs.TestDuration)
+ ctx := utils.TestContext(t)
+ testContext, testCancel := context.WithTimeout(ctx, v.Inputs.TestDuration)
defer testCancel()
v.NumberOfRandRequests = 0
@@ -126,7 +128,7 @@ func (v *VRFV2SoakTest) Run(t *testing.T) {
//todo - need to find better way for this
time.Sleep(1 * time.Minute)
- loadTestMetrics, err := v.Inputs.ConsumerContract.GetLoadTestMetrics(nil)
+ loadTestMetrics, err := v.Inputs.ConsumerContract.GetLoadTestMetrics(ctx)
if err != nil {
l.Error().Err(err).Msg("Error Occurred when getting Load Test Metrics from Consumer contract")
}
diff --git a/integration-tests/types/envcommon/common.go b/integration-tests/types/envcommon/common.go
index 607c481f33..bdabcaf96b 100644
--- a/integration-tests/types/envcommon/common.go
+++ b/integration-tests/types/envcommon/common.go
@@ -2,7 +2,7 @@ package envcommon
import (
"encoding/json"
- "io/ioutil"
+ "io"
"os"
)
@@ -12,7 +12,7 @@ func ParseJSONFile(path string, v any) error {
return err
}
defer jsonFile.Close()
- b, _ := ioutil.ReadAll(jsonFile)
+ b, _ := io.ReadAll(jsonFile)
err = json.Unmarshal(b, v)
if err != nil {
return err
diff --git a/integration-tests/universal/log_poller/config.go b/integration-tests/universal/log_poller/config.go
index 7297e81124..78a0da46bc 100644
--- a/integration-tests/universal/log_poller/config.go
+++ b/integration-tests/universal/log_poller/config.go
@@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/pelletier/go-toml/v2"
"github.com/rs/zerolog/log"
+
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
@@ -131,33 +132,33 @@ func (c *Config) validate() error {
err := c.General.validate()
if err != nil {
- return fmt.Errorf("General config validation failed: %v", err)
+ return fmt.Errorf("General config validation failed: %w", err)
}
switch c.General.Generator {
case GeneratorType_WASP:
if c.Wasp == nil {
- return fmt.Errorf("Wasp config is nil")
+ return fmt.Errorf("wasp config is nil")
}
if c.Wasp.Load == nil {
- return fmt.Errorf("Wasp load config is nil")
+ return fmt.Errorf("wasp load config is nil")
}
err = c.Wasp.validate()
if err != nil {
- return fmt.Errorf("Wasp config validation failed: %v", err)
+ return fmt.Errorf("wasp config validation failed: %w", err)
}
case GeneratorType_Looped:
if c.LoopedConfig == nil {
- return fmt.Errorf("Looped config is nil")
+ return fmt.Errorf("looped config is nil")
}
err = c.LoopedConfig.validate()
if err != nil {
- return fmt.Errorf("Looped config validation failed: %v", err)
+ return fmt.Errorf("looped config validation failed: %w", err)
}
default:
- return fmt.Errorf("Unknown generator type: %s", c.General.Generator)
+ return fmt.Errorf("unknown generator type: %s", c.General.Generator)
}
return nil
@@ -165,15 +166,15 @@ func (c *Config) validate() error {
func (g *General) validate() error {
if g.Generator == "" {
- return fmt.Errorf("Generator is empty")
+ return fmt.Errorf("generator is empty")
}
if g.Contracts == 0 {
- return fmt.Errorf("Contracts is 0, but must be > 0")
+ return fmt.Errorf("contracts is 0, but must be > 0")
}
if g.EventsPerTx == 0 {
- return fmt.Errorf("Events_per_tx is 0, but must be > 0")
+ return fmt.Errorf("events_per_tx is 0, but must be > 0")
}
return nil
@@ -186,7 +187,7 @@ func (w *WaspConfig) validate() error {
err := w.Load.validate()
if err != nil {
- return fmt.Errorf("Load config validation failed: %v", err)
+ return fmt.Errorf("Load config validation failed: %w", err)
}
return nil
@@ -194,11 +195,11 @@ func (w *WaspConfig) validate() error {
func (l *Load) validate() error {
if l.RPS == 0 && l.LPS == 0 {
- return fmt.Errorf("Either RPS or LPS needs to be set")
+ return fmt.Errorf("either RPS or LPS needs to be set")
}
if l.RPS != 0 && l.LPS != 0 {
- return fmt.Errorf("Only one of RPS or LPS can be set")
+ return fmt.Errorf("only one of RPS or LPS can be set")
}
if l.Duration == nil {
diff --git a/integration-tests/universal/log_poller/gun.go b/integration-tests/universal/log_poller/gun.go
index 11932330a3..39286f1b53 100644
--- a/integration-tests/universal/log_poller/gun.go
+++ b/integration-tests/universal/log_poller/gun.go
@@ -7,8 +7,9 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/rs/zerolog"
- "github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/wasp"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
)
/* LogEmitterGun is a gun that constantly emits logs from a contract */
@@ -53,13 +54,13 @@ func (m *LogEmitterGun) Call(l *wasp.Generator) *wasp.CallResult {
case "Log3":
_, err = logEmitter.EmitLogStrings(getStringSlice(m.eventsPerTx))
default:
- err = fmt.Errorf("Unknown event name: %s", event.Name)
+ err = fmt.Errorf("unknown event name: %s", event.Name)
}
if err != nil {
return &wasp.CallResult{Error: err.Error(), Failed: true}
}
- localCounter += 1
+ localCounter++
}
// I don't think that will work as expected, I should atomically read the value and save it, so maybe just a mutex?
diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go
index 9f88827bb4..08ceb4a7be 100644
--- a/integration-tests/universal/log_poller/helpers.go
+++ b/integration-tests/universal/log_poller/helpers.go
@@ -3,7 +3,6 @@ package logpoller
import (
"bytes"
"context"
- "errors"
"fmt"
"math/big"
"math/rand"
@@ -22,16 +21,15 @@ import (
"github.com/scylladb/go-reflectx"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/wasp"
+
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
- ctf_blockchain "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/wasp"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
- lpEvm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
@@ -41,12 +39,13 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
+
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
+
it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
- utils2 "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -80,64 +79,65 @@ var registerSingleTopicFilter = func(registry contracts.KeeperRegistry, upkeepID
return nil
}
+// Currently Unused November 8, 2023, Might be useful in the near future so keeping it here for now
// this is not really possible, log trigger doesn't support multiple topics, even if log poller does
-var registerMultipleTopicsFilter = func(registry contracts.KeeperRegistry, upkeepID *big.Int, emitterAddress common.Address, topics []abi.Event) error {
- if len(topics) > 4 {
- return errors.New("Cannot register more than 4 topics")
- }
-
- var getTopic = func(topics []abi.Event, i int) common.Hash {
- if i > len(topics)-1 {
- return bytes0
- }
-
- return topics[i].ID
- }
-
- var getFilterSelector = func(topics []abi.Event) (uint8, error) {
- switch len(topics) {
- case 0:
- return 0, errors.New("Cannot register filter with 0 topics")
- case 1:
- return 0, nil
- case 2:
- return 1, nil
- case 3:
- return 3, nil
- case 4:
- return 7, nil
- default:
- return 0, errors.New("Cannot register filter with more than 4 topics")
- }
- }
-
- filterSelector, err := getFilterSelector(topics)
- if err != nil {
- return err
- }
-
- logTriggerConfigStruct := automation_utils_2_1.LogTriggerConfig{
- ContractAddress: emitterAddress,
- FilterSelector: filterSelector,
- Topic0: getTopic(topics, 0),
- Topic1: getTopic(topics, 1),
- Topic2: getTopic(topics, 2),
- Topic3: getTopic(topics, 3),
- }
- encodedLogTriggerConfig, err := automationUtilsABI.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct)
- if err != nil {
- return err
- }
-
- err = registry.SetUpkeepTriggerConfig(upkeepID, encodedLogTriggerConfig)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func NewOrm(logger core_logger.SugaredLogger, chainID *big.Int, postgresDb *ctf_test_env.PostgresDb) (*lpEvm.DbORM, *sqlx.DB, error) {
+// var registerMultipleTopicsFilter = func(registry contracts.KeeperRegistry, upkeepID *big.Int, emitterAddress common.Address, topics []abi.Event) error {
+// if len(topics) > 4 {
+// return errors.New("Cannot register more than 4 topics")
+// }
+
+// var getTopic = func(topics []abi.Event, i int) common.Hash {
+// if i > len(topics)-1 {
+// return bytes0
+// }
+
+// return topics[i].ID
+// }
+
+// var getFilterSelector = func(topics []abi.Event) (uint8, error) {
+// switch len(topics) {
+// case 0:
+// return 0, errors.New("Cannot register filter with 0 topics")
+// case 1:
+// return 0, nil
+// case 2:
+// return 1, nil
+// case 3:
+// return 3, nil
+// case 4:
+// return 7, nil
+// default:
+// return 0, errors.New("Cannot register filter with more than 4 topics")
+// }
+// }
+
+// filterSelector, err := getFilterSelector(topics)
+// if err != nil {
+// return err
+// }
+
+// logTriggerConfigStruct := automation_utils_2_1.LogTriggerConfig{
+// ContractAddress: emitterAddress,
+// FilterSelector: filterSelector,
+// Topic0: getTopic(topics, 0),
+// Topic1: getTopic(topics, 1),
+// Topic2: getTopic(topics, 2),
+// Topic3: getTopic(topics, 3),
+// }
+// encodedLogTriggerConfig, err := automationUtilsABI.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct)
+// if err != nil {
+// return err
+// }
+
+// err = registry.SetUpkeepTriggerConfig(upkeepID, encodedLogTriggerConfig)
+// if err != nil {
+// return err
+// }
+
+// return nil
+// }
+
+func NewOrm(logger core_logger.SugaredLogger, chainID *big.Int, postgresDb *ctf_test_env.PostgresDb) (*logpoller.DbORM, *sqlx.DB, error) {
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", "127.0.0.1", postgresDb.ExternalPort, postgresDb.User, postgresDb.Password, postgresDb.DbName)
db, err := sqlx.Open("postgres", dsn)
if err != nil {
@@ -145,7 +145,7 @@ func NewOrm(logger core_logger.SugaredLogger, chainID *big.Int, postgresDb *ctf_
}
db.MapperFunc(reflectx.CamelToSnakeASCII)
- return lpEvm.NewORM(chainID, db, logger, pg.NewQConfig(false)), db, nil
+ return logpoller.NewORM(chainID, db, logger, pg.NewQConfig(false)), db, nil
}
type ExpectedFilter struct {
@@ -189,7 +189,7 @@ var nodeHasExpectedFilters = func(expectedFilters []ExpectedFilter, logger core_
}
if !filterFound {
- return false, fmt.Errorf("No filter found for emitter %s and topic %s", expectedFilter.emitterAddress.String(), expectedFilter.topic.Hex())
+ return false, fmt.Errorf("no filter found for emitter %s and topic %s", expectedFilter.emitterAddress.String(), expectedFilter.topic.Hex())
}
}
@@ -203,9 +203,10 @@ var randomWait = func(minMilliseconds, maxMilliseconds int) {
}
type LogEmitterChannel struct {
- logsEmitted int
- err error
- currentIndex int
+ logsEmitted int
+ err error
+ // unused
+ // currentIndex int
}
func getIntSlice(length int) []int {
@@ -247,7 +248,7 @@ var emitEvents = func(ctx context.Context, l zerolog.Logger, logEmitter *contrac
case "Log3":
_, err = (*logEmitter).EmitLogStrings(getStringSlice(cfg.General.EventsPerTx))
default:
- err = fmt.Errorf("Unknown event name: %s", event.Name)
+ err = fmt.Errorf("unknown event name: %s", event.Name)
}
if err != nil {
@@ -276,29 +277,7 @@ var emitEvents = func(ctx context.Context, l zerolog.Logger, logEmitter *contrac
}
}
-var waitForEndBlockInLogPoller = func(endBlock int64, chainID *big.Int, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) {
- for i := 1; i < len(nodes.Nodes); i++ {
- clNode := nodes.Nodes[i]
- orm, db, err := NewOrm(coreLogger, chainID, clNode.PostgresDb)
- if err != nil {
- return false, err
- }
-
- defer db.Close()
- block, err := orm.SelectBlockByNumber(endBlock)
- if err != nil {
- return false, err
- }
-
- if block == nil {
- return false, nil
- }
- }
-
- return true, nil
-}
-
-var chainHasFinalisedEndBlock = func(l zerolog.Logger, evmClient ctf_blockchain.EVMClient, endBlock int64) (bool, error) {
+var chainHasFinalisedEndBlock = func(l zerolog.Logger, evmClient blockchain.EVMClient, endBlock int64) (bool, error) {
effectiveEndBlock := endBlock + 1
lastFinalisedBlockHeader, err := evmClient.GetLatestFinalizedBlockHeader(context.Background())
if err != nil {
@@ -512,7 +491,7 @@ func (m *MissingLogs) IsEmpty() bool {
return true
}
-var getMissingLogs = func(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient ctf_blockchain.EVMClient, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *Config) (MissingLogs, error) {
+var getMissingLogs = func(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient blockchain.EVMClient, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *Config) (MissingLogs, error) {
wg := &sync.WaitGroup{}
type dbQueryResult struct {
@@ -696,11 +675,7 @@ var printMissingLogsByType = func(missingLogs map[string][]geth_types.Log, l zer
for _, logs := range missingLogs {
for _, v := range logs {
humanName := findHumanName(v.Topics[0])
- if _, ok := missingByType[humanName]; ok {
- missingByType[humanName] += 1
- } else {
- missingByType[humanName] = 1
- }
+ missingByType[humanName]++
}
}
@@ -709,7 +684,7 @@ var printMissingLogsByType = func(missingLogs map[string][]geth_types.Log, l zer
}
}
-var getEVMLogs = func(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient ctf_blockchain.EVMClient, l zerolog.Logger, cfg *Config) ([]geth_types.Log, error) {
+var getEVMLogs = func(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient blockchain.EVMClient, l zerolog.Logger, cfg *Config) ([]geth_types.Log, error) {
allLogsInEVMNode := make([]geth_types.Log, 0)
for j := 0; j < len(logEmitters); j++ {
address := (*logEmitters[j]).Address()
@@ -757,7 +732,7 @@ func runWaspGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmi
RPSprime = cfg.Wasp.Load.LPS / int64(cfg.General.Contracts) / int64(cfg.General.EventsPerTx) / int64(len(cfg.General.EventsToEmit))
if RPSprime < 1 {
- return 0, fmt.Errorf("Invalid load configuration, effective RPS would have been zero. Adjust LPS, contracts count, events per tx or events to emit")
+ return 0, fmt.Errorf("invalid load configuration, effective RPS would have been zero. Adjust LPS, contracts count, events per tx or events to emit")
}
}
@@ -854,9 +829,8 @@ func getExpectedLogCount(cfg *Config) int64 {
if cfg.General.Generator == GeneratorType_WASP {
if cfg.Wasp.Load.RPS != 0 {
return cfg.Wasp.Load.RPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds()) * int64(cfg.General.EventsPerTx)
- } else {
- return cfg.Wasp.Load.LPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds())
}
+ return cfg.Wasp.Load.LPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds())
}
return int64(len(cfg.General.EventsToEmit) * cfg.LoopedConfig.ExecutionCount * cfg.General.Contracts * cfg.General.EventsPerTx)
@@ -903,6 +877,7 @@ var executeChaosExperiment = func(l zerolog.Logger, testEnv *test_env.CLClusterT
guardChan := make(chan struct{}, 1)
for i := 0; i < cfg.ChaosConfig.ExperimentCount; i++ {
+ i := i
wg.Add(1)
guardChan <- struct{}{}
go func() {
@@ -921,22 +896,21 @@ var executeChaosExperiment = func(l zerolog.Logger, testEnv *test_env.CLClusterT
}()
go func() {
- for {
- select {
- case err, ok := <-chaosChan:
- if !ok {
- l.Info().Msg("All chaos experiments finished")
- errorCh <- nil
- return
- } else {
- if err != nil {
- l.Err(err).Msg("Error encountered during chaos experiment")
- errorCh <- err
- return
- }
- }
+ for err := range chaosChan {
+ // This will receive errors until chaosChan is closed
+ if err != nil {
+ // If an error is encountered, log it, send it to the error channel, and return from the function
+ l.Err(err).Msg("Error encountered during chaos experiment")
+ errorCh <- err
+ return // Return on actual error
}
+ // No need for an else block here, because if err is nil (which happens when the channel is closed),
+ // the loop will exit and the following log and nil send will execute.
}
+
+ // After the loop exits, which it will do when chaosChan is closed, log that all experiments are finished.
+ l.Info().Msg("All chaos experiments finished")
+ errorCh <- nil // Only send nil once, after all errors have been handled and the channel is closed
}()
}
@@ -953,7 +927,7 @@ var GetFinalityDepth = func(chainId int64) (int64, error) {
case 1337:
finalityDepth = 10
default:
- return 0, fmt.Errorf("No known finality depth for chain %d", chainId)
+ return 0, fmt.Errorf("no known finality depth for chain %d", chainId)
}
return finalityDepth, nil
@@ -1014,7 +988,6 @@ var (
func setupLogPollerTestDocker(
t *testing.T,
- testName string,
registryVersion ethereum.KeeperRegistryVersion,
registryConfig contracts.KeeperRegistrySettings,
upkeepsNeeded int,
@@ -1057,8 +1030,8 @@ func setupLogPollerTestDocker(
var logPolllerSettingsFn = func(chain *evmcfg.Chain) *evmcfg.Chain {
chain.LogPollInterval = models.MustNewDuration(lpPollingInterval)
- chain.FinalityDepth = utils2.Ptr[uint32](uint32(finalityDepth))
- chain.FinalityTagEnabled = utils2.Ptr[bool](finalityTagEnabled)
+ chain.FinalityDepth = it_utils.Ptr[uint32](uint32(finalityDepth))
+ chain.FinalityTagEnabled = it_utils.Ptr[bool](finalityTagEnabled)
return chain
}
@@ -1078,6 +1051,7 @@ func setupLogPollerTestDocker(
SlotsPerEpoch: 2,
}).
Build()
+ require.NoError(t, err, "Error building ethereum network config")
env, err = test_env.NewCLTestEnvBuilder().
WithTestLogger(t).
diff --git a/integration-tests/universal/log_poller/scenarios.go b/integration-tests/universal/log_poller/scenarios.go
index 1110a2f8ca..886547d46e 100644
--- a/integration-tests/universal/log_poller/scenarios.go
+++ b/integration-tests/universal/log_poller/scenarios.go
@@ -1,19 +1,20 @@
package logpoller
import (
- "context"
"fmt"
"math/big"
"testing"
"time"
"github.com/onsi/gomega"
+ "github.com/stretchr/testify/require"
+
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
+ "github.com/smartcontractkit/chainlink/integration-tests/utils"
core_logger "github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/stretchr/testify/require"
)
func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
@@ -31,12 +32,11 @@ func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
var (
err error
- testName = "basic-log-poller"
upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit)
)
chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupLogPollerTestDocker(
- t, testName, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(500*time.Millisecond), cfg.General.UseFinalityTag,
+ t, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(500*time.Millisecond), cfg.General.UseFinalityTag,
)
_, upkeepIDs := actions.DeployConsumers(
@@ -100,7 +100,7 @@ func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
// Save block number before starting to emit events, so that we can later use it when querying logs
- sb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ sb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Error getting latest block number")
startBlock := int64(sb)
@@ -122,7 +122,7 @@ func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
// Save block number after finishing to emit events, so that we can later use it when querying logs
- eb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ eb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Error getting latest block number")
endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
@@ -194,13 +194,12 @@ func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string
var (
err error
- testName = "replay-log-poller"
upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit)
)
// we set blockBackfillDepth to 0, to make sure nothing will be backfilled and won't interfere with our test
chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupLogPollerTestDocker(
- t, testName, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(1000*time.Millisecond), cfg.General.UseFinalityTag)
+ t, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(1000*time.Millisecond), cfg.General.UseFinalityTag)
_, upkeepIDs := actions.DeployConsumers(
t,
@@ -230,7 +229,7 @@ func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string
time.Sleep(5 * time.Second)
// Save block number before starting to emit events, so that we can later use it when querying logs
- sb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ sb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Error getting latest block number")
startBlock := int64(sb)
@@ -244,7 +243,7 @@ func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string
l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
// Save block number after finishing to emit events, so that we can later use it when querying logs
- eb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ eb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Error getting latest block number")
endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
@@ -352,12 +351,11 @@ func ExecuteCILogPollerTest(t *testing.T, cfg *Config) {
var (
err error
- testName = "ci-log-poller"
upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit)
)
chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupLogPollerTestDocker(
- t, testName, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(1000*time.Millisecond), cfg.General.UseFinalityTag,
+ t, ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, upKeepsNeeded, time.Duration(1000*time.Millisecond), cfg.General.UseFinalityTag,
)
_, upkeepIDs := actions.DeployConsumers(
@@ -421,7 +419,7 @@ func ExecuteCILogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
// Save block number before starting to emit events, so that we can later use it when querying logs
- sb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ sb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Error getting latest block number")
startBlock := int64(sb)
@@ -443,7 +441,7 @@ func ExecuteCILogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
// Save block number after finishing to emit events, so that we can later use it when querying logs
- eb, err := testEnv.EVMClient.LatestBlockNumber(context.Background())
+ eb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
require.NoError(t, err, "Error getting latest block number")
endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
diff --git a/integration-tests/utils/cl_node_jobs.go b/integration-tests/utils/cl_node_jobs.go
index 16b0c167cf..65dc6e4e39 100644
--- a/integration-tests/utils/cl_node_jobs.go
+++ b/integration-tests/utils/cl_node_jobs.go
@@ -10,13 +10,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/lib/pq"
+ "gopkg.in/guregu/null.v4"
+
coreClient "github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "gopkg.in/guregu/null.v4"
)
-func BuildBootstrapSpec(verifierAddr common.Address, chainID int64, fromBlock uint64, feedId [32]byte) *coreClient.OCR2TaskJobSpec {
+func BuildBootstrapSpec(verifierAddr common.Address, chainID int64, feedId [32]byte) *coreClient.OCR2TaskJobSpec {
hash := common.BytesToHash(feedId[:])
return &coreClient.OCR2TaskJobSpec{
Name: fmt.Sprintf("bootstrap-%s", uuid.NewString()),
diff --git a/integration-tests/utils/common.go b/integration-tests/utils/common.go
index 9aacaeed41..5ef3209c92 100644
--- a/integration-tests/utils/common.go
+++ b/integration-tests/utils/common.go
@@ -1,8 +1,10 @@
package utils
import (
+ "context"
"math/big"
"net"
+ "testing"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
@@ -33,3 +35,20 @@ func BigIntSliceContains(slice []*big.Int, b *big.Int) bool {
}
return false
}
+
+// TestContext returns a context with the test's deadline, if available.
+func TestContext(tb testing.TB) context.Context {
+ ctx := context.Background()
+ var cancel func()
+ switch t := tb.(type) {
+ case *testing.T:
+ if d, ok := t.Deadline(); ok {
+ ctx, cancel = context.WithDeadline(ctx, d)
+ }
+ }
+ if cancel == nil {
+ ctx, cancel = context.WithCancel(ctx)
+ }
+ tb.Cleanup(cancel)
+ return ctx
+}
diff --git a/integration-tests/utils/log.go b/integration-tests/utils/log.go
deleted file mode 100644
index 499be8002d..0000000000
--- a/integration-tests/utils/log.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package utils
-
-import (
- "github.com/rs/zerolog"
- "github.com/rs/zerolog/log"
- "os"
-)
-
-func SetupCoreDockerEnvLogger() {
- lvlStr := os.Getenv("CORE_DOCKER_ENV_LOG_LEVEL")
- if lvlStr == "" {
- lvlStr = "info"
- }
- lvl, err := zerolog.ParseLevel(lvlStr)
- if err != nil {
- panic(err)
- }
- log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Level(lvl)
-}
diff --git a/integration-tests/utils/templates/secrets.go b/integration-tests/utils/templates/secrets.go
index f81287e871..45edf0d012 100644
--- a/integration-tests/utils/templates/secrets.go
+++ b/integration-tests/utils/templates/secrets.go
@@ -2,6 +2,7 @@ package templates
import (
"github.com/google/uuid"
+
"github.com/smartcontractkit/chainlink-testing-framework/utils/templates"
)
From f7981f5c10403eca31a11d55b356e1191725f5c3 Mon Sep 17 00:00:00 2001
From: Mateusz Sekara
Date: Mon, 13 Nov 2023 17:43:00 +0100
Subject: [PATCH 136/327] CCIP-1277 LogPoller - Fixing leaky abstraction by
removing Q() from the ORM interface (#11200)
* Fixing leaky abstraction by removing Q() from the ORM interface. Moving all the TX internals into the ORM implementation
* Adding test
* Post review fix
* Post rebase fixes
---
core/chains/evm/logpoller/log_poller.go | 39 +----
core/chains/evm/logpoller/models.go | 9 ++
core/chains/evm/logpoller/observability.go | 22 +--
.../evm/logpoller/observability_test.go | 2 +-
core/chains/evm/logpoller/orm.go | 99 ++++++++----
core/chains/evm/logpoller/orm_test.go | 141 +++++++++++++++++-
6 files changed, 232 insertions(+), 80 deletions(-)
diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go
index 01d6a2aad4..b86ede5dbc 100644
--- a/core/chains/evm/logpoller/log_poller.go
+++ b/core/chains/evm/logpoller/log_poller.go
@@ -679,9 +679,7 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error {
}
lp.lggr.Debugw("Backfill found logs", "from", from, "to", to, "logs", len(gethLogs), "blocks", blocks)
- err = lp.orm.Q().WithOpts(pg.WithParentCtx(ctx)).Transaction(func(tx pg.Queryer) error {
- return lp.orm.InsertLogs(convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), pg.WithQueryer(tx))
- })
+ err = lp.orm.InsertLogs(convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), pg.WithParentCtx(ctx))
if err != nil {
lp.lggr.Warnw("Unable to insert logs, retrying", "err", err, "from", from, "to", to)
return err
@@ -750,21 +748,7 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren
// the canonical set per read. Typically, if an application took action on a log
// it would be saved elsewhere e.g. evm.txes, so it seems better to just support the fast reads.
// Its also nicely analogous to reading from the chain itself.
- err2 = lp.orm.Q().WithOpts(pg.WithParentCtx(ctx)).Transaction(func(tx pg.Queryer) error {
- // These deletes are bounded by reorg depth, so they are
- // fast and should not slow down the log readers.
- err3 := lp.orm.DeleteBlocksAfter(blockAfterLCA.Number, pg.WithQueryer(tx))
- if err3 != nil {
- lp.lggr.Warnw("Unable to clear reorged blocks, retrying", "err", err3)
- return err3
- }
- err3 = lp.orm.DeleteLogsAfter(blockAfterLCA.Number, pg.WithQueryer(tx))
- if err3 != nil {
- lp.lggr.Warnw("Unable to clear reorged logs, retrying", "err", err3)
- return err3
- }
- return nil
- })
+ err2 = lp.orm.DeleteLogsAndBlocksAfter(blockAfterLCA.Number, pg.WithParentCtx(ctx))
if err2 != nil {
// If we error on db commit, we can't know if the tx went through or not.
// We return an error here which will cause us to restart polling from lastBlockSaved + 1
@@ -849,20 +833,11 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int
return
}
lp.lggr.Debugw("Unfinalized log query", "logs", len(logs), "currentBlockNumber", currentBlockNumber, "blockHash", currentBlock.Hash, "timestamp", currentBlock.Timestamp.Unix())
- err = lp.orm.Q().WithOpts(pg.WithParentCtx(ctx)).Transaction(func(tx pg.Queryer) error {
- if err2 := lp.orm.InsertBlock(h, currentBlockNumber, currentBlock.Timestamp, latestFinalizedBlockNumber, pg.WithQueryer(tx)); err2 != nil {
- return err2
- }
- if len(logs) == 0 {
- return nil
- }
- return lp.orm.InsertLogs(convertLogs(logs,
- []LogPollerBlock{{BlockNumber: currentBlockNumber,
- BlockTimestamp: currentBlock.Timestamp}},
- lp.lggr,
- lp.ec.ConfiguredChainID(),
- ), pg.WithQueryer(tx))
- })
+ block := NewLogPollerBlock(h, currentBlockNumber, currentBlock.Timestamp, latestFinalizedBlockNumber)
+ err = lp.orm.InsertLogsWithBlock(
+ convertLogs(logs, []LogPollerBlock{block}, lp.lggr, lp.ec.ConfiguredChainID()),
+ block,
+ )
if err != nil {
lp.lggr.Warnw("Unable to save logs resuming from last saved block + 1", "err", err, "block", currentBlockNumber)
return
diff --git a/core/chains/evm/logpoller/models.go b/core/chains/evm/logpoller/models.go
index 9c55786777..87ddd079a5 100644
--- a/core/chains/evm/logpoller/models.go
+++ b/core/chains/evm/logpoller/models.go
@@ -56,3 +56,12 @@ func (l *Log) ToGethLog() types.Log {
Index: uint(l.LogIndex),
}
}
+
+func NewLogPollerBlock(blockHash common.Hash, blockNumber int64, timestamp time.Time, finalizedBlockNumber int64) LogPollerBlock {
+ return LogPollerBlock{
+ BlockHash: blockHash,
+ BlockNumber: blockNumber,
+ BlockTimestamp: timestamp,
+ FinalizedBlockNumber: finalizedBlockNumber,
+ }
+}
diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go
index c4b58b42a2..03f4b77be2 100644
--- a/core/chains/evm/logpoller/observability.go
+++ b/core/chains/evm/logpoller/observability.go
@@ -68,19 +68,15 @@ func NewObservedORM(chainID *big.Int, db *sqlx.DB, lggr logger.Logger, cfg pg.QC
}
}
-func (o *ObservedORM) Q() pg.Q {
- return o.ORM.Q()
-}
-
func (o *ObservedORM) InsertLogs(logs []Log, qopts ...pg.QOpt) error {
return withObservedExec(o, "InsertLogs", func() error {
return o.ORM.InsertLogs(logs, qopts...)
})
}
-func (o *ObservedORM) InsertBlock(hash common.Hash, blockNumber int64, blockTimestamp time.Time, lastFinalizedBlock int64, qopts ...pg.QOpt) error {
- return withObservedExec(o, "InsertBlock", func() error {
- return o.ORM.InsertBlock(hash, blockNumber, blockTimestamp, lastFinalizedBlock, qopts...)
+func (o *ObservedORM) InsertLogsWithBlock(logs []Log, block LogPollerBlock, qopts ...pg.QOpt) error {
+ return withObservedExec(o, "InsertLogsWithBlock", func() error {
+ return o.ORM.InsertLogsWithBlock(logs, block, qopts...)
})
}
@@ -102,21 +98,15 @@ func (o *ObservedORM) DeleteFilter(name string, qopts ...pg.QOpt) error {
})
}
-func (o *ObservedORM) DeleteBlocksAfter(start int64, qopts ...pg.QOpt) error {
- return withObservedExec(o, "DeleteBlocksAfter", func() error {
- return o.ORM.DeleteBlocksAfter(start, qopts...)
- })
-}
-
func (o *ObservedORM) DeleteBlocksBefore(end int64, qopts ...pg.QOpt) error {
return withObservedExec(o, "DeleteBlocksBefore", func() error {
return o.ORM.DeleteBlocksBefore(end, qopts...)
})
}
-func (o *ObservedORM) DeleteLogsAfter(start int64, qopts ...pg.QOpt) error {
- return withObservedExec(o, "DeleteLogsAfter", func() error {
- return o.ORM.DeleteLogsAfter(start, qopts...)
+func (o *ObservedORM) DeleteLogsAndBlocksAfter(start int64, qopts ...pg.QOpt) error {
+ return withObservedExec(o, "DeleteLogsAndBlocksAfter", func() error {
+ return o.ORM.DeleteLogsAndBlocksAfter(start, qopts...)
})
}
diff --git a/core/chains/evm/logpoller/observability_test.go b/core/chains/evm/logpoller/observability_test.go
index 0d3eadf47d..ded3d7854d 100644
--- a/core/chains/evm/logpoller/observability_test.go
+++ b/core/chains/evm/logpoller/observability_test.go
@@ -38,7 +38,7 @@ func TestMultipleMetricsArePublished(t *testing.T) {
_, _ = orm.SelectLatestLogEventSigsAddrsWithConfs(0, []common.Address{{}}, []common.Hash{{}}, 1, pg.WithParentCtx(ctx))
_, _ = orm.SelectIndexedLogsCreatedAfter(common.Address{}, common.Hash{}, 1, []common.Hash{}, time.Now(), 0, pg.WithParentCtx(ctx))
_ = orm.InsertLogs([]Log{}, pg.WithParentCtx(ctx))
- _ = orm.InsertBlock(common.Hash{}, 1, time.Now(), 0, pg.WithParentCtx(ctx))
+ _ = orm.InsertLogsWithBlock([]Log{}, NewLogPollerBlock(common.Hash{}, 1, time.Now(), 0), pg.WithParentCtx(ctx))
require.Equal(t, 13, testutil.CollectAndCount(orm.queryDuration))
require.Equal(t, 10, testutil.CollectAndCount(orm.datasetSize))
diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go
index e044be2e0c..a1b86d2cb2 100644
--- a/core/chains/evm/logpoller/orm.go
+++ b/core/chains/evm/logpoller/orm.go
@@ -20,17 +20,15 @@ import (
// it exposes some of the database implementation details (e.g. pg.Q). Ideally it should be agnostic and could be applied to any persistence layer.
// What is more, LogPoller should not be aware of the underlying database implementation and delegate all the queries to the ORM.
type ORM interface {
- Q() pg.Q
InsertLogs(logs []Log, qopts ...pg.QOpt) error
- InsertBlock(blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, lastFinalizedBlockNumber int64, qopts ...pg.QOpt) error
+ InsertLogsWithBlock(logs []Log, block LogPollerBlock, qopts ...pg.QOpt) error
InsertFilter(filter Filter, qopts ...pg.QOpt) error
LoadFilters(qopts ...pg.QOpt) (map[string]Filter, error)
DeleteFilter(name string, qopts ...pg.QOpt) error
- DeleteBlocksAfter(start int64, qopts ...pg.QOpt) error
DeleteBlocksBefore(end int64, qopts ...pg.QOpt) error
- DeleteLogsAfter(start int64, qopts ...pg.QOpt) error
+ DeleteLogsAndBlocksAfter(start int64, qopts ...pg.QOpt) error
DeleteExpiredLogs(qopts ...pg.QOpt) error
GetBlocksRange(start int64, end int64, qopts ...pg.QOpt) ([]LogPollerBlock, error)
@@ -58,6 +56,7 @@ type ORM interface {
type DbORM struct {
chainID *big.Int
q pg.Q
+ lggr logger.Logger
}
// NewORM creates a DbORM scoped to chainID.
@@ -67,13 +66,10 @@ func NewORM(chainID *big.Int, db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *
return &DbORM{
chainID: chainID,
q: q,
+ lggr: lggr,
}
}
-func (o *DbORM) Q() pg.Q {
- return o.q
-}
-
// InsertBlock is idempotent to support replays.
func (o *DbORM) InsertBlock(blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, finalizedBlock int64, qopts ...pg.QOpt) error {
args, err := newQueryArgs(o.chainID).
@@ -191,12 +187,6 @@ func (o *DbORM) SelectLatestLogByEventSigWithConfs(eventSig common.Hash, address
return &l, nil
}
-// DeleteBlocksAfter delete all blocks after and including start.
-func (o *DbORM) DeleteBlocksAfter(start int64, qopts ...pg.QOpt) error {
- q := o.q.WithOpts(qopts...)
- return q.ExecQ(`DELETE FROM evm.log_poller_blocks WHERE block_number >= $1 AND evm_chain_id = $2`, start, utils.NewBig(o.chainID))
-}
-
// DeleteBlocksBefore delete all blocks before and including end.
func (o *DbORM) DeleteBlocksBefore(end int64, qopts ...pg.QOpt) error {
q := o.q.WithOpts(qopts...)
@@ -204,9 +194,31 @@ func (o *DbORM) DeleteBlocksBefore(end int64, qopts ...pg.QOpt) error {
return err
}
-func (o *DbORM) DeleteLogsAfter(start int64, qopts ...pg.QOpt) error {
- q := o.q.WithOpts(qopts...)
- return q.ExecQ(`DELETE FROM evm.logs WHERE block_number >= $1 AND evm_chain_id = $2`, start, utils.NewBig(o.chainID))
+func (o *DbORM) DeleteLogsAndBlocksAfter(start int64, qopts ...pg.QOpt) error {
+ // These deletes are bounded by reorg depth, so they are
+ // fast and should not slow down the log readers.
+ return o.q.WithOpts(qopts...).Transaction(func(tx pg.Queryer) error {
+ args, err := newQueryArgs(o.chainID).
+ withStartBlock(start).
+ toArgs()
+ if err != nil {
+ o.lggr.Error("Cant build args for DeleteLogsAndBlocksAfter queries", "err", err)
+ return err
+ }
+
+ _, err = tx.NamedExec(`DELETE FROM evm.log_poller_blocks WHERE block_number >= :start_block AND evm_chain_id = :evm_chain_id`, args)
+ if err != nil {
+ o.lggr.Warnw("Unable to clear reorged blocks, retrying", "err", err)
+ return err
+ }
+
+ _, err = tx.NamedExec(`DELETE FROM evm.logs WHERE block_number >= :start_block AND evm_chain_id = :evm_chain_id`, args)
+ if err != nil {
+ o.lggr.Warnw("Unable to clear reorged logs, retrying", "err", err)
+ return err
+ }
+ return nil
+ })
}
type Exp struct {
@@ -233,13 +245,35 @@ func (o *DbORM) DeleteExpiredLogs(qopts ...pg.QOpt) error {
// InsertLogs is idempotent to support replays.
func (o *DbORM) InsertLogs(logs []Log, qopts ...pg.QOpt) error {
- for _, log := range logs {
- if o.chainID.Cmp(log.EvmChainId.ToInt()) != 0 {
- return errors.Errorf("invalid chainID in log got %v want %v", log.EvmChainId.ToInt(), o.chainID)
- }
+ if err := o.validateLogs(logs); err != nil {
+ return err
}
- q := o.q.WithOpts(qopts...)
+ return o.q.WithOpts(qopts...).Transaction(func(tx pg.Queryer) error {
+ return o.insertLogsWithinTx(logs, tx)
+ })
+}
+
+func (o *DbORM) InsertLogsWithBlock(logs []Log, block LogPollerBlock, qopts ...pg.QOpt) error {
+ // Optimization, don't open TX when there is only a block to be persisted
+ if len(logs) == 0 {
+ return o.InsertBlock(block.BlockHash, block.BlockNumber, block.BlockTimestamp, block.FinalizedBlockNumber, qopts...)
+ }
+
+ if err := o.validateLogs(logs); err != nil {
+ return err
+ }
+
+ // Block and logs goes with the same TX to ensure atomicity
+ return o.q.WithOpts(qopts...).Transaction(func(tx pg.Queryer) error {
+ if err := o.InsertBlock(block.BlockHash, block.BlockNumber, block.BlockTimestamp, block.FinalizedBlockNumber, pg.WithQueryer(tx)); err != nil {
+ return err
+ }
+ return o.insertLogsWithinTx(logs, tx)
+ })
+}
+
+func (o *DbORM) insertLogsWithinTx(logs []Log, tx pg.Queryer) error {
batchInsertSize := 4000
for i := 0; i < len(logs); i += batchInsertSize {
start, end := i, i+batchInsertSize
@@ -247,12 +281,14 @@ func (o *DbORM) InsertLogs(logs []Log, qopts ...pg.QOpt) error {
end = len(logs)
}
- err := q.ExecQNamed(`
- INSERT INTO evm.logs
- (evm_chain_id, log_index, block_hash, block_number, block_timestamp, address, event_sig, topics, tx_hash, data, created_at)
+ _, err := tx.NamedExec(`
+ INSERT INTO evm.logs
+ (evm_chain_id, log_index, block_hash, block_number, block_timestamp, address, event_sig, topics, tx_hash, data, created_at)
VALUES
- (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW())
- ON CONFLICT DO NOTHING`, logs[start:end])
+ (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW())
+ ON CONFLICT DO NOTHING`,
+ logs[start:end],
+ )
if err != nil {
if errors.Is(err, context.DeadlineExceeded) && batchInsertSize > 500 {
@@ -267,6 +303,15 @@ func (o *DbORM) InsertLogs(logs []Log, qopts ...pg.QOpt) error {
return nil
}
+func (o *DbORM) validateLogs(logs []Log) error {
+ for _, log := range logs {
+ if o.chainID.Cmp(log.EvmChainId.ToInt()) != 0 {
+ return errors.Errorf("invalid chainID in log got %v want %v", log.EvmChainId.ToInt(), o.chainID)
+ }
+ }
+ return nil
+}
+
func (o *DbORM) SelectLogsByBlockRange(start, end int64) ([]Log, error) {
args, err := newQueryArgs(o.chainID).
withStartBlock(start).
diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go
index 66e1afdc93..887984055e 100644
--- a/core/chains/evm/logpoller/orm_test.go
+++ b/core/chains/evm/logpoller/orm_test.go
@@ -4,6 +4,7 @@ import (
"bytes"
"database/sql"
"fmt"
+ "math"
"math/big"
"testing"
"time"
@@ -15,7 +16,10 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -179,13 +183,13 @@ func TestORM(t *testing.T) {
assert.Equal(t, int64(12), latest.BlockNumber)
// Delete a block (only 10 on chain).
- require.NoError(t, o1.DeleteBlocksAfter(10))
+ require.NoError(t, o1.DeleteLogsAndBlocksAfter(10))
_, err = o1.SelectBlockByHash(common.HexToHash("0x1234"))
require.Error(t, err)
assert.True(t, errors.Is(err, sql.ErrNoRows))
// Delete blocks from another chain.
- require.NoError(t, o2.DeleteBlocksAfter(11))
+ require.NoError(t, o2.DeleteLogsAndBlocksAfter(11))
_, err = o2.SelectBlockByHash(common.HexToHash("0x1234"))
require.Error(t, err)
assert.True(t, errors.Is(err, sql.ErrNoRows))
@@ -318,7 +322,6 @@ func TestORM(t *testing.T) {
require.Error(t, err)
assert.True(t, errors.Is(err, sql.ErrNoRows))
// With block 12, anything <=2 should work
- require.NoError(t, o1.DeleteBlocksAfter(10))
require.NoError(t, o1.InsertBlock(common.HexToHash("0x1234"), 11, time.Now(), 0))
require.NoError(t, o1.InsertBlock(common.HexToHash("0x1235"), 12, time.Now(), 0))
_, err = o1.SelectLatestLogByEventSigWithConfs(topic, common.HexToAddress("0x1234"), 0)
@@ -421,7 +424,7 @@ func TestORM(t *testing.T) {
assert.Len(t, logs, 7)
// Delete logs after should delete all logs.
- err = o1.DeleteLogsAfter(1)
+ err = o1.DeleteLogsAndBlocksAfter(1)
require.NoError(t, err)
logs, err = o1.SelectLogsByBlockRange(1, latest.BlockNumber)
require.NoError(t, err)
@@ -1301,3 +1304,133 @@ func TestNestedLogPollerBlocksQuery(t *testing.T) {
require.NoError(t, err)
require.Len(t, logs, 0)
}
+
+func TestInsertLogsWithBlock(t *testing.T) {
+ chainID := testutils.NewRandomEVMChainID()
+ event := utils.RandomBytes32()
+ address := utils.RandomAddress()
+
+ // We need full db here, because we want to test transaction rollbacks.
+ // Using pgtest.NewSqlxDB(t) will run all tests in TXs which is not desired for this type of test
+ // (inner tx rollback will rollback outer tx, blocking rest of execution)
+ _, db := heavyweight.FullTestDBV2(t, nil)
+ o := logpoller.NewORM(chainID, db, logger.TestLogger(t), pgtest.NewQConfig(true))
+
+ correctLog := GenLog(chainID, 1, 1, utils.RandomAddress().String(), event[:], address)
+ invalidLog := GenLog(chainID, -10, -10, utils.RandomAddress().String(), event[:], address)
+ correctBlock := logpoller.NewLogPollerBlock(utils.RandomBytes32(), 20, time.Now(), 10)
+ invalidBlock := logpoller.NewLogPollerBlock(utils.RandomBytes32(), -10, time.Now(), -10)
+
+ tests := []struct {
+ name string
+ logs []logpoller.Log
+ block logpoller.LogPollerBlock
+ shouldRollback bool
+ }{
+ {
+ name: "properly persist all data",
+ logs: []logpoller.Log{correctLog},
+ block: correctBlock,
+ shouldRollback: false,
+ },
+ {
+ name: "rollbacks transaction when block is invalid",
+ logs: []logpoller.Log{correctLog},
+ block: invalidBlock,
+ shouldRollback: true,
+ },
+ {
+ name: "rollbacks transaction when log is invalid",
+ logs: []logpoller.Log{invalidLog},
+ block: correctBlock,
+ shouldRollback: true,
+ },
+ {
+ name: "rollback when only some logs are invalid",
+ logs: []logpoller.Log{correctLog, invalidLog},
+ block: correctBlock,
+ shouldRollback: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // clean all logs and blocks between test cases
+ defer func() { _ = o.DeleteLogsAndBlocksAfter(0) }()
+ insertError := o.InsertLogsWithBlock(tt.logs, tt.block)
+
+ logs, logsErr := o.SelectLogs(0, math.MaxInt, address, event)
+ block, blockErr := o.SelectLatestBlock()
+
+ if tt.shouldRollback {
+ assert.Error(t, insertError)
+
+ assert.NoError(t, logsErr)
+ assert.Len(t, logs, 0)
+
+ assert.Error(t, blockErr)
+ } else {
+ assert.NoError(t, insertError)
+
+ assert.NoError(t, logsErr)
+ assert.Len(t, logs, len(tt.logs))
+
+ assert.NoError(t, blockErr)
+ assert.Equal(t, block.BlockNumber, tt.block.BlockNumber)
+ }
+ })
+ }
+}
+
+func TestInsertLogsInTx(t *testing.T) {
+ chainID := testutils.NewRandomEVMChainID()
+ event := utils.RandomBytes32()
+ address := utils.RandomAddress()
+ maxLogsSize := 9000
+
+ // We need full db here, because we want to test transaction rollbacks.
+ _, db := heavyweight.FullTestDBV2(t, nil)
+ o := logpoller.NewORM(chainID, db, logger.TestLogger(t), pgtest.NewQConfig(true))
+
+ logs := make([]logpoller.Log, maxLogsSize, maxLogsSize+1)
+ for i := 0; i < maxLogsSize; i++ {
+ logs[i] = GenLog(chainID, int64(i+1), int64(i+1), utils.RandomAddress().String(), event[:], address)
+ }
+ invalidLog := GenLog(chainID, -10, -10, utils.RandomAddress().String(), event[:], address)
+
+ tests := []struct {
+ name string
+ logs []logpoller.Log
+ shouldRollback bool
+ }{
+ {
+ name: "all logs persisted",
+ logs: logs,
+ shouldRollback: false,
+ },
+ {
+ name: "rollback when invalid log is passed",
+ logs: append(logs, invalidLog),
+ shouldRollback: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // clean all logs and blocks between test cases
+ defer func() { _ = o.DeleteLogsAndBlocksAfter(0) }()
+
+ insertErr := o.InsertLogs(tt.logs)
+ logsFromDb, err := o.SelectLogs(0, math.MaxInt, address, event)
+ assert.NoError(t, err)
+
+ if tt.shouldRollback {
+ assert.Error(t, insertErr)
+ assert.Len(t, logsFromDb, 0)
+ } else {
+ assert.NoError(t, insertErr)
+ assert.Len(t, logsFromDb, len(tt.logs))
+ }
+ })
+ }
+}
From c8902245b2847fd3c201ebc10a992181f84a3d02 Mon Sep 17 00:00:00 2001
From: Patrick
Date: Mon, 13 Nov 2023 13:03:15 -0500
Subject: [PATCH 137/327] bumping relay and wiring logger through (#11172)
---
core/cmd/shell.go | 5 +++--
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 ++--
go.mod | 2 +-
go.sum | 4 ++--
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
7 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 595c42b9fe..e1ac0b99ca 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -60,7 +60,7 @@ var (
grpcOpts loop.GRPCOpts
)
-func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing) error {
+func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, logger logger.Logger) error {
// Avoid double initializations, but does not prevent relay methods from being called multiple times.
var err error
initGlobalsOnce.Do(func() {
@@ -71,6 +71,7 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing) error {
CollectorTarget: cfgTracing.CollectorTarget(),
NodeAttributes: cfgTracing.Attributes(),
SamplingRatio: cfgTracing.SamplingRatio(),
+ OnDialError: func(error) { logger.Errorw("Failed to dial", "err", err) },
})
})
return err
@@ -134,7 +135,7 @@ 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, db *sqlx.DB) (app chainlink.Application, err error) {
- err = initGlobals(cfg.Prometheus(), cfg.Tracing())
+ err = initGlobals(cfg.Prometheus(), cfg.Tracing(), appLggr)
if err != nil {
appLggr.Errorf("Failed to initialize globals: %v", err)
}
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index bb68175ddf..eb41312a6a 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -304,7 +304,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index bd3b75d37a..35e85fe2c9 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1464,8 +1464,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 h1:28XkPE6YfJ4uabTX9/7sueRV6IKtY4hcm1nIt1e6b20=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a h1:G/pD8uI1PULRJU8Y3eLLzjqQBp9ruG9hj+wWxtyrgTo=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/go.mod b/go.mod
index 8a4d58469c..0a85fe7f48 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
diff --git a/go.sum b/go.sum
index 1b96c936c5..7fe91a6b12 100644
--- a/go.sum
+++ b/go.sum
@@ -1465,8 +1465,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 h1:28XkPE6YfJ4uabTX9/7sueRV6IKtY4hcm1nIt1e6b20=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a h1:G/pD8uI1PULRJU8Y3eLLzjqQBp9ruG9hj+wWxtyrgTo=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index b5455838b5..a943e1c41a 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -387,7 +387,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index fc486e5451..5719c36b5a 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2369,8 +2369,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742 h1:28XkPE6YfJ4uabTX9/7sueRV6IKtY4hcm1nIt1e6b20=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231108215906-8bbaf383b742/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a h1:G/pD8uI1PULRJU8Y3eLLzjqQBp9ruG9hj+wWxtyrgTo=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
From 58b0e2536cad8f183865cc2004cd6969492c0816 Mon Sep 17 00:00:00 2001
From: FelixFan1992
Date: Mon, 13 Nov 2023 13:38:17 -0500
Subject: [PATCH 138/327] add ocr3-automation telemetry type (#11087)
* add ocr3-automation telemetry type
* pass ocr3 automation telem type to 2.1
---
core/services/ocr2/delegate.go | 2 +-
core/services/synchronization/common.go | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 9905ed6ae6..bbb3b5cf7a 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -1122,7 +1122,7 @@ func (d *Delegate) newServicesOCR2Keepers21(
ContractConfigTracker: keeperProvider.ContractConfigTracker(),
KeepersDatabase: ocrDB,
Logger: ocrLogger,
- MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2Automation),
+ MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR3Automation),
OffchainConfigDigester: keeperProvider.OffchainConfigDigester(),
OffchainKeyring: kb,
OnchainKeyring: services.Keyring(),
diff --git a/core/services/synchronization/common.go b/core/services/synchronization/common.go
index 32f3a86c6f..584f5b2438 100644
--- a/core/services/synchronization/common.go
+++ b/core/services/synchronization/common.go
@@ -22,6 +22,7 @@ const (
OCR3Mercury TelemetryType = "ocr3-mercury"
OCR2VRF TelemetryType = "ocr2-vrf"
AutomationCustom TelemetryType = "automation-custom"
+ OCR3Automation TelemetryType = "ocr3-automation"
)
type TelemPayload struct {
From 023985b15d3a58db8425bc30aed49cca454679f4 Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Mon, 13 Nov 2023 14:53:46 -0500
Subject: [PATCH 139/327] [Functions] Coordinator v1.1 changes (#11269)
* inline abi decode and reduce string length
* mv ChainSpecificUtil to lib
* Regenerate geth wrappers & gas snapshot
---------
Co-authored-by: Rens Rooimans
---
.../gas-snapshots/functions.gas-snapshot | 24 +++++++++----------
.../functions/dev/v1_X/FunctionsBilling.sol | 2 +-
.../dev/v1_X/FunctionsCoordinator.sol | 20 +++++++---------
.../{ => libraries}/ChainSpecificUtil.sol | 4 ++--
.../functions_coordinator.go | 2 +-
...rapper-dependency-versions-do-not-edit.txt | 2 +-
6 files changed, 25 insertions(+), 29 deletions(-)
rename contracts/src/v0.8/functions/dev/v1_X/{ => libraries}/ChainSpecificUtil.sol (94%)
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index 521b3bffac..82b5b494a7 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,12 +1,12 @@
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14600662)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14600640)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14600656)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14612076)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14612053)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14612025)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14611976)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14611965)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14612009)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14577815)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14577793)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14577809)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14589229)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14589206)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14589178)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14589129)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14589118)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14589162)
FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
@@ -141,10 +141,10 @@ FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Reve
FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13459)
FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 59592)
FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15010)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43863, ~: 45548)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46375, ~: 48060)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata(uint96) (runs: 256, μ: 43508, ~: 45548)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription(uint96) (runs: 256, μ: 46020, ~: 48060)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink(uint96) (runs: 256, μ: 14295, ~: 14295)
-FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51177, ~: 53040)
+FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused(uint96) (runs: 256, μ: 51089, ~: 53040)
FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success(uint96) (runs: 256, μ: 86057, ~: 89604)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20745)
FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189)
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
index e4b6fe7d90..cb4f2f4567 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
@@ -10,7 +10,7 @@ import {FunctionsResponse} from "./libraries/FunctionsResponse.sol";
import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol";
-import {ChainSpecificUtil} from "./ChainSpecificUtil.sol";
+import {ChainSpecificUtil} from "./libraries/ChainSpecificUtil.sol";
/// @title Functions Billing contract
/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON).
diff --git a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
index 15949a497e..16e9029ce3 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol
@@ -133,15 +133,13 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
address[MAX_NUM_ORACLES] memory /*signers*/,
bytes calldata report
) internal override {
- bytes32[] memory requestIds;
- bytes[] memory results;
- bytes[] memory errors;
- bytes[] memory onchainMetadata;
- bytes[] memory offchainMetadata;
- (requestIds, results, errors, onchainMetadata, offchainMetadata) = abi.decode(
- report,
- (bytes32[], bytes[], bytes[], bytes[], bytes[])
- );
+ (
+ bytes32[] memory requestIds,
+ bytes[] memory results,
+ bytes[] memory errors,
+ bytes[] memory onchainMetadata,
+ bytes[] memory offchainMetadata
+ ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[]));
uint256 numberOfFulfillments = uint8(requestIds.length);
if (
@@ -151,9 +149,7 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
numberOfFulfillments != onchainMetadata.length ||
numberOfFulfillments != offchainMetadata.length
) {
- revert ReportInvalid(
- "All fields on the report must be of equal length: requestIds, results, errors, onchainMetadata, offchainMetadata"
- );
+ revert ReportInvalid("Fields must be equal length");
}
// Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig
diff --git a/contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol b/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol
similarity index 94%
rename from contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol
rename to contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol
index f0eec19db2..d6569a256b 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/ChainSpecificUtil.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
-import {ArbGasInfo} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
-import {OVM_GasPriceOracle} from "../../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
+import {ArbGasInfo} from "../../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
+import {OVM_GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
/// @dev A library that abstracts out opcodes that behave differently across chains.
/// @dev The methods below return values that are pertinent to the given chain.
diff --git a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
index 3e3fac16d1..5f0d2d45f2 100644
--- a/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
+++ b/core/gethwrappers/functions/generated/functions_coordinator/functions_coordinator.go
@@ -72,7 +72,7 @@ type FunctionsResponseRequestMeta struct {
var FunctionsCoordinatorMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"linkToNativeFeed\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InconsistentReportData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransmittersSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByRouterOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustBeSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedPublicKeyChange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedRequestDataVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CommitmentDeleted\",\"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\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requestInitiator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callbackGasLimit\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OracleResponse\",\"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\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"juelsPerGas\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1FeeShareWei\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"callbackCostJuels\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalCostJuels\",\"type\":\"uint96\"}],\"name\":\"RequestBilled\",\"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\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"deleteCommitment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateCost\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAdminFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getDONFee\",\"outputs\":[{\"internalType\":\"uint72\",\"name\":\"\",\"type\":\"uint72\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getThresholdPublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"oracleWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleWithdrawAll\",\"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\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"donPublicKey\",\"type\":\"bytes\"}],\"name\":\"setDONPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"thresholdPublicKey\",\"type\":\"bytes\"}],\"name\":\"setThresholdPublicKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"flags\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"requestingContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"availableBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initiatedRequests\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"dataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"completedRequests\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subscriptionOwner\",\"type\":\"address\"}],\"internalType\":\"structFunctionsResponse.RequestMeta\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"startRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"estimatedTotalCostJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"adminFee\",\"type\":\"uint72\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"timeoutTimestamp\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsResponse.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"}],\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fulfillmentGasPriceOverEstimationBP\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feedStalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadBeforeCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasOverheadAfterCallback\",\"type\":\"uint32\"},{\"internalType\":\"uint72\",\"name\":\"donFee\",\"type\":\"uint72\"},{\"internalType\":\"uint40\",\"name\":\"minimumEstimateGasPriceWei\",\"type\":\"uint40\"},{\"internalType\":\"uint16\",\"name\":\"maxSupportedRequestDataVersion\",\"type\":\"uint16\"},{\"internalType\":\"uint224\",\"name\":\"fallbackNativePerUnitLink\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"requestTimeoutSeconds\",\"type\":\"uint32\"}],\"internalType\":\"structFunctionsBilling.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x60a06040523480156200001157600080fd5b50604051620057423803806200574283398101604081905262000034916200046d565b8282828233806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c28162000139565b5050506001600160a01b038116620000ed57604051632530e88560e11b815260040160405180910390fd5b6001600160a01b03908116608052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200012d82620001e4565b5050505050506200062c565b336001600160a01b03821603620001935760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee62000342565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033790839062000576565b60405180910390a150565b6200034c6200034e565b565b6000546001600160a01b031633146200034c5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000086565b80516001600160a01b0381168114620003c257600080fd5b919050565b60405161012081016001600160401b0381118282101715620003f957634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c257600080fd5b80516001600160481b0381168114620003c257600080fd5b805164ffffffffff81168114620003c257600080fd5b805161ffff81168114620003c257600080fd5b80516001600160e01b0381168114620003c257600080fd5b60008060008385036101608112156200048557600080fd5b6200049085620003aa565b935061012080601f1983011215620004a757600080fd5b620004b1620003c7565b9150620004c160208701620003ff565b8252620004d160408701620003ff565b6020830152620004e460608701620003ff565b6040830152620004f760808701620003ff565b60608301526200050a60a0870162000414565b60808301526200051d60c087016200042c565b60a08301526200053060e0870162000442565b60c08301526101006200054581880162000455565b60e084015262000557828801620003ff565b908301525091506200056d6101408501620003aa565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005c960808401826001600160481b03169052565b5060a0830151620005e360a084018264ffffffffff169052565b5060c0830151620005fa60c084018261ffff169052565b5060e08301516200061660e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b6080516150d06200067260003960008181610845015281816109d301528181610ca601528181610f3a0152818161104501528181611789015261350201526150d06000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a0366004613a46565b61059c565b005b6101a56101b5366004613bef565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613d13565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613db4565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613e43565b6108d7565b6101a5610a90565b6101a5610b92565b6101a5610293366004613a46565b610d92565b6102a0610de2565b6040516102039190613ecd565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613ee0565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613ef9565b610fd4565b604051610203919061404e565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab3660046140a2565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b6040516102039190614159565b61053b610536366004614249565b611785565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f66118e5565b6101a561056e366004614362565b61193c565b61057b6124b8565b604051908152602001610203565b6101a561059736600461442f565b612711565b6105a4612725565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec8284836144e5565b505050565b6105f96127a8565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f518486290610836908390614159565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d2919061460b565b905090565b6108df6127b0565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff16614657565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6127a8565b610ba26127b0565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd261467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c3161467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf561467c565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d87816146ab565b9050610bb1565b5050565b610d9a612725565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec8284836144e5565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e609061444c565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea89061444c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed49061444c565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a8836146e3565b61295c565b90506110bf606083016040840161442f565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a088016147d0565b61111f6101608801610140890161442f565b61112988806147ed565b61113b6101208b016101008c01614852565b60208b01356111516101008d0160e08e0161486d565b8b6040516111679998979695949392919061488a565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16111d68a8a8a8a8a8a612dfa565b6003546000906002906111f49060ff80821691610100900416614932565b6111fe919061497a565b611209906001614932565b60ff169050878114611277576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b878614611306576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f7265706f727420727320616e64207373206d757374206265206f66206571756160448201527f6c206c656e6774680000000000000000000000000000000000000000000000006064820152608401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113495761134961499c565b600281111561135a5761135a61499c565b90525090506002816020015160028111156113775761137761499c565b141580156113c057506006816000015160ff168154811061139a5761139a61467c565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b15611427576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b505050506114336139de565b6000808a8a6040516114469291906149cb565b60405190819003812061145d918e906020016149db565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b898110156117675760006001848984602081106114c6576114c661467c565b6114d391901a601b614932565b8e8e868181106114e5576114e561467c565b905060200201358d8d878181106114fe576114fe61467c565b905060200201356040516000815260200160405260405161153b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561155d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff808216855292965092945084019161010090041660028111156115dd576115dd61499c565b60028111156115ee576115ee61499c565b905250925060018360200151600281111561160b5761160b61499c565b14611672576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061168c5761168c61467c565b602002015173ffffffffffffffffffffffffffffffffffffffff161461170e576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117285761172861467c565b73ffffffffffffffffffffffffffffffffffffffff9092166020929092020152611753600186614932565b94505080611760906146ab565b90506114a7565b505050611778833383858e8e612eb1565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b15801561182557600080fd5b505afa158015611839573d6000803e3d6000fd5b5050505066038d7ea4c6800082111561187e576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611888610841565b905060006118cb87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b90506118d985858385613122565b98975050505050505050565b6060600c80546118f49061444c565b905060000361192f576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea89061444c565b855185518560ff16601f8311156119af576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611a19576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611aa7576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611ab28160036149ef565b8311611b1a576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611b22612725565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611b69908861328f565b60055415611d1e57600554600090611b8390600190614a06565b9050600060058281548110611b9a57611b9a61467c565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611bd457611bd461467c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611c5457611c54614a19565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611cbd57611cbd614a19565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611b69915050565b60005b8151518110156122d557815180516000919083908110611d4357611d4361467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611dc8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f7369676e6572206d757374206e6f7420626520656d70747900000000000000006044820152606401610b0d565b600073ffffffffffffffffffffffffffffffffffffffff1682602001518281518110611df657611df661467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611e7b576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d7074790000006044820152606401610b0d565b60006004600084600001518481518110611e9757611e9761467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611ee157611ee161499c565b14611f48576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611f7957611f7961467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561201a5761201a61499c565b02179055506000915061202a9050565b60046000846020015184815181106120445761204461467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff16600281111561208e5761208e61499c565b146120f5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff8216815260208101600281525060046000846020015184815181106121285761212861467c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156121c9576121c961499c565b0217905550508251805160059250839081106121e7576121e761467c565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106122635761226361467c565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055806122cd816146ab565b915050611d21565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff438116820292909217808555920481169291829160149161238d91849174010000000000000000000000000000000000000000900416614a48565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123ec4630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a001516132a8565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986124a3988b9891977401000000000000000000000000000000000000000090920463ffffffff16969095919491939192614a65565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266a9190614b15565b50935050925050804261267d9190614a06565b836020015163ffffffff1610801561269f57506000836020015163ffffffff16115b156126cd57505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b6000821361270a576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b612719612725565b61272281613353565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146127a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6127a6612725565b600b546bffffffffffffffffffffffff166000036127ca57565b60006127d4610de2565b80519091506000819003612814576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b546000906128339083906bffffffffffffffffffffffff16614b65565b905060005b828110156128fe5781600a60008684815181106128575761285761467c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128bf9190614b90565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550806128f7906146ab565b9050612838565b506129098282614bb5565b600b80546000906129299084906bffffffffffffffffffffffff16614657565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612b17576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612b548560e001513a848860800151613122565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612bb0576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612bc99190614bdd565b905060003087604001518860a001518960c001516001612be99190614bf0565b8a5180516020918201206101008d015160e08e0151604051612c9d98979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612dac919061404e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612e078260206149ef565b612e128560206149ef565b612e1e88610144614bdd565b612e289190614bdd565b612e329190614bdd565b612e3d906000614bdd565b9050368114612ea8576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b606080808080612ec386880188614cec565b84519499509297509095509350915060ff16801580612ee3575084518114155b80612eef575083518114155b80612efb575082518114155b80612f07575081518114155b15612fe0576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152607060248201527f416c6c206669656c6473206f6e20746865207265706f7274206d75737420626560448201527f206f6620657175616c206c656e6774683a20726571756573744964732c20726560648201527f73756c74732c206572726f72732c206f6e636861696e4d657461646174612c2060848201527f6f6666636861696e4d657461646174610000000000000000000000000000000060a482015260c401610b0d565b60005b818110156131135760006130788883815181106130025761300261467c565b602002602001015188848151811061301c5761301c61467c565b60200260200101518885815181106130365761303661467c565b60200260200101518886815181106130505761305061467c565b602002602001015188878151811061306a5761306a61467c565b602002602001015188613448565b9050600081600681111561308e5761308e61499c565b14806130ab575060018160068111156130a9576130a961499c565b145b15613102578782815181106130c2576130c261467c565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b5061310c816146ab565b9050612fe3565b50505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561317d57600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b600854600090612710906131979063ffffffff16876149ef565b6131a19190614dbe565b6131ab9086614bdd565b60085490915060009087906131e49063ffffffff6c01000000000000000000000000820481169168010000000000000000900416614a48565b6131ee9190614a48565b63ffffffff16905060006132386000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061375c92505050565b905060006132598261324a85876149ef565b6132549190614bdd565b61389e565b9050600061327568ffffffffffffffffff808916908a16614b90565b90506132818183614b90565b9a9950505050505050505050565b6000613299610de2565b511115610d8e57610d8e6127b0565b6000808a8a8a8a8a8a8a8a8a6040516020016132cc99989796959493929190614dd2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036133d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000808480602001905181019061345f9190614e9e565b905060003a82610120015183610100015161347a9190614f66565b64ffffffffff1661348b91906149ef565b905060008460ff166134d36000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061375c92505050565b6134dd9190614dbe565b905060006134ee6132548385614bdd565b905060006134fb3a61389e565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff168961355a9190614b90565b338d6040518763ffffffff1660e01b815260040161357d96959493929190614f84565b60408051808303816000875af115801561359b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135bf9190615000565b909250905060008260068111156135d8576135d861499c565b14806135f5575060018260068111156135f3576135f361499c565b145b1561374b5760008e8152600760205260408120556136138185614b90565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161367f91859116614b90565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b6136fe9190614b90565b6137089190614b90565b6137129190614b90565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b600046613768816138d2565b156137e457606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137dd9190615033565b9392505050565b6137ed816138f5565b156138955773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e8460405180608001604052806048815260200161507c6048913960405160200161384d92919061504c565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016138789190613d13565b602060405180830381865afa1580156137b9573d6000803e3d6000fd5b50600092915050565b60006138cc6138ab6124b8565b6138bd84670de0b6b3a76400006149ef565b6138c79190614dbe565b61393c565b92915050565b600061a4b18214806138e6575062066eed82145b806138cc57505062066eee1490565b6000600a82148061390757506101a482145b80613914575062aa37dc82145b80613920575061210582145b8061392d575062014a3382145b806138cc57505062014a341490565b60006bffffffffffffffffffffffff8211156139da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f840112613a0f57600080fd5b50813567ffffffffffffffff811115613a2757600080fd5b602083019150836020828501011115613a3f57600080fd5b9250929050565b60008060208385031215613a5957600080fd5b823567ffffffffffffffff811115613a7057600080fd5b613a7c858286016139fd565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715613adb57613adb613a88565b60405290565b604051610160810167ffffffffffffffff81118282101715613adb57613adb613a88565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613b4c57613b4c613a88565b604052919050565b63ffffffff8116811461272257600080fd5b803561117081613b54565b68ffffffffffffffffff8116811461272257600080fd5b803561117081613b71565b64ffffffffff8116811461272257600080fd5b803561117081613b93565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613c0257600080fd5b613c0a613ab7565b613c1383613b66565b8152613c2160208401613b66565b6020820152613c3260408401613b66565b6040820152613c4360608401613b66565b6060820152613c5460808401613b88565b6080820152613c6560a08401613ba6565b60a0820152613c7660c08401613bb1565b60c0820152613c8760e08401613bc3565b60e0820152610100613c9a818501613b66565b908201529392505050565b60005b83811015613cc0578181015183820152602001613ca8565b50506000910152565b60008151808452613ce1816020860160208601613ca5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006137dd6020830184613cc9565b600082601f830112613d3757600080fd5b813567ffffffffffffffff811115613d5157613d51613a88565b613d8260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613b05565b818152846020838601011115613d9757600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613dc657600080fd5b813567ffffffffffffffff811115613ddd57600080fd5b613de984828501613d26565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461272257600080fd5b803561117081613df1565b6bffffffffffffffffffffffff8116811461272257600080fd5b803561117081613e1e565b60008060408385031215613e5657600080fd5b8235613e6181613df1565b91506020830135613e7181613e1e565b809150509250929050565b600081518084526020808501945080840160005b83811015613ec257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e90565b509495945050505050565b6020815260006137dd6020830184613e7c565b600060208284031215613ef257600080fd5b5035919050565b600060208284031215613f0b57600080fd5b813567ffffffffffffffff811115613f2257600080fd5b820161016081850312156137dd57600080fd5b805182526020810151613f60602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613f8060408401826bffffffffffffffffffffffff169052565b506060810151613fa8606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613fc4608084018267ffffffffffffffff169052565b5060a0810151613fdc60a084018263ffffffff169052565b5060c0810151613ff960c084018268ffffffffffffffffff169052565b5060e081015161401660e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b61016081016138cc8284613f35565b60008083601f84011261406f57600080fd5b50813567ffffffffffffffff81111561408757600080fd5b6020830191508360208260051b8501011115613a3f57600080fd5b60008060008060008060008060e0898b0312156140be57600080fd5b606089018a8111156140cf57600080fd5b8998503567ffffffffffffffff808211156140e957600080fd5b6140f58c838d016139fd565b909950975060808b013591508082111561410e57600080fd5b61411a8c838d0161405d565b909750955060a08b013591508082111561413357600080fd5b506141408b828c0161405d565b999c989b50969995989497949560c00135949350505050565b815163ffffffff9081168252602080840151821690830152604080840151821690830152606080840151918216908301526101208201905060808301516141ad608084018268ffffffffffffffffff169052565b5060a08301516141c660a084018264ffffffffff169052565b5060c08301516141dc60c084018261ffff169052565b5060e083015161420c60e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461272257600080fd5b803561117081614228565b60008060008060006080868803121561426157600080fd5b853561426c81614228565b9450602086013567ffffffffffffffff81111561428857600080fd5b614294888289016139fd565b90955093505060408601356142a881613b54565b949793965091946060013592915050565b600067ffffffffffffffff8211156142d3576142d3613a88565b5060051b60200190565b600082601f8301126142ee57600080fd5b813560206143036142fe836142b9565b613b05565b82815260059290921b8401810191818101908684111561432257600080fd5b8286015b8481101561434657803561433981613df1565b8352918301918301614326565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561437b57600080fd5b863567ffffffffffffffff8082111561439357600080fd5b61439f8a838b016142dd565b975060208901359150808211156143b557600080fd5b6143c18a838b016142dd565b96506143cf60408a01614351565b955060608901359150808211156143e557600080fd5b6143f18a838b01613d26565b94506143ff60808a0161423e565b935060a089013591508082111561441557600080fd5b5061442289828a01613d26565b9150509295509295509295565b60006020828403121561444157600080fd5b81356137dd81613df1565b600181811c9082168061446057607f821691505b602082108103614499577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c810160208610156144c65750805b601f850160051c820191505b81811015610a88578281556001016144d2565b67ffffffffffffffff8311156144fd576144fd613a88565b6145118361450b835461444c565b8361449f565b6000601f841160018114614563576000851561452d5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556145f9565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156145b25786850135825560209485019460019092019101614592565b50868210156145ed577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613b71565b60006020828403121561461d57600080fd5b81516137dd81613b71565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff82811682821603908082111561270a5761270a614628565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146dc576146dc614628565b5060010190565b600061016082360312156146f657600080fd5b6146fe613ae1565b823567ffffffffffffffff81111561471557600080fd5b61472136828601613d26565b8252506020830135602082015261473a60408401613e13565b604082015261474b60608401613e38565b606082015261475c60808401613b88565b608082015261476d60a0840161423e565b60a082015261477e60c0840161423e565b60c082015261478f60e08401613b66565b60e08201526101006147a2818501613bb1565b908201526101206147b484820161423e565b908201526101406147c6848201613e13565b9082015292915050565b6000602082840312156147e257600080fd5b81356137dd81614228565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261482257600080fd5b83018035915067ffffffffffffffff82111561483d57600080fd5b602001915036819003821315613a3f57600080fd5b60006020828403121561486457600080fd5b6137dd82613bb1565b60006020828403121561487f57600080fd5b81356137dd81613b54565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061328160e0830184613f35565b60ff81811683821601908111156138cc576138cc614628565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061498d5761498d61494b565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b80820281158282048414176138cc576138cc614628565b818103818111156138cc576138cc614628565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff81811683821601908082111561270a5761270a614628565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a958184018a613e7c565b90508281036080840152614aa98189613e7c565b905060ff871660a084015282810360c0840152614ac68187613cc9565b905067ffffffffffffffff851660e0840152828103610100840152614aeb8185613cc9565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a08688031215614b2d57600080fd5b614b3686614afb565b9450602086015193506040860151925060608601519150614b5960808701614afb565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614b8457614b8461494b565b92169190910492915050565b6bffffffffffffffffffffffff81811683821601908082111561270a5761270a614628565b6bffffffffffffffffffffffff81811683821602808216919082811461422057614220614628565b808201808211156138cc576138cc614628565b67ffffffffffffffff81811683821601908082111561270a5761270a614628565b600082601f830112614c2257600080fd5b81356020614c326142fe836142b9565b82815260059290921b84018101918181019086841115614c5157600080fd5b8286015b848110156143465780358352918301918301614c55565b600082601f830112614c7d57600080fd5b81356020614c8d6142fe836142b9565b82815260059290921b84018101918181019086841115614cac57600080fd5b8286015b8481101561434657803567ffffffffffffffff811115614cd05760008081fd5b614cde8986838b0101613d26565b845250918301918301614cb0565b600080600080600060a08688031215614d0457600080fd5b853567ffffffffffffffff80821115614d1c57600080fd5b614d2889838a01614c11565b96506020880135915080821115614d3e57600080fd5b614d4a89838a01614c6c565b95506040880135915080821115614d6057600080fd5b614d6c89838a01614c6c565b94506060880135915080821115614d8257600080fd5b614d8e89838a01614c6c565b93506080880135915080821115614da457600080fd5b50614db188828901614c6c565b9150509295509295909350565b600082614dcd57614dcd61494b565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614e198285018b613e7c565b91508382036080850152614e2d828a613e7c565b915060ff881660a085015283820360c0850152614e4a8288613cc9565b90861660e08501528381036101008501529050614aeb8185613cc9565b805161117081613df1565b805161117081613e1e565b805161117081614228565b805161117081613b54565b805161117081613b93565b60006101608284031215614eb157600080fd5b614eb9613ae1565b82518152614ec960208401614e67565b6020820152614eda60408401614e72565b6040820152614eeb60608401614e67565b6060820152614efc60808401614e7d565b6080820152614f0d60a08401614e88565b60a0820152614f1e60c08401614600565b60c0820152614f2f60e08401614600565b60e0820152610100614f42818501614e93565b90820152610120614f54848201614e93565b90820152610140613c9a848201614e88565b64ffffffffff81811683821601908082111561270a5761270a614628565b6000610200808352614f988184018a613cc9565b90508281036020840152614fac8189613cc9565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614ff5905060a0830184613f35565b979650505050505050565b6000806040838503121561501357600080fd5b82516007811061502257600080fd5b6020840151909250613e7181613e1e565b60006020828403121561504557600080fd5b5051919050565b6000835161505e818460208801613ca5565b835190830190615072818360208801613ca5565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
+ Bin: "0x60a06040523480156200001157600080fd5b50604051620056d0380380620056d083398101604081905262000034916200046d565b8282828233806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c28162000139565b5050506001600160a01b038116620000ed57604051632530e88560e11b815260040160405180910390fd5b6001600160a01b03908116608052600b80549183166c01000000000000000000000000026001600160601b039092169190911790556200012d82620001e4565b5050505050506200062c565b336001600160a01b03821603620001935760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee62000342565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff16600160f01b026001600160f01b0364ffffffffff909216600160c81b0264ffffffffff60c81b196001600160481b03909416600160801b0293909316600160801b600160f01b031963ffffffff9586166c010000000000000000000000000263ffffffff60601b19978716680100000000000000000297909716600160401b600160801b0319998716640100000000026001600160401b0319909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e0830151610100840151909216600160e01b026001600160e01b0390921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906200033790839062000576565b60405180910390a150565b6200034c6200034e565b565b6000546001600160a01b031633146200034c5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000086565b80516001600160a01b0381168114620003c257600080fd5b919050565b60405161012081016001600160401b0381118282101715620003f957634e487b7160e01b600052604160045260246000fd5b60405290565b805163ffffffff81168114620003c257600080fd5b80516001600160481b0381168114620003c257600080fd5b805164ffffffffff81168114620003c257600080fd5b805161ffff81168114620003c257600080fd5b80516001600160e01b0381168114620003c257600080fd5b60008060008385036101608112156200048557600080fd5b6200049085620003aa565b935061012080601f1983011215620004a757600080fd5b620004b1620003c7565b9150620004c160208701620003ff565b8252620004d160408701620003ff565b6020830152620004e460608701620003ff565b6040830152620004f760808701620003ff565b60608301526200050a60a0870162000414565b60808301526200051d60c087016200042c565b60a08301526200053060e0870162000442565b60c08301526101006200054581880162000455565b60e084015262000557828801620003ff565b908301525091506200056d6101408501620003aa565b90509250925092565b815163ffffffff908116825260208084015182169083015260408084015182169083015260608084015191821690830152610120820190506080830151620005c960808401826001600160481b03169052565b5060a0830151620005e360a084018264ffffffffff169052565b5060c0830151620005fa60c084018261ffff169052565b5060e08301516200061660e08401826001600160e01b03169052565b506101009283015163ffffffff16919092015290565b60805161505e6200067260003960008181610845015281816109d301528181610ca601528181610f3a01528181611045015281816117890152613490015261505e6000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806381ff7048116100e3578063c3f909d41161008c578063e3d0e71211610066578063e3d0e71214610560578063e4ddcea614610573578063f2fde38b1461058957600080fd5b8063c3f909d4146103b0578063d227d24514610528578063d328a91e1461055857600080fd5b8063a631571e116100bd578063a631571e1461035d578063afcb95d71461037d578063b1dc65a41461039d57600080fd5b806381ff7048146102b557806385b214cf146103225780638da5cb5b1461033557600080fd5b806366316d8d116101455780637f15e1661161011f5780637f15e16614610285578063814118341461029857806381f1b938146102ad57600080fd5b806366316d8d1461026257806379ba5097146102755780637d4807871461027d57600080fd5b8063181f5a7711610176578063181f5a77146101ba5780632a905ccc1461020c57806359b5b7ac1461022e57600080fd5b8063083a5466146101925780631112dadc146101a7575b600080fd5b6101a56101a03660046139d4565b61059c565b005b6101a56101b5366004613b7d565b6105f1565b6101f66040518060400160405280601c81526020017f46756e6374696f6e7320436f6f7264696e61746f722076312e312e300000000081525081565b6040516102039190613ca1565b60405180910390f35b610214610841565b60405168ffffffffffffffffff9091168152602001610203565b61021461023c366004613d42565b50600854700100000000000000000000000000000000900468ffffffffffffffffff1690565b6101a5610270366004613dd1565b6108d7565b6101a5610a90565b6101a5610b92565b6101a56102933660046139d4565b610d92565b6102a0610de2565b6040516102039190613e5b565b6101f6610e51565b6102ff60015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610203565b6101a5610330366004613e6e565b610f22565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b61037061036b366004613e87565b610fd4565b6040516102039190613fdc565b604080516001815260006020820181905291810191909152606001610203565b6101a56103ab366004614030565b611175565b61051b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830152700100000000000000000000000000000000810468ffffffffffffffffff166080830152790100000000000000000000000000000000000000000000000000810464ffffffffff1660a08301527e01000000000000000000000000000000000000000000000000000000000000900461ffff1660c08201526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08301527c0100000000000000000000000000000000000000000000000000000000900490911661010082015290565b60405161020391906140e7565b61053b6105363660046141d7565b611785565b6040516bffffffffffffffffffffffff9091168152602001610203565b6101f66118e5565b6101a561056e3660046142f0565b61193c565b61057b6124b8565b604051908152602001610203565b6101a56105973660046143bd565b612711565b6105a4612725565b60008190036105df576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d6105ec828483614473565b505050565b6105f96127a8565b80516008805460208401516040808601516060870151608088015160a089015160c08a015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff909216790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff68ffffffffffffffffff90941670010000000000000000000000000000000002939093167fffff0000000000000000000000000000ffffffffffffffffffffffffffffffff63ffffffff9586166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff9787166801000000000000000002979097167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff998716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b169c87169c909c1799909917979097169990991793909317959095169390931793909317929092169390931790915560e08301516101008401519092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117600955517f5f32d06f5e83eda3a68e0e964ef2e6af5cb613e8117aa103c2d6bca5f5184862906108369083906140e7565b60405180910390a150565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a905ccc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d29190614599565b905090565b6108df6127b0565b806bffffffffffffffffffffffff166000036109195750336000908152600a60205260409020546bffffffffffffffffffffffff16610973565b336000908152600a60205260409020546bffffffffffffffffffffffff80831691161015610973576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600a6020526040812080548392906109a09084906bffffffffffffffffffffffff166145e5565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506109f57f000000000000000000000000000000000000000000000000000000000000000090565b6040517f66316d8d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526bffffffffffffffffffffffff8416602483015291909116906366316d8d90604401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b9a6127a8565b610ba26127b0565b6000610bac610de2565b905060005b8151811015610d8e576000600a6000848481518110610bd257610bd261460a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020546bffffffffffffffffffffffff1690508015610d7d576000600a6000858581518110610c3157610c3161460a565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550610cc87f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166366316d8d848481518110610cf557610cf561460a565b6020026020010151836040518363ffffffff1660e01b8152600401610d4a92919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b600060405180830381600087803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b505050505b50610d8781614639565b9050610bb1565b5050565b610d9a612725565b6000819003610dd5576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c6105ec828483614473565b60606006805480602002602001604051908101604052809291908181526020018280548015610e4757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e1c575b5050505050905090565b6060600d8054610e60906143da565b9050600003610e9b576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d8054610ea8906143da565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed4906143da565b8015610e475780601f10610ef657610100808354040283529160200191610e47565b820191906000526020600020905b815481529060010190602001808311610f0457509395945050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f91576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604080822091909155517f8a4b97add3359bd6bcf5e82874363670eb5ad0f7615abddbd0ed0a3a98f0f416906108369083815260200190565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091523373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461109c576040517fc41a5b0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110ad6110a883614671565b61295c565b90506110bf60608301604084016143bd565b815173ffffffffffffffffffffffffffffffffffffffff91909116907fbf50768ccf13bd0110ca6d53a9c4f1f3271abdd4c24a56878863ed25b20598ff3261110d60c0870160a0880161475e565b61111f610160880161014089016143bd565b611129888061477b565b61113b6101208b016101008c016147e0565b60208b01356111516101008d0160e08e016147fb565b8b60405161116799989796959493929190614818565b60405180910390a35b919050565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16111d68a8a8a8a8a8a612dfa565b6003546000906002906111f49060ff808216916101009004166148c0565b6111fe9190614908565b6112099060016148c0565b60ff169050878114611277576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610b0d565b878614611306576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f7265706f727420727320616e64207373206d757374206265206f66206571756160448201527f6c206c656e6774680000000000000000000000000000000000000000000000006064820152608401610b0d565b3360009081526004602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156113495761134961492a565b600281111561135a5761135a61492a565b90525090506002816020015160028111156113775761137761492a565b141580156113c057506006816000015160ff168154811061139a5761139a61460a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b15611427576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610b0d565b5050505061143361396c565b6000808a8a604051611446929190614959565b60405190819003812061145d918e90602001614969565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b898110156117675760006001848984602081106114c6576114c661460a565b6114d391901a601b6148c0565b8e8e868181106114e5576114e561460a565b905060200201358d8d878181106114fe576114fe61460a565b905060200201356040516000815260200160405260405161153b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561155d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff808216855292965092945084019161010090041660028111156115dd576115dd61492a565b60028111156115ee576115ee61492a565b905250925060018360200151600281111561160b5761160b61492a565b14611672576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e00006044820152606401610b0d565b8251600090879060ff16601f811061168c5761168c61460a565b602002015173ffffffffffffffffffffffffffffffffffffffff161461170e576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e61747572650000000000000000000000006044820152606401610b0d565b8086846000015160ff16601f81106117285761172861460a565b73ffffffffffffffffffffffffffffffffffffffff90921660209290920201526117536001866148c0565b9450508061176090614639565b90506114a7565b505050611778833383858e8e612eb1565b5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006040517f10fc49c100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015263ffffffff8516602482015273ffffffffffffffffffffffffffffffffffffffff91909116906310fc49c19060440160006040518083038186803b15801561182557600080fd5b505afa158015611839573d6000803e3d6000fd5b5050505066038d7ea4c6800082111561187e576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611888610841565b905060006118cb87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061023c92505050565b90506118d9858583856130b0565b98975050505050505050565b6060600c80546118f4906143da565b905060000361192f576040517f4f42be3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8054610ea8906143da565b855185518560ff16601f8311156119af576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610b0d565b80600003611a19576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610b0d565b818314611aa7576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610b0d565b611ab281600361497d565b8311611b1a576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610b0d565b611b22612725565b6040805160c0810182528a8152602081018a905260ff89169181018290526060810188905267ffffffffffffffff8716608082015260a0810186905290611b69908861321d565b60055415611d1e57600554600090611b8390600190614994565b9050600060058281548110611b9a57611b9a61460a565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110611bd457611bd461460a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080611c5457611c546149a7565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480611cbd57611cbd6149a7565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611b69915050565b60005b8151518110156122d557815180516000919083908110611d4357611d4361460a565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611dc8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f7369676e6572206d757374206e6f7420626520656d70747900000000000000006044820152606401610b0d565b600073ffffffffffffffffffffffffffffffffffffffff1682602001518281518110611df657611df661460a565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611e7b576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d7074790000006044820152606401610b0d565b60006004600084600001518481518110611e9757611e9761460a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115611ee157611ee161492a565b14611f48576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610b0d565b6040805180820190915260ff82168152600160208201528251805160049160009185908110611f7957611f7961460a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561201a5761201a61492a565b02179055506000915061202a9050565b60046000846020015184815181106120445761204461460a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff16600281111561208e5761208e61492a565b146120f5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610b0d565b6040805180820190915260ff8216815260208101600281525060046000846020015184815181106121285761212861460a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156121c9576121c961492a565b0217905550508251805160059250839081106121e7576121e761460a565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217909155820151805160069190839081106122635761226361460a565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055806122cd81614639565b915050611d21565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff438116820292909217808555920481169291829160149161238d918491740100000000000000000000000000000000000000009004166149d6565b92506101000a81548163ffffffff021916908363ffffffff1602179055506123ec4630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a00151613236565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986124a3988b9891977401000000000000000000000000000000000000000090920463ffffffff169690959194919391926149f3565b60405180910390a15050505050505050505050565b604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000080830482166060850152700100000000000000000000000000000000830468ffffffffffffffffff166080850152790100000000000000000000000000000000000000000000000000830464ffffffffff1660a0808601919091527e0100000000000000000000000000000000000000000000000000000000000090930461ffff1660c08501526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08601527c01000000000000000000000000000000000000000000000000000000009004909116610100840152600b5484517ffeaf968c00000000000000000000000000000000000000000000000000000000815294516000958694859490930473ffffffffffffffffffffffffffffffffffffffff169263feaf968c926004808401938290030181865afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266a9190614aa3565b50935050925050804261267d9190614994565b836020015163ffffffff1610801561269f57506000836020015163ffffffff16115b156126cd57505060e001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16919050565b6000821361270a576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610b0d565b5092915050565b612719612725565b612722816132e1565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146127a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b0d565b565b6127a6612725565b600b546bffffffffffffffffffffffff166000036127ca57565b60006127d4610de2565b80519091506000819003612814576040517f30274b3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b546000906128339083906bffffffffffffffffffffffff16614af3565b905060005b828110156128fe5781600a60008684815181106128575761285761460a565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046bffffffffffffffffffffffff166128bf9190614b1e565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550806128f790614639565b9050612838565b506129098282614b43565b600b80546000906129299084906bffffffffffffffffffffffff166145e5565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152604080516101208101825260085463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c0100000000000000000000000081048316606083015268ffffffffffffffffff700100000000000000000000000000000000820416608083015264ffffffffff79010000000000000000000000000000000000000000000000000082041660a083015261ffff7e01000000000000000000000000000000000000000000000000000000000000909104811660c083018190526009547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660e08501527c0100000000000000000000000000000000000000000000000000000000900490931661010080840191909152850151919291161115612b17576040517fdada758700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854600090700100000000000000000000000000000000900468ffffffffffffffffff1690506000612b548560e001513a8488608001516130b0565b9050806bffffffffffffffffffffffff1685606001516bffffffffffffffffffffffff161015612bb0576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083610100015163ffffffff1642612bc99190614b6b565b905060003087604001518860a001518960c001516001612be99190614b7e565b8a5180516020918201206101008d015160e08e0151604051612c9d98979695948c918c9132910173ffffffffffffffffffffffffffffffffffffffff9a8b168152988a1660208a015267ffffffffffffffff97881660408a0152959096166060880152608087019390935261ffff9190911660a086015263ffffffff90811660c08601526bffffffffffffffffffffffff9190911660e0850152919091166101008301529091166101208201526101400190565b6040516020818303038152906040528051906020012090506040518061016001604052808281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001846bffffffffffffffffffffffff168152602001886040015173ffffffffffffffffffffffffffffffffffffffff1681526020018860a0015167ffffffffffffffff1681526020018860e0015163ffffffff168152602001886080015168ffffffffffffffffff1681526020018568ffffffffffffffffff168152602001866040015163ffffffff1664ffffffffff168152602001866060015163ffffffff1664ffffffffff1681526020018363ffffffff16815250955085604051602001612dac9190613fdc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009384526007909252909120555092949350505050565b6000612e0782602061497d565b612e1285602061497d565b612e1e88610144614b6b565b612e289190614b6b565b612e329190614b6b565b612e3d906000614b6b565b9050368114612ea8576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610b0d565b50505050505050565b600080808080612ec386880188614c7a565b84519499509297509095509350915060ff16801580612ee3575084518114155b80612eef575083518114155b80612efb575082518114155b80612f07575081518114155b15612f6e576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4669656c6473206d75737420626520657175616c206c656e67746800000000006044820152606401610b0d565b60005b818110156130a1576000613006888381518110612f9057612f9061460a565b6020026020010151888481518110612faa57612faa61460a565b6020026020010151888581518110612fc457612fc461460a565b6020026020010151888681518110612fde57612fde61460a565b6020026020010151888781518110612ff857612ff861460a565b6020026020010151886133d6565b9050600081600681111561301c5761301c61492a565b1480613039575060018160068111156130375761303761492a565b145b15613090578782815181106130505761305061460a565b60209081029190910181015160405133815290917fc708e0440951fd63499c0f7a73819b469ee5dd3ecc356c0ab4eb7f18389009d9910160405180910390a25b5061309a81614639565b9050612f71565b50505050505050505050505050565b600854600090790100000000000000000000000000000000000000000000000000900464ffffffffff1684101561310b57600854790100000000000000000000000000000000000000000000000000900464ffffffffff1693505b600854600090612710906131259063ffffffff168761497d565b61312f9190614d4c565b6131399086614b6b565b60085490915060009087906131729063ffffffff6c010000000000000000000000008204811691680100000000000000009004166149d6565b61317c91906149d6565b63ffffffff16905060006131c66000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506136ea92505050565b905060006131e7826131d8858761497d565b6131e29190614b6b565b61382c565b9050600061320368ffffffffffffffffff808916908a16614b1e565b905061320f8183614b1e565b9a9950505050505050505050565b6000613227610de2565b511115610d8e57610d8e6127b0565b6000808a8a8a8a8a8a8a8a8a60405160200161325a99989796959493929190614d60565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b0d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080848060200190518101906133ed9190614e2c565b905060003a8261012001518361010001516134089190614ef4565b64ffffffffff16613419919061497d565b905060008460ff166134616000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506136ea92505050565b61346b9190614d4c565b9050600061347c6131e28385614b6b565b905060006134893a61382c565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663330605298e8e868b60e0015168ffffffffffffffffff16896134e89190614b1e565b338d6040518763ffffffff1660e01b815260040161350b96959493929190614f12565b60408051808303816000875af1158015613529573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061354d9190614f8e565b909250905060008260068111156135665761356661492a565b1480613583575060018260068111156135815761358161492a565b145b156136d95760008e8152600760205260408120556135a18185614b1e565b336000908152600a6020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff93841617905560e0890151600b805468ffffffffffffffffff9092169390929161360d91859116614b1e565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508d7f90815c2e624694e8010bffad2bcefaf96af282ef1bc2ebc0042d1b89a585e0468487848b60c0015168ffffffffffffffffff168c60e0015168ffffffffffffffffff16878b61368c9190614b1e565b6136969190614b1e565b6136a09190614b1e565b604080516bffffffffffffffffffffffff9586168152602081019490945291841683830152909216606082015290519081900360800190a25b509c9b505050505050505050505050565b6000466136f681613860565b1561377257606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376b9190614fc1565b9392505050565b61377b81613883565b156138235773420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e8460405180608001604052806048815260200161500a604891396040516020016137db929190614fda565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016138069190613ca1565b602060405180830381865afa158015613747573d6000803e3d6000fd5b50600092915050565b600061385a6138396124b8565b61384b84670de0b6b3a764000061497d565b6138559190614d4c565b6138ca565b92915050565b600061a4b1821480613874575062066eed82145b8061385a57505062066eee1490565b6000600a82148061389557506101a482145b806138a2575062aa37dc82145b806138ae575061210582145b806138bb575062014a3382145b8061385a57505062014a341490565b60006bffffffffffffffffffffffff821115613968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b0d565b5090565b604051806103e00160405280601f906020820280368337509192915050565b60008083601f84011261399d57600080fd5b50813567ffffffffffffffff8111156139b557600080fd5b6020830191508360208285010111156139cd57600080fd5b9250929050565b600080602083850312156139e757600080fd5b823567ffffffffffffffff8111156139fe57600080fd5b613a0a8582860161398b565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715613a6957613a69613a16565b60405290565b604051610160810167ffffffffffffffff81118282101715613a6957613a69613a16565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613ada57613ada613a16565b604052919050565b63ffffffff8116811461272257600080fd5b803561117081613ae2565b68ffffffffffffffffff8116811461272257600080fd5b803561117081613aff565b64ffffffffff8116811461272257600080fd5b803561117081613b21565b803561ffff8116811461117057600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117057600080fd5b60006101208284031215613b9057600080fd5b613b98613a45565b613ba183613af4565b8152613baf60208401613af4565b6020820152613bc060408401613af4565b6040820152613bd160608401613af4565b6060820152613be260808401613b16565b6080820152613bf360a08401613b34565b60a0820152613c0460c08401613b3f565b60c0820152613c1560e08401613b51565b60e0820152610100613c28818501613af4565b908201529392505050565b60005b83811015613c4e578181015183820152602001613c36565b50506000910152565b60008151808452613c6f816020860160208601613c33565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061376b6020830184613c57565b600082601f830112613cc557600080fd5b813567ffffffffffffffff811115613cdf57613cdf613a16565b613d1060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613a93565b818152846020838601011115613d2557600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613d5457600080fd5b813567ffffffffffffffff811115613d6b57600080fd5b613d7784828501613cb4565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461272257600080fd5b803561117081613d7f565b6bffffffffffffffffffffffff8116811461272257600080fd5b803561117081613dac565b60008060408385031215613de457600080fd5b8235613def81613d7f565b91506020830135613dff81613dac565b809150509250929050565b600081518084526020808501945080840160005b83811015613e5057815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e1e565b509495945050505050565b60208152600061376b6020830184613e0a565b600060208284031215613e8057600080fd5b5035919050565b600060208284031215613e9957600080fd5b813567ffffffffffffffff811115613eb057600080fd5b8201610160818503121561376b57600080fd5b805182526020810151613eee602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613f0e60408401826bffffffffffffffffffffffff169052565b506060810151613f36606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080810151613f52608084018267ffffffffffffffff169052565b5060a0810151613f6a60a084018263ffffffff169052565b5060c0810151613f8760c084018268ffffffffffffffffff169052565b5060e0810151613fa460e084018268ffffffffffffffffff169052565b506101008181015164ffffffffff9081169184019190915261012080830151909116908301526101409081015163ffffffff16910152565b610160810161385a8284613ec3565b60008083601f840112613ffd57600080fd5b50813567ffffffffffffffff81111561401557600080fd5b6020830191508360208260051b85010111156139cd57600080fd5b60008060008060008060008060e0898b03121561404c57600080fd5b606089018a81111561405d57600080fd5b8998503567ffffffffffffffff8082111561407757600080fd5b6140838c838d0161398b565b909950975060808b013591508082111561409c57600080fd5b6140a88c838d01613feb565b909750955060a08b01359150808211156140c157600080fd5b506140ce8b828c01613feb565b999c989b50969995989497949560c00135949350505050565b815163ffffffff90811682526020808401518216908301526040808401518216908301526060808401519182169083015261012082019050608083015161413b608084018268ffffffffffffffffff169052565b5060a083015161415460a084018264ffffffffff169052565b5060c083015161416a60c084018261ffff169052565b5060e083015161419a60e08401827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169052565b506101008381015163ffffffff8116848301525b505092915050565b67ffffffffffffffff8116811461272257600080fd5b8035611170816141b6565b6000806000806000608086880312156141ef57600080fd5b85356141fa816141b6565b9450602086013567ffffffffffffffff81111561421657600080fd5b6142228882890161398b565b909550935050604086013561423681613ae2565b949793965091946060013592915050565b600067ffffffffffffffff82111561426157614261613a16565b5060051b60200190565b600082601f83011261427c57600080fd5b8135602061429161428c83614247565b613a93565b82815260059290921b840181019181810190868411156142b057600080fd5b8286015b848110156142d45780356142c781613d7f565b83529183019183016142b4565b509695505050505050565b803560ff8116811461117057600080fd5b60008060008060008060c0878903121561430957600080fd5b863567ffffffffffffffff8082111561432157600080fd5b61432d8a838b0161426b565b9750602089013591508082111561434357600080fd5b61434f8a838b0161426b565b965061435d60408a016142df565b9550606089013591508082111561437357600080fd5b61437f8a838b01613cb4565b945061438d60808a016141cc565b935060a08901359150808211156143a357600080fd5b506143b089828a01613cb4565b9150509295509295509295565b6000602082840312156143cf57600080fd5b813561376b81613d7f565b600181811c908216806143ee57607f821691505b602082108103614427577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105ec57600081815260208120601f850160051c810160208610156144545750805b601f850160051c820191505b81811015610a8857828155600101614460565b67ffffffffffffffff83111561448b5761448b613a16565b61449f8361449983546143da565b8361442d565b6000601f8411600181146144f157600085156144bb5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614587565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156145405786850135825560209485019460019092019101614520565b508682101561457b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b805161117081613aff565b6000602082840312156145ab57600080fd5b815161376b81613aff565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff82811682821603908082111561270a5761270a6145b6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361466a5761466a6145b6565b5060010190565b6000610160823603121561468457600080fd5b61468c613a6f565b823567ffffffffffffffff8111156146a357600080fd5b6146af36828601613cb4565b825250602083013560208201526146c860408401613da1565b60408201526146d960608401613dc6565b60608201526146ea60808401613b16565b60808201526146fb60a084016141cc565b60a082015261470c60c084016141cc565b60c082015261471d60e08401613af4565b60e0820152610100614730818501613b3f565b908201526101206147428482016141cc565b90820152610140614754848201613da1565b9082015292915050565b60006020828403121561477057600080fd5b813561376b816141b6565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126147b057600080fd5b83018035915067ffffffffffffffff8211156147cb57600080fd5b6020019150368190038213156139cd57600080fd5b6000602082840312156147f257600080fd5b61376b82613b3f565b60006020828403121561480d57600080fd5b813561376b81613ae2565b73ffffffffffffffffffffffffffffffffffffffff8a8116825267ffffffffffffffff8a166020830152881660408201526102406060820181905281018690526000610260878982850137600083890182015261ffff8716608084015260a0830186905263ffffffff851660c0840152601f88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016830101905061320f60e0830184613ec3565b60ff818116838216019081111561385a5761385a6145b6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061491b5761491b6148d9565b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b808202811582820484141761385a5761385a6145b6565b8181038181111561385a5761385a6145b6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff81811683821601908082111561270a5761270a6145b6565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a238184018a613e0a565b90508281036080840152614a378189613e0a565b905060ff871660a084015282810360c0840152614a548187613c57565b905067ffffffffffffffff851660e0840152828103610100840152614a798185613c57565b9c9b505050505050505050505050565b805169ffffffffffffffffffff8116811461117057600080fd5b600080600080600060a08688031215614abb57600080fd5b614ac486614a89565b9450602086015193506040860151925060608601519150614ae760808701614a89565b90509295509295909350565b60006bffffffffffffffffffffffff80841680614b1257614b126148d9565b92169190910492915050565b6bffffffffffffffffffffffff81811683821601908082111561270a5761270a6145b6565b6bffffffffffffffffffffffff8181168382160280821691908281146141ae576141ae6145b6565b8082018082111561385a5761385a6145b6565b67ffffffffffffffff81811683821601908082111561270a5761270a6145b6565b600082601f830112614bb057600080fd5b81356020614bc061428c83614247565b82815260059290921b84018101918181019086841115614bdf57600080fd5b8286015b848110156142d45780358352918301918301614be3565b600082601f830112614c0b57600080fd5b81356020614c1b61428c83614247565b82815260059290921b84018101918181019086841115614c3a57600080fd5b8286015b848110156142d457803567ffffffffffffffff811115614c5e5760008081fd5b614c6c8986838b0101613cb4565b845250918301918301614c3e565b600080600080600060a08688031215614c9257600080fd5b853567ffffffffffffffff80821115614caa57600080fd5b614cb689838a01614b9f565b96506020880135915080821115614ccc57600080fd5b614cd889838a01614bfa565b95506040880135915080821115614cee57600080fd5b614cfa89838a01614bfa565b94506060880135915080821115614d1057600080fd5b614d1c89838a01614bfa565b93506080880135915080821115614d3257600080fd5b50614d3f88828901614bfa565b9150509295509295909350565b600082614d5b57614d5b6148d9565b500490565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614da78285018b613e0a565b91508382036080850152614dbb828a613e0a565b915060ff881660a085015283820360c0850152614dd88288613c57565b90861660e08501528381036101008501529050614a798185613c57565b805161117081613d7f565b805161117081613dac565b8051611170816141b6565b805161117081613ae2565b805161117081613b21565b60006101608284031215614e3f57600080fd5b614e47613a6f565b82518152614e5760208401614df5565b6020820152614e6860408401614e00565b6040820152614e7960608401614df5565b6060820152614e8a60808401614e0b565b6080820152614e9b60a08401614e16565b60a0820152614eac60c0840161458e565b60c0820152614ebd60e0840161458e565b60e0820152610100614ed0818501614e21565b90820152610120614ee2848201614e21565b90820152610140613c28848201614e16565b64ffffffffff81811683821601908082111561270a5761270a6145b6565b6000610200808352614f268184018a613c57565b90508281036020840152614f3a8189613c57565b6bffffffffffffffffffffffff88811660408601528716606085015273ffffffffffffffffffffffffffffffffffffffff861660808501529150614f83905060a0830184613ec3565b979650505050505050565b60008060408385031215614fa157600080fd5b825160078110614fb057600080fd5b6020840151909250613dff81613dac565b600060208284031215614fd357600080fd5b5051919050565b60008351614fec818460208801613c33565b835190830190615000818360208801613c33565b0194935050505056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a",
}
var FunctionsCoordinatorABI = FunctionsCoordinatorMetaData.ABI
diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 93c4e64a3a..ac1fc4e83d 100644
--- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -4,7 +4,7 @@ functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServ
functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77
functions_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca
functions_client_example: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.bin abf32e69f268f40e8530eb8d8e96bf310b798a4c0049a58022d9d2fb527b601b
-functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 4e05ca5e624b7a1e604b81b84bc088818b376d533f556ba1c2ee586b7eb38b68
+functions_coordinator: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsCoordinator.bin 97aa7c56d78c703056990eff102279af86b97b11b5855b059e8dd658dc15da8a
functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsLoadTestClient.bin c8dbbd5ebb34435800d6674700068837c3a252db60046a14b0e61e829db517de
functions_oracle_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c
functions_router: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRouter.bin 9dedd3a36043605fd9bedf821e7ec5b4281a5c7ae2e4a1955f37aff8ba13519f
From aa0223133f392f0f02b4e1e563347ad4b3a58afc Mon Sep 17 00:00:00 2001
From: amit-momin <108959691+amit-momin@users.noreply.github.com>
Date: Mon, 13 Nov 2023 14:15:46 -0600
Subject: [PATCH 140/327] Decouple job pipeline tables from the TXM DB (#11173)
* Decoupled job pipeline tables from the TXM DB
* Updated errors to return better context
* Updated method comment
---
common/txmgr/broadcaster.go | 7 +-
common/txmgr/confirmer.go | 6 +-
common/txmgr/types/mocks/tx_store.go | 66 ++++++++------
common/txmgr/types/tx.go | 8 ++
common/txmgr/types/tx_store.go | 8 +-
core/chains/evm/txmgr/broadcaster_test.go | 1 +
core/chains/evm/txmgr/confirmer_test.go | 48 +++++++++--
core/chains/evm/txmgr/evm_tx_store.go | 47 +++++++---
core/chains/evm/txmgr/evm_tx_store_test.go | 85 ++++++++++++++++---
core/chains/evm/txmgr/mocks/evm_tx_store.go | 66 ++++++++------
core/services/pipeline/orm.go | 6 +-
core/services/pipeline/runner.go | 2 +-
core/services/pipeline/task.eth_tx.go | 1 +
core/services/pipeline/task.eth_tx_test.go | 8 ++
...resume_pipeline_task_flags_to_evm_txes.sql | 15 ++++
15 files changed, 281 insertions(+), 93 deletions(-)
create mode 100644 core/store/migrate/migrations/0209_add_resume_pipeline_task_flags_to_evm_txes.sql
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index d68b509101..00522abf22 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -775,12 +775,17 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) save
// Now we have an errored pipeline even though the tx succeeded. This case
// is relatively benign and probably nobody will ever run into it in
// practice, but something to be aware of.
- if etx.PipelineTaskRunID.Valid && eb.resumeCallback != nil {
+ if etx.PipelineTaskRunID.Valid && eb.resumeCallback != nil && etx.SignalCallback {
err := eb.resumeCallback(etx.PipelineTaskRunID.UUID, nil, errors.Errorf("fatal error while sending transaction: %s", etx.Error.String))
if errors.Is(err, sql.ErrNoRows) {
lgr.Debugw("callback missing or already resumed", "etxID", etx.ID)
} else if err != nil {
return errors.Wrap(err, "failed to resume pipeline")
+ } else {
+ // Mark tx as having completed callback
+ if err := eb.txStore.UpdateTxCallbackCompleted(ctx, etx.PipelineTaskRunID.UUID, eb.chainID); err != nil {
+ return err
+ }
}
}
return eb.txStore.UpdateTxFatalError(ctx, etx)
diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go
index 1d7446d9d2..afb2b3003a 100644
--- a/common/txmgr/confirmer.go
+++ b/common/txmgr/confirmer.go
@@ -1083,7 +1083,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) sen
// ResumePendingTaskRuns issues callbacks to task runs that are pending waiting for receipts
func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ResumePendingTaskRuns(ctx context.Context, head types.Head[BLOCK_HASH]) error {
- receiptsPlus, err := ec.txStore.FindReceiptsPendingConfirmation(ctx, head.BlockNumber(), ec.chainID)
+ receiptsPlus, err := ec.txStore.FindTxesPendingCallback(ctx, head.BlockNumber(), ec.chainID)
if err != nil {
return err
@@ -1105,6 +1105,10 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Res
ec.lggr.Debugw("Callback: resuming tx with receipt", "output", output, "taskErr", taskErr, "pipelineTaskRunID", data.ID)
if err := ec.resumeCallback(data.ID, output, taskErr); err != nil {
+ return fmt.Errorf("failed to resume suspended pipeline run: %w", err)
+ }
+ // Mark tx as having completed callback
+ if err := ec.txStore.UpdateTxCallbackCompleted(ctx, data.ID, ec.chainID); err != nil {
return err
}
}
diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go
index 7da51de606..0e344b9b6f 100644
--- a/common/txmgr/types/mocks/tx_store.go
+++ b/common/txmgr/types/mocks/tx_store.go
@@ -180,32 +180,6 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindNextUns
return r0
}
-// FindReceiptsPendingConfirmation provides a mock function with given fields: ctx, blockNum, chainID
-func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindReceiptsPendingConfirmation(ctx context.Context, blockNum int64, chainID CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error) {
- ret := _m.Called(ctx, blockNum, chainID)
-
- var r0 []txmgrtypes.ReceiptPlus[R]
- var r1 error
- if rf, ok := ret.Get(0).(func(context.Context, int64, CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error)); ok {
- return rf(ctx, blockNum, chainID)
- }
- if rf, ok := ret.Get(0).(func(context.Context, int64, CHAIN_ID) []txmgrtypes.ReceiptPlus[R]); ok {
- r0 = rf(ctx, blockNum, chainID)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]txmgrtypes.ReceiptPlus[R])
- }
- }
-
- if rf, ok := ret.Get(1).(func(context.Context, int64, CHAIN_ID) error); ok {
- r1 = rf(ctx, blockNum, chainID)
- } else {
- r1 = ret.Error(1)
- }
-
- return r0, r1
-}
-
// FindTransactionsConfirmedInBlockRange provides a mock function with given fields: ctx, highBlockNumber, lowBlockNumber, chainID
func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber int64, lowBlockNumber int64, chainID CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
ret := _m.Called(ctx, highBlockNumber, lowBlockNumber, chainID)
@@ -388,6 +362,32 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesByM
return r0, r1
}
+// FindTxesPendingCallback provides a mock function with given fields: ctx, blockNum, chainID
+func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error) {
+ ret := _m.Called(ctx, blockNum, chainID)
+
+ var r0 []txmgrtypes.ReceiptPlus[R]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error)); ok {
+ return rf(ctx, blockNum, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, CHAIN_ID) []txmgrtypes.ReceiptPlus[R]); ok {
+ r0 = rf(ctx, blockNum, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]txmgrtypes.ReceiptPlus[R])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, CHAIN_ID) error); ok {
+ r1 = rf(ctx, blockNum, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID
func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) {
ret := _m.Called(ctx, ids, states, chainID)
@@ -814,6 +814,20 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxAtt
return r0
}
+// UpdateTxCallbackCompleted provides a mock function with given fields: ctx, pipelineTaskRunRid, chainId
+func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error {
+ ret := _m.Called(ctx, pipelineTaskRunRid, chainId)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, CHAIN_ID) error); ok {
+ r0 = rf(ctx, pipelineTaskRunRid, chainId)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
// UpdateTxFatalError provides a mock function with given fields: ctx, etx
func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalError(ctx context.Context, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error {
ret := _m.Called(ctx, etx)
diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go
index d95f07afab..11017bd032 100644
--- a/common/txmgr/types/tx.go
+++ b/common/txmgr/types/tx.go
@@ -91,6 +91,9 @@ type TxRequest[ADDR types.Hashable, TX_HASH types.Hashable] struct {
// Checker defines the check that should be run before a transaction is submitted on chain.
Checker TransmitCheckerSpec[ADDR]
+
+ // Mark tx requiring callback
+ SignalCallback bool
}
// TransmitCheckerSpec defines the check that should be performed before a transaction is submitted
@@ -217,6 +220,11 @@ type Tx[
// TransmitChecker defines the check that should be performed before a transaction is submitted on
// chain.
TransmitChecker *datatypes.JSON
+
+ // Marks tx requiring callback
+ SignalCallback bool
+ // Marks tx callback as signaled
+ CallbackCompleted bool
}
func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetError() error {
diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go
index 83cb4b85ee..c2dfeee414 100644
--- a/common/txmgr/types/tx_store.go
+++ b/common/txmgr/types/tx_store.go
@@ -35,8 +35,10 @@ type TxStore[
TxHistoryReaper[CHAIN_ID]
TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE]
- // methods for saving & retreiving receipts
- FindReceiptsPendingConfirmation(ctx context.Context, blockNum int64, chainID CHAIN_ID) (receiptsPlus []ReceiptPlus[R], err error)
+ // Find confirmed txes beyond the minConfirmations param that require callback but have not yet been signaled
+ FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID CHAIN_ID) (receiptsPlus []ReceiptPlus[R], err error)
+ // Update tx to mark that its callback has been signaled
+ UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error
SaveFetchedReceipts(ctx context.Context, receipts []R, chainID CHAIN_ID) (err error)
// additional methods for tx store management
@@ -93,6 +95,8 @@ type TransactionStore[
SetBroadcastBeforeBlockNum(ctx context.Context, blockNum int64, chainID CHAIN_ID) error
UpdateBroadcastAts(ctx context.Context, now time.Time, etxIDs []int64) error
UpdateTxAttemptInProgressToBroadcast(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], NewAttemptState TxAttemptState) error
+ // Update tx to mark that its callback has been signaled
+ UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error
UpdateTxsUnconfirmed(ctx context.Context, ids []int64) error
UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error
UpdateTxFatalError(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index fcbc7a1f4c..460f9629fb 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -1055,6 +1055,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
FeeLimit: gasLimit,
State: txmgrcommon.TxUnstarted,
PipelineTaskRunID: uuid.NullUUID{UUID: tr.ID, Valid: true},
+ SignalCallback: true,
}
t.Run("with erroring callback bails out", func(t *testing.T) {
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index 1385250a20..3a0d33f7ba 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -2933,11 +2933,12 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) {
etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 1, fromAddress)
cltest.MustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2 WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
+ // Setting both signal_callback and callback_completed to TRUE to simulate a completed pipeline task
+ // It would only be in a state past suspended if the resume callback was called and callback_completed was set to TRUE
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
err := ec.ResumePendingTaskRuns(testutils.Context(t), &head)
require.NoError(t, err)
-
})
t.Run("doesn't process task runs where the receipt is younger than minConfirmations", func(t *testing.T) {
@@ -2952,15 +2953,15 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) {
etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress)
cltest.MustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2 WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
err := ec.ResumePendingTaskRuns(testutils.Context(t), &head)
require.NoError(t, err)
-
})
t.Run("processes eth_txes with receipts older than minConfirmations", func(t *testing.T) {
ch := make(chan interface{})
+ nonce := evmtypes.Nonce(3)
var err error
ec := cltest.NewEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, func(id uuid.UUID, value interface{}, thisErr error) error {
err = thisErr
@@ -2972,15 +2973,19 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) {
tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID)
pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
- etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress)
+ etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress)
pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
receipt := cltest.MustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2 WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
go func() {
err2 := ec.ResumePendingTaskRuns(testutils.Context(t), &head)
require.NoError(t, err2)
+ // Retrieve Tx to check if callback completed flag was set to true
+ updateTx, err3 := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce)
+ require.NoError(t, err3)
+ require.Equal(t, true, updateTx.CallbackCompleted)
}()
select {
@@ -3000,6 +3005,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) {
t.Run("processes eth_txes with receipt older than minConfirmations that reverted", func(t *testing.T) {
ch := make(chan interface{})
+ nonce := evmtypes.Nonce(4)
var err error
ec := cltest.NewEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, func(id uuid.UUID, value interface{}, thisErr error) error {
err = thisErr
@@ -3011,17 +3017,21 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) {
tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID)
pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
- etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress)
+ etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress)
pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
// receipt is not passed through as a value since it reverted and caused an error
cltest.MustInsertRevertedEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2 WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
go func() {
err2 := ec.ResumePendingTaskRuns(testutils.Context(t), &head)
require.NoError(t, err2)
+ // Retrieve Tx to check if callback completed flag was set to true
+ updateTx, err3 := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce)
+ require.NoError(t, err3)
+ require.Equal(t, true, updateTx.CallbackCompleted)
}()
select {
@@ -3036,6 +3046,28 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) {
t.Fatal("no value received")
}
})
+
+ t.Run("does not mark callback complete if callback fails", func(t *testing.T) {
+ nonce := evmtypes.Nonce(5)
+ ec := cltest.NewEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, func(uuid.UUID, interface{}, error) error {
+ return errors.New("error")
+ })
+
+ run := cltest.MustInsertPipelineRun(t, db)
+ tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID)
+
+ etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress)
+ cltest.MustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
+
+ err := ec.ResumePendingTaskRuns(testutils.Context(t), &head)
+ require.Error(t, err)
+
+ // Retrieve Tx to check if callback completed flag was left unchanged
+ updateTx, err := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce)
+ require.NoError(t, err)
+ require.Equal(t, false, updateTx.CallbackCompleted)
+ })
}
func ptr[T any](t T) *T { return &t }
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 4db7989b46..c3371fee80 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -115,7 +115,7 @@ type rawOnchainReceipt = evmtypes.Receipt
// Does not map to a single database table.
// It's comprised of fields from different tables.
type dbReceiptPlus struct {
- ID uuid.UUID `db:"id"`
+ ID uuid.UUID `db:"pipeline_task_run_id"`
Receipt evmtypes.Receipt `db:"receipt"`
FailOnRevert bool `db:"FailOnRevert"`
}
@@ -180,6 +180,10 @@ type DbEthTx struct {
// chain.
TransmitChecker *datatypes.JSON
InitialBroadcastAt *time.Time
+ // Marks tx requiring callback
+ SignalCallback bool
+ // Marks tx callback as signaled
+ CallbackCompleted bool
}
func (db *DbEthTx) FromTx(tx *Tx) {
@@ -200,6 +204,8 @@ func (db *DbEthTx) FromTx(tx *Tx) {
db.MinConfirmations = tx.MinConfirmations
db.TransmitChecker = tx.TransmitChecker
db.InitialBroadcastAt = tx.InitialBroadcastAt
+ db.SignalCallback = tx.SignalCallback
+ db.CallbackCompleted = tx.CallbackCompleted
if tx.ChainID != nil {
db.EVMChainID = *utils.NewBig(tx.ChainID)
@@ -233,6 +239,8 @@ func (db DbEthTx) ToTx(tx *Tx) {
tx.ChainID = db.EVMChainID.ToInt()
tx.TransmitChecker = db.TransmitChecker
tx.InitialBroadcastAt = db.InitialBroadcastAt
+ tx.SignalCallback = db.SignalCallback
+ tx.CallbackCompleted = db.CallbackCompleted
}
func dbEthTxsToEvmEthTxs(dbEthTxs []DbEthTx) []Tx {
@@ -512,8 +520,8 @@ func (o *evmTxStore) InsertTx(etx *Tx) error {
if etx.CreatedAt == (time.Time{}) {
etx.CreatedAt = time.Now()
}
- const insertEthTxSQL = `INSERT INTO evm.txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, error, broadcast_at, initial_broadcast_at, created_at, state, meta, subject, pipeline_task_run_id, min_confirmations, evm_chain_id, transmit_checker, idempotency_key) VALUES (
-:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit, :error, :broadcast_at, :initial_broadcast_at, :created_at, :state, :meta, :subject, :pipeline_task_run_id, :min_confirmations, :evm_chain_id, :transmit_checker, :idempotency_key
+ const insertEthTxSQL = `INSERT INTO evm.txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, error, broadcast_at, initial_broadcast_at, created_at, state, meta, subject, pipeline_task_run_id, min_confirmations, evm_chain_id, transmit_checker, idempotency_key, signal_callback, callback_completed) VALUES (
+:nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit, :error, :broadcast_at, :initial_broadcast_at, :created_at, :state, :meta, :subject, :pipeline_task_run_id, :min_confirmations, :evm_chain_id, :transmit_checker, :idempotency_key, :signal_callback, :callback_completed
) RETURNING *`
var dbTx DbEthTx
dbTx.FromTx(etx)
@@ -941,25 +949,40 @@ WHERE evm.tx_attempts.state = 'in_progress' AND evm.txes.from_address = $1 AND e
return attempts, pkgerrors.Wrap(err, "getInProgressEthTxAttempts failed")
}
-func (o *evmTxStore) FindReceiptsPendingConfirmation(ctx context.Context, blockNum int64, chainID *big.Int) (receiptsPlus []ReceiptPlus, err error) {
+// Find confirmed txes requiring callback but have not yet been signaled
+func (o *evmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID *big.Int) (receiptsPlus []ReceiptPlus, err error) {
var rs []dbReceiptPlus
var cancel context.CancelFunc
ctx, cancel = o.mergeContexts(ctx)
defer cancel()
err = o.q.SelectContext(ctx, &rs, `
- SELECT pipeline_task_runs.id, evm.receipts.receipt, COALESCE((evm.txes.meta->>'FailOnRevert')::boolean, false) "FailOnRevert" FROM pipeline_task_runs
- INNER JOIN pipeline_runs ON pipeline_runs.id = pipeline_task_runs.pipeline_run_id
- INNER JOIN evm.txes ON evm.txes.pipeline_task_run_id = pipeline_task_runs.id
+ SELECT evm.txes.pipeline_task_run_id, evm.receipts.receipt, COALESCE((evm.txes.meta->>'FailOnRevert')::boolean, false) "FailOnRevert" FROM evm.txes
INNER JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id
INNER JOIN evm.receipts ON evm.tx_attempts.hash = evm.receipts.tx_hash
- WHERE pipeline_runs.state = 'suspended' AND evm.receipts.block_number <= ($1 - evm.txes.min_confirmations) AND evm.txes.evm_chain_id = $2
+ WHERE evm.txes.pipeline_task_run_id IS NOT NULL AND evm.txes.signal_callback = TRUE AND evm.txes.callback_completed = FALSE
+ AND evm.receipts.block_number <= ($1 - evm.txes.min_confirmations) AND evm.txes.evm_chain_id = $2
`, blockNum, chainID.String())
-
+ if err != nil {
+ return nil, fmt.Errorf("failed to retrieve transactions pending pipeline resume callback: %w", err)
+ }
receiptsPlus = fromDBReceiptsPlus(rs)
return
}
+// Update tx to mark that its callback has been signaled
+func (o *evmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunId uuid.UUID, chainId *big.Int) error {
+ var cancel context.CancelFunc
+ ctx, cancel = o.mergeContexts(ctx)
+ defer cancel()
+ qq := o.q.WithOpts(pg.WithParentCtx(ctx))
+ _, err := qq.Exec(`UPDATE evm.txes SET callback_completed = TRUE WHERE pipeline_task_run_id = $1 AND evm_chain_id = $2`, pipelineTaskRunId, chainId.String())
+ if err != nil {
+ return fmt.Errorf("failed to mark callback completed for transaction: %w", err)
+ }
+ return nil
+}
+
func (o *evmTxStore) FindLatestSequence(ctx context.Context, fromAddress common.Address, chainId *big.Int) (nonce evmtypes.Nonce, err error) {
var cancel context.CancelFunc
ctx, cancel = o.mergeContexts(ctx)
@@ -1661,12 +1684,12 @@ func (o *evmTxStore) CreateTransaction(ctx context.Context, txRequest TxRequest,
}
}
err = tx.Get(&dbEtx, `
-INSERT INTO evm.txes (from_address, to_address, encoded_payload, value, gas_limit, state, created_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id, transmit_checker, idempotency_key)
+INSERT INTO evm.txes (from_address, to_address, encoded_payload, value, gas_limit, state, created_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id, transmit_checker, idempotency_key, signal_callback)
VALUES (
-$1,$2,$3,$4,$5,'unstarted',NOW(),$6,$7,$8,$9,$10,$11,$12
+$1,$2,$3,$4,$5,'unstarted',NOW(),$6,$7,$8,$9,$10,$11,$12,$13
)
RETURNING "txes".*
-`, txRequest.FromAddress, txRequest.ToAddress, txRequest.EncodedPayload, assets.Eth(txRequest.Value), txRequest.FeeLimit, txRequest.Meta, txRequest.Strategy.Subject(), chainID.String(), txRequest.MinConfirmations, txRequest.PipelineTaskRunID, txRequest.Checker, txRequest.IdempotencyKey)
+`, txRequest.FromAddress, txRequest.ToAddress, txRequest.EncodedPayload, assets.Eth(txRequest.Value), txRequest.FeeLimit, txRequest.Meta, txRequest.Strategy.Subject(), chainID.String(), txRequest.MinConfirmations, txRequest.PipelineTaskRunID, txRequest.Checker, txRequest.IdempotencyKey, txRequest.SignalCallback)
if err != nil {
return pkgerrors.Wrap(err, "CreateEthTransaction failed to insert evm tx")
}
diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go
index ba02f118cf..f8798f9f83 100644
--- a/core/chains/evm/txmgr/evm_tx_store_test.go
+++ b/core/chains/evm/txmgr/evm_tx_store_test.go
@@ -21,6 +21,7 @@ import (
"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/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -617,7 +618,7 @@ func TestORM_GetInProgressTxAttempts(t *testing.T) {
assert.Equal(t, etx.TxAttempts[0].ID, attempts[0].ID)
}
-func TestORM_FindReceiptsPendingConfirmation(t *testing.T) {
+func TestORM_FindTxesPendingCallback(t *testing.T) {
t.Parallel()
db := pgtest.NewSqlxDB(t)
@@ -645,21 +646,50 @@ func TestORM_FindReceiptsPendingConfirmation(t *testing.T) {
minConfirmations := int64(2)
- run := cltest.MustInsertPipelineRun(t, db)
- tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID)
- pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
-
- etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress)
+ // Suspended run waiting for callback
+ run1 := cltest.MustInsertPipelineRun(t, db)
+ tr1 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run1.ID)
+ pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run1.ID)
+ etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress)
pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
- attempt := etx.TxAttempts[0]
- cltest.MustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt.Hash)
-
- pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2 WHERE id = $3`, &tr.ID, minConfirmations, etx.ID)
-
- receiptsPlus, err := txStore.FindReceiptsPendingConfirmation(testutils.Context(t), head.Number, ethClient.ConfiguredChainID())
+ attempt1 := etx1.TxAttempts[0]
+ cltest.MustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt1.Hash)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr1.ID, minConfirmations, etx1.ID)
+
+ // Callback to pipeline service completed. Should be ignored
+ run2 := cltest.MustInsertPipelineRunWithStatus(t, db, 0, pipeline.RunStatusCompleted)
+ tr2 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run2.ID)
+ etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`)
+ attempt2 := etx2.TxAttempts[0]
+ cltest.MustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt2.Hash)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &tr2.ID, minConfirmations, etx2.ID)
+
+ // Suspended run younger than minConfirmations. Should be ignored
+ run3 := cltest.MustInsertPipelineRun(t, db)
+ tr3 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run3.ID)
+ pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run3.ID)
+ etx3 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 5, 1, fromAddress)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`)
+ attempt3 := etx3.TxAttempts[0]
+ cltest.MustInsertEthReceipt(t, txStore, head.Number, head.Hash, attempt3.Hash)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr3.ID, minConfirmations, etx3.ID)
+
+ // Tx not marked for callback. Should be ignore
+ etx4 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 6, 1, fromAddress)
+ attempt4 := etx4.TxAttempts[0]
+ cltest.MustInsertEthReceipt(t, txStore, head.Number, head.Hash, attempt4.Hash)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx4.ID)
+
+ // Unconfirmed Tx without receipts. Should be ignored
+ etx5 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 1, fromAddress)
+ pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx5.ID)
+
+ // Search evm.txes table for tx requiring callback
+ receiptsPlus, err := txStore.FindTxesPendingCallback(testutils.Context(t), head.Number, ethClient.ConfiguredChainID())
require.NoError(t, err)
assert.Len(t, receiptsPlus, 1)
- assert.Equal(t, tr.ID, receiptsPlus[0].ID)
+ assert.Equal(t, tr1.ID, receiptsPlus[0].ID)
}
func Test_FindTxWithIdempotencyKey(t *testing.T) {
@@ -1569,6 +1599,35 @@ func TestORM_CreateTransaction(t *testing.T) {
assert.Equal(t, tx1.GetID(), tx2.GetID())
})
+
+ t.Run("sets signal callback flag", func(t *testing.T) {
+ subject := uuid.New()
+ strategy := newMockTxStrategy(t)
+ strategy.On("Subject").Return(uuid.NullUUID{UUID: subject, Valid: true})
+ strategy.On("PruneQueue", mock.Anything, mock.AnythingOfType("*txmgr.evmTxStore")).Return(int64(0), nil)
+ etx, err := txStore.CreateTransaction(testutils.Context(t), txmgr.TxRequest{
+ FromAddress: fromAddress,
+ ToAddress: toAddress,
+ EncodedPayload: payload,
+ FeeLimit: gasLimit,
+ Meta: nil,
+ Strategy: strategy,
+ SignalCallback: true,
+ }, ethClient.ConfiguredChainID())
+ assert.NoError(t, err)
+
+ assert.Greater(t, etx.ID, int64(0))
+ assert.Equal(t, fromAddress, etx.FromAddress)
+ assert.Equal(t, true, etx.SignalCallback)
+
+ cltest.AssertCount(t, db, "evm.txes", 3)
+
+ var dbEthTx txmgr.DbEthTx
+ require.NoError(t, db.Get(&dbEthTx, `SELECT * FROM evm.txes ORDER BY id DESC LIMIT 1`))
+
+ assert.Equal(t, fromAddress, dbEthTx.FromAddress)
+ assert.Equal(t, true, dbEthTx.SignalCallback)
+ })
}
func TestORM_PruneUnstartedTxQueue(t *testing.T) {
diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go
index 4632a8ae34..f491bda40b 100644
--- a/core/chains/evm/txmgr/mocks/evm_tx_store.go
+++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go
@@ -183,32 +183,6 @@ func (_m *EvmTxStore) FindNextUnstartedTransactionFromAddress(ctx context.Contex
return r0
}
-// FindReceiptsPendingConfirmation provides a mock function with given fields: ctx, blockNum, chainID
-func (_m *EvmTxStore) FindReceiptsPendingConfirmation(ctx context.Context, blockNum int64, chainID *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error) {
- ret := _m.Called(ctx, blockNum, chainID)
-
- var r0 []types.ReceiptPlus[*evmtypes.Receipt]
- var r1 error
- if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)); ok {
- return rf(ctx, blockNum, chainID)
- }
- if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) []types.ReceiptPlus[*evmtypes.Receipt]); ok {
- r0 = rf(ctx, blockNum, chainID)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]types.ReceiptPlus[*evmtypes.Receipt])
- }
- }
-
- if rf, ok := ret.Get(1).(func(context.Context, int64, *big.Int) error); ok {
- r1 = rf(ctx, blockNum, chainID)
- } else {
- r1 = ret.Error(1)
- }
-
- return r0, r1
-}
-
// FindTransactionsConfirmedInBlockRange provides a mock function with given fields: ctx, highBlockNumber, lowBlockNumber, chainID
func (_m *EvmTxStore) FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber int64, lowBlockNumber int64, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
ret := _m.Called(ctx, highBlockNumber, lowBlockNumber, chainID)
@@ -493,6 +467,32 @@ func (_m *EvmTxStore) FindTxesByMetaFieldAndStates(ctx context.Context, metaFiel
return r0, r1
}
+// FindTxesPendingCallback provides a mock function with given fields: ctx, blockNum, chainID
+func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error) {
+ ret := _m.Called(ctx, blockNum, chainID)
+
+ var r0 []types.ReceiptPlus[*evmtypes.Receipt]
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)); ok {
+ return rf(ctx, blockNum, chainID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) []types.ReceiptPlus[*evmtypes.Receipt]); ok {
+ r0 = rf(ctx, blockNum, chainID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]types.ReceiptPlus[*evmtypes.Receipt])
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, *big.Int) error); ok {
+ r1 = rf(ctx, blockNum, chainID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID
func (_m *EvmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) {
ret := _m.Called(ctx, ids, states, chainID)
@@ -1018,6 +1018,20 @@ func (_m *EvmTxStore) UpdateTxAttemptInProgressToBroadcast(ctx context.Context,
return r0
}
+// UpdateTxCallbackCompleted provides a mock function with given fields: ctx, pipelineTaskRunRid, chainId
+func (_m *EvmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId *big.Int) error {
+ ret := _m.Called(ctx, pipelineTaskRunRid, chainId)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, *big.Int) error); ok {
+ r0 = rf(ctx, pipelineTaskRunRid, chainId)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
// UpdateTxFatalError provides a mock function with given fields: ctx, etx
func (_m *EvmTxStore) UpdateTxFatalError(ctx context.Context, etx *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error {
ret := _m.Called(ctx, etx)
diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go
index d60050700f..056a7deab2 100644
--- a/core/services/pipeline/orm.go
+++ b/core/services/pipeline/orm.go
@@ -306,13 +306,13 @@ func (o *orm) UpdateTaskRunResult(taskID uuid.UUID, result Result) (run Run, sta
WHERE pipeline_task_runs.id = $1 AND pipeline_runs.state in ('running', 'suspended')
FOR UPDATE`
if err = tx.Get(&run, sql, taskID); err != nil {
- return err
+ return fmt.Errorf("failed to find pipeline run for ID %s: %w", taskID.String(), err)
}
// Update the task with result
sql = `UPDATE pipeline_task_runs SET output = $2, error = $3, finished_at = $4 WHERE id = $1`
if _, err = tx.Exec(sql, taskID, result.OutputDB(), result.ErrorDB(), time.Now()); err != nil {
- return errors.Wrap(err, "UpdateTaskRunResult")
+ return fmt.Errorf("failed to update pipeline task run: %w", err)
}
if run.State == RunStatusSuspended {
@@ -321,7 +321,7 @@ func (o *orm) UpdateTaskRunResult(taskID uuid.UUID, result Result) (run Run, sta
sql = `UPDATE pipeline_runs SET state = $2 WHERE id = $1`
if _, err = tx.Exec(sql, run.ID, run.State); err != nil {
- return errors.Wrap(err, "UpdateTaskRunResult")
+ return fmt.Errorf("failed to update pipeline run state: %w", err)
}
}
diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go
index 3dbe94747e..d33913b475 100644
--- a/core/services/pipeline/runner.go
+++ b/core/services/pipeline/runner.go
@@ -609,7 +609,7 @@ func (r *runner) ResumeRun(taskID uuid.UUID, value interface{}, err error) error
Error: err,
})
if err != nil {
- return err
+ return fmt.Errorf("failed to update task run result: %w", err)
}
// TODO: Should probably replace this with a listener to update events
diff --git a/core/services/pipeline/task.eth_tx.go b/core/services/pipeline/task.eth_tx.go
index 57f1c0a7ed..384c86446e 100644
--- a/core/services/pipeline/task.eth_tx.go
+++ b/core/services/pipeline/task.eth_tx.go
@@ -155,6 +155,7 @@ func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inpu
ForwarderAddress: forwarderAddress,
Strategy: strategy,
Checker: transmitChecker,
+ SignalCallback: true,
}
if minOutgoingConfirmations > 0 {
diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go
index e5f50bc29e..a0ff54d444 100644
--- a/core/services/pipeline/task.eth_tx_test.go
+++ b/core/services/pipeline/task.eth_tx_test.go
@@ -95,6 +95,7 @@ func TestETHTxTask(t *testing.T) {
CheckerType: txmgr.TransmitCheckerTypeVRFV2,
VRFCoordinatorAddress: &addr,
},
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -138,6 +139,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: gasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -215,6 +217,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: gasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -260,6 +263,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: gasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -290,6 +294,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: gasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -324,6 +329,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: drJobTypeGasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -358,6 +364,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: specGasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, nil)
},
nil, nil, "", pipeline.RunInfo{},
@@ -423,6 +430,7 @@ func TestETHTxTask(t *testing.T) {
FeeLimit: gasLimit,
Meta: txMeta,
Strategy: txmgrcommon.NewSendEveryStrategy(),
+ SignalCallback: true,
}).Return(txmgr.Tx{}, errors.New("uh oh"))
},
nil, pipeline.ErrTaskRunFailed, "while creating transaction", pipeline.RunInfo{IsRetryable: true},
diff --git a/core/store/migrate/migrations/0209_add_resume_pipeline_task_flags_to_evm_txes.sql b/core/store/migrate/migrations/0209_add_resume_pipeline_task_flags_to_evm_txes.sql
new file mode 100644
index 0000000000..dbe7e91b9f
--- /dev/null
+++ b/core/store/migrate/migrations/0209_add_resume_pipeline_task_flags_to_evm_txes.sql
@@ -0,0 +1,15 @@
+-- +goose Up
+ALTER TABLE evm.txes ADD COLUMN "signal_callback" BOOL DEFAULT FALSE;
+ALTER TABLE evm.txes ADD COLUMN "callback_completed" BOOL DEFAULT FALSE;
+
+UPDATE evm.txes
+SET signal_callback = TRUE AND callback_completed = FALSE
+WHERE evm.txes.pipeline_task_run_id IN (
+ SELECT pipeline_task_runs.id FROM pipeline_task_runs
+ INNER JOIN pipeline_runs ON pipeline_runs.id = pipeline_task_runs.pipeline_run_id
+ WHERE pipeline_runs.state = 'suspended'
+);
+
+-- +goose Down
+ALTER TABLE evm.txes DROP COLUMN "signal_callback";
+ALTER TABLE evm.txes DROP COLUMN "callback_completed";
From 6fb7fae8511edb4b9c7ef3fbc3373f7de5dd90a0 Mon Sep 17 00:00:00 2001
From: Patrick
Date: Tue, 14 Nov 2023 05:57:27 -0500
Subject: [PATCH 141/327] feature/tracing-data: Trace data as artifact in CI
(#11113)
* WIP: generate traces as artifact
* Splitting otel collector into dev and ci environments
* feature/tracing-data: minor cleanup
---
.github/tracing/README.md | 43 ++++++++-
.../tracing/local-smoke-docker-compose.yaml | 4 +-
.github/tracing/otel-collector-ci.yaml | 22 +++++
...collector.yaml => otel-collector-dev.yaml} | 5 +
.github/tracing/replay.sh | 6 ++
.github/workflows/integration-tests.yml | 92 +++++++------------
6 files changed, 111 insertions(+), 61 deletions(-)
create mode 100644 .github/tracing/otel-collector-ci.yaml
rename .github/tracing/{otel-collector.yaml => otel-collector-dev.yaml} (67%)
create mode 100644 .github/tracing/replay.sh
diff --git a/.github/tracing/README.md b/.github/tracing/README.md
index 6988383ca7..eb75738429 100644
--- a/.github/tracing/README.md
+++ b/.github/tracing/README.md
@@ -1,5 +1,44 @@
# Distributed Tracing
-These config files are for an OTEL collector, grafana Tempo, and a grafana UI instance to run as containers on the same network.
+As part of the LOOP plugin effort, we've added distributed tracing to the core node. This is helpful for initial development and maintenance of LOOPs, but will also empower product teams building on top of core.
+
+## Dev environment
+
+One way to generate traces locally today is with the OCR2 basic smoke test.
+
+1. navigate to `.github/tracing/` and then run `docker compose --file local-smoke-docker-compose.yaml up`
+2. setup a local docker registry at `127.0.0.1:5000` (https://www.docker.com/blog/how-to-use-your-own-registry-2/)
+3. run `make build_push_plugin_docker_image` in `chainlink/integration-tests/Makefile`
+4. run `SELECTED_NETWORKS=SIMULATED CHAINLINK_IMAGE="127.0.0.1:5000/chainlink" CHAINLINK_VERSION="develop" go test -run TestOCRv2Basic ./smoke/ocr2_test.go`
+5. navigate to `localhost:3000/explore` in a web browser to query for traces
+
+Core and the median plugins are instrumented with open telemetry traces, which are sent to the OTEL collector and forwarded to the Tempo backend. The grafana UI can then read the trace data from the Tempo backend.
+
+
-A localhost client can send gRPC calls to the server. The gRPC server is instrumented with open telemetry traces, which are sent to the OTEL collector and forwarded to the Tempo backend. The grafana UI can then read the trace data from the Tempo backend.
\ No newline at end of file
+## CI environment
+
+Another way to generate traces is by enabling traces for PRs. This will instrument traces for `TestOCRv2Basic` in the CI run.
+
+1. Cut a PR in the core repo
+2. Add the `enable tracing` label to the PR
+3. Navigate to `Integration Tests / ETH Smoke Tests ocr2-plugins (pull_request)` details
+4. Navigate to the summary of the integration tests
+5. After the test completes, the generated trace data will be saved as an artifact, currently called `trace-data`
+6. Download the artifact to this directory (`chainlink/.github/tracing`)
+7. `docker compose --file local-smoke-docker-compose.yaml up`
+8. Run `sh replay.sh` to replay those traces to the otel-collector container that was spun up in the last step.
+9. navigate to `localhost:3000/explore` in a web browser to query for traces
+
+The artifact is not json encoded - each individual line is a well formed and complete json object.
+
+## Configuration
+This folder contains the following config files:
+* otel-collector-ci.yaml
+* otel-collector-dev.yaml
+* tempo.yaml
+* grafana-datasources.yaml
+
+These config files are for an OTEL collector, grafana Tempo, and a grafana UI instance to run as containers on the same network.
+`otel-collector-dev.yaml` is the configuration for dev (i.e. your local machine) environments, and forwards traces from the otel collector to the grafana tempo instance on the same network.
+`otel-collector-ci.yaml` is the configuration for the CI runs, and exports the trace data to the artifact from the github run.
\ No newline at end of file
diff --git a/.github/tracing/local-smoke-docker-compose.yaml b/.github/tracing/local-smoke-docker-compose.yaml
index e0e60a675e..744ba88ef6 100644
--- a/.github/tracing/local-smoke-docker-compose.yaml
+++ b/.github/tracing/local-smoke-docker-compose.yaml
@@ -6,9 +6,11 @@ services:
image: otel/opentelemetry-collector:0.61.0
command: [ "--config=/etc/otel-collector.yaml" ]
volumes:
- - ./otel-collector.yaml:/etc/otel-collector.yaml
+ - ./otel-collector-dev.yaml:/etc/otel-collector.yaml
+ - ../../integration-tests/smoke/traces/trace-data.json:/etc/trace-data.json # local trace data stored consistent with smoke/logs
ports:
- "4317:4317" # otlp grpc
+ - "3100:3100"
depends_on:
- tempo
networks:
diff --git a/.github/tracing/otel-collector-ci.yaml b/.github/tracing/otel-collector-ci.yaml
new file mode 100644
index 0000000000..0bf123d29b
--- /dev/null
+++ b/.github/tracing/otel-collector-ci.yaml
@@ -0,0 +1,22 @@
+receivers:
+ otlp:
+ protocols:
+ grpc:
+ endpoint: "0.0.0.0:4317"
+ http:
+ endpoint: "0.0.0.0:3100"
+exporters:
+ file:
+ path: /tracing/trace-data.json
+ otlp:
+ endpoint: tempo:4317
+ tls:
+ insecure: true
+service:
+ telemetry:
+ logs:
+ level: "debug" # Set log level to debug
+ pipelines:
+ traces:
+ receivers: [otlp]
+ exporters: [file,otlp]
\ No newline at end of file
diff --git a/.github/tracing/otel-collector.yaml b/.github/tracing/otel-collector-dev.yaml
similarity index 67%
rename from .github/tracing/otel-collector.yaml
rename to .github/tracing/otel-collector-dev.yaml
index fb8721cba2..dd059127b8 100644
--- a/.github/tracing/otel-collector.yaml
+++ b/.github/tracing/otel-collector-dev.yaml
@@ -3,12 +3,17 @@ receivers:
protocols:
grpc:
endpoint: "0.0.0.0:4317"
+ http:
+ endpoint: "0.0.0.0:3100"
exporters:
otlp:
endpoint: tempo:4317
tls:
insecure: true
service:
+ telemetry:
+ logs:
+ level: "debug" # Set log level to debug
pipelines:
traces:
receivers: [otlp]
diff --git a/.github/tracing/replay.sh b/.github/tracing/replay.sh
new file mode 100644
index 0000000000..b2e564567c
--- /dev/null
+++ b/.github/tracing/replay.sh
@@ -0,0 +1,6 @@
+# Read JSON file and loop through each trace
+while IFS= read -r trace; do
+ curl -X POST http://localhost:3100/v1/traces \
+ -H "Content-Type: application/json" \
+ -d "$trace"
+done < "trace-data"
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 9294dceae6..17f571fd63 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -368,67 +368,33 @@ jobs:
# Create network
docker network create --driver bridge tracing
- # Start Grafana
- cd ./.github/tracing
- docker run -d --network=tracing --name=grafana -p 3000:3000 -v $PWD/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml -e GF_AUTH_ANONYMOUS_ENABLED=true -e GF_AUTH_ANONYMOUS_ORG_ROLE=Admin -e GF_AUTH_DISABLE_LOGIN_FORM=true -e GF_FEATURE_TOGGLES_ENABLE=traceqlEditor grafana/grafana:9.4.3
+ # Make trace directory
+ cd integration-tests/smoke/
+ mkdir ./traces
+ chmod -R 777 ./traces
- # Start Tempo
- docker run -d --network=tracing --name=tempo -v ./tempo.yaml:/etc/tempo.yaml -v $PWD/tempo-data:/tmp/tempo grafana/tempo:latest -config.file=/etc/tempo.yaml
+ # Switch directory
+ cd ../../.github/tracing
- # Start OpenTelemetry Collector
- docker run -d --network=tracing --name=otel-collector -v $PWD/otel-collector.yaml:/etc/otel-collector.yaml -p 4317:4317 otel/opentelemetry-collector:0.61.0 --config=/etc/otel-collector.yaml
-
- - name: Generate port
- id: generate-port
- if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
- env:
- GITHUB_PR_NUMBER: ${{ github.event.number }}
- run: |
- PORT_BASE=3001
- MAX_PORT=8000
+ # Create a Docker volume for traces
+ # docker volume create otel-traces
- # Use PR number as offset. Given GitHub PRs are incremental, this guarantees uniqueness for at least 5000 PRs.
- OFFSET=$GITHUB_PR_NUMBER
- echo "PR Number: $OFFSET"
-
- # Ensure that we don't exceed the max port
- if (( OFFSET > (MAX_PORT - PORT_BASE) )); then
- OFFSET=$((OFFSET % (MAX_PORT - PORT_BASE)))
- fi
-
- # Map the offset to the port range
- REMOTE_PORT=$((PORT_BASE + OFFSET))
- echo "REMOTE_PORT=$REMOTE_PORT" >> $GITHUB_OUTPUT
- - name: Reverse SSH Tunneling
- if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
- env:
- TRACING_SSH_KEY: ${{ secrets.TRACING_SSH_KEY }}
- TRACING_SSH_SERVER: ${{ secrets.TRACING_SSH_SERVER }}
- REMOTE_PORT: ${{ steps.generate-port.outputs.REMOTE_PORT }}
- run: |
- eval $(ssh-agent)
- echo "test"
- echo "$TRACING_SSH_KEY" | wc -c
- echo "$TRACING_SSH_KEY" | tr -d '\r' | wc -c
- echo "$TRACING_SSH_KEY" | tr -d '\r' | base64 --decode | ssh-add -
- # f: background process
- # N: do not execute a remote command
- # R: remote port forwarding
- ssh -o StrictHostKeyChecking=no -f -N -R $REMOTE_PORT:127.0.0.1:3000 user-gha@$TRACING_SSH_SERVER
- echo "To view Grafana locally:"
- echo "ssh -N -L 8000:localhost:$REMOTE_PORT user-gha@$TRACING_SSH_SERVER"
- echo "Then visit http://localhost:8000 in a browser."
- echo "If you are unable to connect, check with the security team that you have access to the tracing server."
- - name: Show Grafana Logs
- if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
+ # Start OpenTelemetry Collector
+ # Note the user must be set to the same user as the runner for the trace data to be accessible
+ docker run -d --network=tracing --name=otel-collector \
+ -v $PWD/otel-collector-ci.yaml:/etc/otel-collector.yaml \
+ -v $PWD/../../integration-tests/smoke/traces:/tracing \
+ --user "$(id -u):$(id -g)" \
+ -p 4317:4317 otel/opentelemetry-collector:0.88.0 --config=/etc/otel-collector.yaml
+ - name: Locate Docker Volume
+ id: locate-volume
+ if: false
run: |
- docker logs grafana
- docker logs tempo
- docker logs otel-collector
- - name: Set sleep time to use in future steps
+ echo "VOLUME_PATH=$(docker volume inspect --format '{{ .Mountpoint }}' otel-traces)" >> $GITHUB_OUTPUT
+ - name: Show Otel-Collector Logs
if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
run: |
- echo "SLEEP_TIME=2400" >> "$GITHUB_ENV"
+ docker logs otel-collector
## Run this step when changes that require tests to be run are made
- name: Run Tests
if: needs.changes.outputs.src == 'true'
@@ -465,6 +431,10 @@ jobs:
QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
+ - name: Show Otel-Collector Logs
+ if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
+ run: |
+ docker logs otel-collector
- name: Collect Metrics
if: always()
id: collect-gha-metrics
@@ -475,11 +445,17 @@ jobs:
this-job-name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }}
test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
continue-on-error: true
- - name: Keep action running to view traces
+ - name: Permissions on traces
if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
run: |
- echo "Sleeping for $SLEEP_TIME seconds..."
- sleep $SLEEP_TIME
+ ls -l ./integration-tests/smoke/traces
+ - name: Upload Trace Data
+ if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins'
+ uses: actions/upload-artifact@v3
+ with:
+ name: trace-data
+ path: ./integration-tests/smoke/traces/trace-data.json
+
### Used to check the required checks box when the matrix completes
eth-smoke-tests:
From ac94719b7d4f7a73ad132db4910d515bb6a633e2 Mon Sep 17 00:00:00 2001
From: Lukasz <120112546+lukaszcl@users.noreply.github.com>
Date: Tue, 14 Nov 2023 13:19:29 +0100
Subject: [PATCH 142/327] Use resty as http response in E2E tests and fix if
testing.T context is nil (#11271)
* Use resty as http response
* Fix for nil testing.T context
---
integration-tests/client/chainlink.go | 31 ++++++++++++++++++++++-----
integration-tests/utils/common.go | 4 ++++
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go
index 3638fa11c7..ef7bd06142 100644
--- a/integration-tests/client/chainlink.go
+++ b/integration-tests/client/chainlink.go
@@ -117,11 +117,11 @@ func (c *ChainlinkClient) MustCreateJob(spec JobSpec) (*Job, error) {
if err != nil {
return nil, err
}
- return job, VerifyStatusCode(resp.StatusCode, http.StatusOK)
+ return job, VerifyStatusCode(resp.RawResponse.StatusCode, http.StatusOK)
}
// CreateJob creates a Chainlink job based on the provided spec struct
-func (c *ChainlinkClient) CreateJob(spec JobSpec) (*Job, *http.Response, error) {
+func (c *ChainlinkClient) CreateJob(spec JobSpec) (*Job, *resty.Response, error) {
job := &Job{}
specString, err := spec.String()
if err != nil {
@@ -138,7 +138,7 @@ func (c *ChainlinkClient) CreateJob(spec JobSpec) (*Job, *http.Response, error)
if err != nil {
return nil, nil, err
}
- return job, resp.RawResponse, err
+ return job, resp, err
}
// ReadJobs reads all jobs from the Chainlink node
@@ -881,8 +881,16 @@ func (c *ChainlinkClient) CreateCSAKey() (*CSAKey, *http.Response, error) {
return csaKey, resp.RawResponse, err
}
+func (c *ChainlinkClient) MustReadCSAKeys() (*CSAKeys, *resty.Response, error) {
+ csaKeys, res, err := c.ReadCSAKeys()
+ if err != nil {
+ return nil, res, err
+ }
+ return csaKeys, res, VerifyStatusCodeWithResponse(res, http.StatusOK)
+}
+
// ReadCSAKeys reads CSA keys from the Chainlink node
-func (c *ChainlinkClient) ReadCSAKeys() (*CSAKeys, *http.Response, error) {
+func (c *ChainlinkClient) ReadCSAKeys() (*CSAKeys, *resty.Response, error) {
csaKeys := &CSAKeys{}
c.l.Info().Str(NodeURL, c.Config.URL).Msg("Reading CSA Keys")
resp, err := c.APIClient.R().
@@ -894,7 +902,7 @@ func (c *ChainlinkClient) ReadCSAKeys() (*CSAKeys, *http.Response, error) {
if err != nil {
return nil, nil, err
}
- return csaKeys, resp.RawResponse, err
+ return csaKeys, resp, err
}
// CreateEI creates an EI on the Chainlink node based on the provided attributes and returns the respective secrets
@@ -1105,6 +1113,19 @@ func VerifyStatusCode(actStatusCd, expStatusCd int) error {
return nil
}
+func VerifyStatusCodeWithResponse(res *resty.Response, expStatusCd int) error {
+ actStatusCd := res.RawResponse.StatusCode
+ if actStatusCd != expStatusCd {
+ return fmt.Errorf(
+ "unexpected response code, got %d, expected %d, response: %s",
+ actStatusCd,
+ expStatusCd,
+ res.Body(),
+ )
+ }
+ return nil
+}
+
func CreateNodeKeysBundle(nodes []*ChainlinkClient, chainName string, chainId string) ([]NodeKeysBundle, []*CLNodesWithKeys, error) {
nkb := make([]NodeKeysBundle, 0)
var clNodes []*CLNodesWithKeys
diff --git a/integration-tests/utils/common.go b/integration-tests/utils/common.go
index 5ef3209c92..f13c71cfd9 100644
--- a/integration-tests/utils/common.go
+++ b/integration-tests/utils/common.go
@@ -42,6 +42,10 @@ func TestContext(tb testing.TB) context.Context {
var cancel func()
switch t := tb.(type) {
case *testing.T:
+ // Return background context if testing.T not set
+ if t == nil {
+ return ctx
+ }
if d, ok := t.Deadline(); ok {
ctx, cancel = context.WithDeadline(ctx, d)
}
From b7f042ceafe543937310fa1e47f2909a86dcf797 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Tue, 14 Nov 2023 06:47:24 -0600
Subject: [PATCH 143/327] core/services/pg: simplify TxOptions (#11276)
---
core/services/pg/transaction.go | 38 ++++-----------------------------
core/services/pg/utils.go | 6 ------
2 files changed, 4 insertions(+), 40 deletions(-)
diff --git a/core/services/pg/transaction.go b/core/services/pg/transaction.go
index d237c20d4c..92d72b3d81 100644
--- a/core/services/pg/transaction.go
+++ b/core/services/pg/transaction.go
@@ -7,20 +7,16 @@ import (
"time"
"github.com/getsentry/sentry-go"
+ "github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/jmoiron/sqlx"
-
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
-
corelogger "github.com/smartcontractkit/chainlink/v2/core/logger"
)
type TxOptions struct {
sql.TxOptions
- LockTimeout time.Duration
- IdleInTxSessionTimeout time.Duration
}
// NOTE: In an ideal world the timeouts below would be set to something sane in
@@ -39,27 +35,14 @@ func OptReadOnlyTx() TxOptions {
return TxOptions{TxOptions: sql.TxOptions{ReadOnly: true}}
}
-func applyDefaults(optss []TxOptions) (lockTimeout, idleInTxSessionTimeout time.Duration, txOpts sql.TxOptions) {
- lockTimeout = defaultLockTimeout
- idleInTxSessionTimeout = defaultIdleInTxSessionTimeout
- txIsolation := DefaultIsolation
+func applyDefaults(optss []TxOptions) (txOpts sql.TxOptions) {
readOnly := false
if len(optss) > 0 {
opts := optss[0]
- if opts.LockTimeout != 0 {
- lockTimeout = opts.LockTimeout
- }
- if opts.IdleInTxSessionTimeout != 0 {
- idleInTxSessionTimeout = opts.IdleInTxSessionTimeout
- }
- if opts.Isolation != 0 {
- txIsolation = opts.Isolation
- }
readOnly = opts.ReadOnly
}
txOpts = sql.TxOptions{
- Isolation: txIsolation,
- ReadOnly: readOnly,
+ ReadOnly: readOnly,
}
return
}
@@ -86,7 +69,7 @@ type TxBeginner interface {
}
func sqlxTransactionQ(ctx context.Context, db TxBeginner, lggr logger.Logger, fn func(q Queryer) error, optss ...TxOptions) (err error) {
- lockTimeout, idleInTxSessionTimeout, txOpts := applyDefaults(optss)
+ txOpts := applyDefaults(optss)
var tx *sqlx.Tx
tx, err = db.BeginTxx(ctx, &txOpts)
@@ -126,19 +109,6 @@ func sqlxTransactionQ(ctx context.Context, db TxBeginner, lggr logger.Logger, fn
}
}()
- if lockTimeout != defaultLockTimeout {
- _, err = tx.Exec(fmt.Sprintf(`SET LOCAL lock_timeout = %d`, lockTimeout.Milliseconds()))
- if err != nil {
- return errors.Wrap(err, "error setting transaction local lock_timeout")
- }
- }
- if idleInTxSessionTimeout != defaultIdleInTxSessionTimeout {
- _, err = tx.Exec(fmt.Sprintf(`SET LOCAL idle_in_transaction_session_timeout = %d`, idleInTxSessionTimeout.Milliseconds()))
- if err != nil {
- return errors.Wrap(err, "error setting transaction local idle_in_transaction_session_timeout")
- }
- }
-
err = fn(tx)
return
diff --git a/core/services/pg/utils.go b/core/services/pg/utils.go
index 5be2a4915b..eb53c26129 100644
--- a/core/services/pg/utils.go
+++ b/core/services/pg/utils.go
@@ -12,12 +12,6 @@ const (
DefaultQueryTimeout = 10 * time.Second
// longQueryTimeout is a bigger upper bound for how long a SQL query should take
longQueryTimeout = 1 * time.Minute
- // defaultLockTimeout controls the max time we will wait for any kind of database lock.
- // It's good to set this to _something_ because waiting for locks forever is really bad.
- defaultLockTimeout = 15 * time.Second
- // defaultIdleInTxSessionTimeout controls the max time we leave a transaction open and idle.
- // It's good to set this to _something_ because leaving transactions open forever is really bad.
- defaultIdleInTxSessionTimeout = 1 * time.Hour
)
var _ driver.Valuer = Limit(-1)
From b36d9ebe3f2e35ccbe26f7c83774e589b369d7fc Mon Sep 17 00:00:00 2001
From: Lukasz <120112546+lukaszcl@users.noreply.github.com>
Date: Tue, 14 Nov 2023 14:02:42 +0100
Subject: [PATCH 144/327] Add ReadBridges() to E2E tests core client (#11282)
---
integration-tests/client/chainlink.go | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go
index ef7bd06142..7d5825c261 100644
--- a/integration-tests/client/chainlink.go
+++ b/integration-tests/client/chainlink.go
@@ -302,6 +302,19 @@ func (c *ChainlinkClient) ReadBridge(name string) (*BridgeType, *http.Response,
return &bt, resp.RawResponse, err
}
+// ReadBridges reads bridges from the Chainlink node
+func (c *ChainlinkClient) ReadBridges() (*ResponseSlice, *resty.Response, error) {
+ result := &ResponseSlice{}
+ c.l.Info().Str(NodeURL, c.Config.URL).Msg("Getting all bridges")
+ resp, err := c.APIClient.R().
+ SetResult(&result).
+ Get("/v2/bridge_types")
+ if err != nil {
+ return nil, nil, err
+ }
+ return result, resp, err
+}
+
// DeleteBridge deletes a bridge on the Chainlink node based on the provided name
func (c *ChainlinkClient) DeleteBridge(name string) (*http.Response, error) {
c.l.Info().Str(NodeURL, c.Config.URL).Str("Name", name).Msg("Deleting Bridge")
From 7be17c91539f2db930ed339117b589d4f7d500eb Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Tue, 14 Nov 2023 07:30:49 -0600
Subject: [PATCH 145/327] core/utils: remove unused LazyLoad (#11277)
---
core/utils/lazy.go | 36 ---------------------
core/utils/lazy_test.go | 71 -----------------------------------------
2 files changed, 107 deletions(-)
delete mode 100644 core/utils/lazy.go
delete mode 100644 core/utils/lazy_test.go
diff --git a/core/utils/lazy.go b/core/utils/lazy.go
deleted file mode 100644
index 43e8480815..0000000000
--- a/core/utils/lazy.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package utils
-
-import (
- "sync"
-)
-
-type LazyLoad[T any] struct {
- f func() (T, error)
- state T
- ok bool
- lock sync.Mutex
-}
-
-func NewLazyLoad[T any](f func() (T, error)) *LazyLoad[T] {
- return &LazyLoad[T]{
- f: f,
- }
-}
-
-func (l *LazyLoad[T]) Get() (out T, err error) {
- l.lock.Lock()
- defer l.lock.Unlock()
-
- if l.ok {
- return l.state, nil
- }
- l.state, err = l.f()
- l.ok = err == nil
- return l.state, err
-}
-
-func (l *LazyLoad[T]) Reset() {
- l.lock.Lock()
- defer l.lock.Unlock()
- l.ok = false
-}
diff --git a/core/utils/lazy_test.go b/core/utils/lazy_test.go
deleted file mode 100644
index 88d02eea7f..0000000000
--- a/core/utils/lazy_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package utils
-
-import (
- "sync"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestLazyLoad(t *testing.T) {
- var clientwg sync.WaitGroup
-
- tc := func() (int, error) {
- clientwg.Done()
- return 10, nil
- }
-
- // Get should only request a client once, use cached afterward
- t.Run("get", func(t *testing.T) {
- clientwg.Add(1) // expect one call to get client
- c := NewLazyLoad(tc)
- rw, err := c.Get()
- assert.NoError(t, err)
- assert.NotNil(t, rw)
- assert.NotNil(t, c.state)
-
- // used cached client
- rw, err = c.Get()
- assert.NoError(t, err)
- assert.NotNil(t, rw)
- clientwg.Wait()
- })
-
- // Clear removes the cached client, should refetch
- t.Run("clear", func(t *testing.T) {
- clientwg.Add(2) // expect two calls to get client
-
- c := NewLazyLoad(tc)
- rw, err := c.Get()
- assert.NotNil(t, rw)
- assert.NoError(t, err)
-
- c.Reset()
-
- rw, err = c.Get()
- assert.NotNil(t, rw)
- assert.NoError(t, err)
- clientwg.Wait()
- })
-
- // Race checks a race condition of Getting and Clearing a new client
- t.Run("race", func(t *testing.T) {
- clientwg.Add(1) // expect one call to get client
-
- c := NewLazyLoad(tc)
- var wg sync.WaitGroup
- wg.Add(2)
- go func() {
- rw, err := c.Get()
- assert.NoError(t, err)
- assert.NotNil(t, rw)
- wg.Done()
- }()
- go func() {
- c.Reset()
- wg.Done()
- }()
- wg.Wait()
- clientwg.Wait()
- })
-}
From 9471f2eb833225310e90da93148e89650f15edfd Mon Sep 17 00:00:00 2001
From: ferglor <19188060+ferglor@users.noreply.github.com>
Date: Tue, 14 Nov 2023 15:12:12 +0000
Subject: [PATCH 146/327] Attempt to fix streams lookup race condition (#11284)
---
.../ocr2/plugins/ocr2keeper/evm21/streams_lookup.go | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
index fb2821a74b..af7ff42b93 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
@@ -151,11 +151,13 @@ func (r *EvmRegistry) streamsLookup(ctx context.Context, checkResults []ocr2keep
var wg sync.WaitGroup
for i, lookup := range lookups {
- i := i
wg.Add(1)
- r.threadCtrl.Go(func(ctx context.Context) {
- r.doLookup(ctx, &wg, lookup, i, checkResults, lggr)
- })
+ func(i int, lookup *StreamsLookup) {
+ r.threadCtrl.Go(func(ctx context.Context) {
+ r.doLookup(ctx, &wg, lookup, i, checkResults, lggr)
+ })
+ }(i, lookup)
+
}
wg.Wait()
From 039ffa93794203bd0b0f8f43278fb49f53aa597e Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Tue, 14 Nov 2023 11:56:17 -0500
Subject: [PATCH 147/327] [Functions] Use @eth-optimism/contracts-bedrock
GasPriceOracle (#11275)
* (chore): Add @eth-optimism/contracts-bedrock v0.16.2 to vendor
* Use GasPriceOracle in Functions ChainSpecificUtil
---
.../dev/v1_X/libraries/ChainSpecificUtil.sol | 8 +-
.../v0.16.2/src/L2/GasPriceOracle.sol | 99 +++++++++++++++++++
.../v0.16.2/src/L2/L1Block.sol | 76 ++++++++++++++
.../v0.16.2/src/libraries/Predeploys.sol | 77 +++++++++++++++
.../v0.16.2/src/universal/ISemver.sol | 13 +++
5 files changed, 269 insertions(+), 4 deletions(-)
create mode 100644 contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol
create mode 100644 contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol
create mode 100644 contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol
create mode 100644 contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol
diff --git a/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol b/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol
index d6569a256b..574d1bf164 100644
--- a/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol
+++ b/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.19;
import {ArbGasInfo} from "../../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
-import {OVM_GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
+import {GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol";
/// @dev A library that abstracts out opcodes that behave differently across chains.
/// @dev The methods below return values that are pertinent to the given chain.
@@ -24,10 +24,10 @@ library ChainSpecificUtil {
/// @dev L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism
bytes internal constant L1_FEE_DATA_PADDING =
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
- /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_GasPriceOracle precompile on Optimism.
+ /// @dev OVM_GASPRICEORACLE_ADDR is the address of the GasPriceOracle precompile on Optimism.
/// @dev reference: https://community.optimism.io/docs/developers/build/transaction-fees/#estimating-the-l1-data-fee
address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
- OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR);
+ GasPriceOracle private constant OVM_GASPRICEORACLE = GasPriceOracle(OVM_GASPRICEORACLE_ADDR);
uint256 private constant OP_MAINNET_CHAIN_ID = 10;
uint256 private constant OP_GOERLI_CHAIN_ID = 420;
@@ -44,7 +44,7 @@ library ChainSpecificUtil {
/// @notice for the current transaction.
/// @notice When on a known Arbitrum chain, it uses ArbGas.getCurrentTxL1GasFees to get the fees.
/// @notice On Arbitrum, the provided calldata is not used to calculate the fees.
- /// @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy
+ /// @notice On Optimism, the provided calldata is passed to the GasPriceOracle predeploy
/// @notice and getL1Fee is called to get the fees.
function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256 l1FeeWei) {
uint256 chainid = block.chainid;
diff --git a/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol
new file mode 100644
index 0000000000..aebc1f747a
--- /dev/null
+++ b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.15;
+
+import { ISemver } from "../universal/ISemver.sol";
+import { Predeploys } from "../libraries/Predeploys.sol";
+import { L1Block } from "./L1Block.sol";
+
+/// @custom:proxied
+/// @custom:predeploy 0x420000000000000000000000000000000000000F
+/// @title GasPriceOracle
+/// @notice This contract maintains the variables responsible for computing the L1 portion of the
+/// total fee charged on L2. Before Bedrock, this contract held variables in state that were
+/// read during the state transition function to compute the L1 portion of the transaction
+/// fee. After Bedrock, this contract now simply proxies the L1Block contract, which has
+/// the values used to compute the L1 portion of the fee in its state.
+///
+/// The contract exposes an API that is useful for knowing how large the L1 portion of the
+/// transaction fee will be. The following events were deprecated with Bedrock:
+/// - event OverheadUpdated(uint256 overhead);
+/// - event ScalarUpdated(uint256 scalar);
+/// - event DecimalsUpdated(uint256 decimals);
+contract GasPriceOracle is ISemver {
+ /// @notice Number of decimals used in the scalar.
+ uint256 public constant DECIMALS = 6;
+
+ /// @notice Semantic version.
+ /// @custom:semver 1.1.0
+ string public constant version = "1.1.0";
+
+ /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input
+ /// transaction, the current L1 base fee, and the various dynamic parameters.
+ /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.
+ /// @return L1 fee that should be paid for the tx
+ function getL1Fee(bytes memory _data) external view returns (uint256) {
+ uint256 l1GasUsed = getL1GasUsed(_data);
+ uint256 l1Fee = l1GasUsed * l1BaseFee();
+ uint256 divisor = 10 ** DECIMALS;
+ uint256 unscaled = l1Fee * scalar();
+ uint256 scaled = unscaled / divisor;
+ return scaled;
+ }
+
+ /// @notice Retrieves the current gas price (base fee).
+ /// @return Current L2 gas price (base fee).
+ function gasPrice() public view returns (uint256) {
+ return block.basefee;
+ }
+
+ /// @notice Retrieves the current base fee.
+ /// @return Current L2 base fee.
+ function baseFee() public view returns (uint256) {
+ return block.basefee;
+ }
+
+ /// @notice Retrieves the current fee overhead.
+ /// @return Current fee overhead.
+ function overhead() public view returns (uint256) {
+ return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();
+ }
+
+ /// @notice Retrieves the current fee scalar.
+ /// @return Current fee scalar.
+ function scalar() public view returns (uint256) {
+ return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();
+ }
+
+ /// @notice Retrieves the latest known L1 base fee.
+ /// @return Latest known L1 base fee.
+ function l1BaseFee() public view returns (uint256) {
+ return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();
+ }
+
+ /// @custom:legacy
+ /// @notice Retrieves the number of decimals used in the scalar.
+ /// @return Number of decimals used in the scalar.
+ function decimals() public pure returns (uint256) {
+ return DECIMALS;
+ }
+
+ /// @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which
+ /// represents the per-transaction gas overhead of posting the transaction and state
+ /// roots to L1. Adds 68 bytes of padding to account for the fact that the input does
+ /// not have a signature.
+ /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.
+ /// @return Amount of L1 gas used to publish the transaction.
+ function getL1GasUsed(bytes memory _data) public view returns (uint256) {
+ uint256 total = 0;
+ uint256 length = _data.length;
+ for (uint256 i = 0; i < length; i++) {
+ if (_data[i] == 0) {
+ total += 4;
+ } else {
+ total += 16;
+ }
+ }
+ uint256 unsigned = total + overhead();
+ return unsigned + (68 * 16);
+ }
+}
\ No newline at end of file
diff --git a/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol
new file mode 100644
index 0000000000..7722b53b30
--- /dev/null
+++ b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.15;
+
+import { ISemver } from "../universal/ISemver.sol";
+
+/// @custom:proxied
+/// @custom:predeploy 0x4200000000000000000000000000000000000015
+/// @title L1Block
+/// @notice The L1Block predeploy gives users access to information about the last known L1 block.
+/// Values within this contract are updated once per epoch (every L1 block) and can only be
+/// set by the "depositor" account, a special system address. Depositor account transactions
+/// are created by the protocol whenever we move to a new epoch.
+contract L1Block is ISemver {
+ /// @notice Address of the special depositor account.
+ address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;
+
+ /// @notice The latest L1 block number known by the L2 system.
+ uint64 public number;
+
+ /// @notice The latest L1 timestamp known by the L2 system.
+ uint64 public timestamp;
+
+ /// @notice The latest L1 basefee.
+ uint256 public basefee;
+
+ /// @notice The latest L1 blockhash.
+ bytes32 public hash;
+
+ /// @notice The number of L2 blocks in the same epoch.
+ uint64 public sequenceNumber;
+
+ /// @notice The versioned hash to authenticate the batcher by.
+ bytes32 public batcherHash;
+
+ /// @notice The overhead value applied to the L1 portion of the transaction fee.
+ uint256 public l1FeeOverhead;
+
+ /// @notice The scalar value applied to the L1 portion of the transaction fee.
+ uint256 public l1FeeScalar;
+
+ /// @custom:semver 1.1.0
+ string public constant version = "1.1.0";
+
+ /// @notice Updates the L1 block values.
+ /// @param _number L1 blocknumber.
+ /// @param _timestamp L1 timestamp.
+ /// @param _basefee L1 basefee.
+ /// @param _hash L1 blockhash.
+ /// @param _sequenceNumber Number of L2 blocks since epoch start.
+ /// @param _batcherHash Versioned hash to authenticate batcher by.
+ /// @param _l1FeeOverhead L1 fee overhead.
+ /// @param _l1FeeScalar L1 fee scalar.
+ function setL1BlockValues(
+ uint64 _number,
+ uint64 _timestamp,
+ uint256 _basefee,
+ bytes32 _hash,
+ uint64 _sequenceNumber,
+ bytes32 _batcherHash,
+ uint256 _l1FeeOverhead,
+ uint256 _l1FeeScalar
+ )
+ external
+ {
+ require(msg.sender == DEPOSITOR_ACCOUNT, "L1Block: only the depositor account can set L1 block values");
+
+ number = _number;
+ timestamp = _timestamp;
+ basefee = _basefee;
+ hash = _hash;
+ sequenceNumber = _sequenceNumber;
+ batcherHash = _batcherHash;
+ l1FeeOverhead = _l1FeeOverhead;
+ l1FeeScalar = _l1FeeScalar;
+ }
+}
\ No newline at end of file
diff --git a/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol
new file mode 100644
index 0000000000..4a0d399ce7
--- /dev/null
+++ b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+/// @title Predeploys
+/// @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.
+library Predeploys {
+ /// @notice Address of the L2ToL1MessagePasser predeploy.
+ address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;
+
+ /// @notice Address of the L2CrossDomainMessenger predeploy.
+ address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007;
+
+ /// @notice Address of the L2StandardBridge predeploy.
+ address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;
+
+ /// @notice Address of the L2ERC721Bridge predeploy.
+ address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;
+
+ //// @notice Address of the SequencerFeeWallet predeploy.
+ address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;
+
+ /// @notice Address of the OptimismMintableERC20Factory predeploy.
+ address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012;
+
+ /// @notice Address of the OptimismMintableERC721Factory predeploy.
+ address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017;
+
+ /// @notice Address of the L1Block predeploy.
+ address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;
+
+ /// @notice Address of the GasPriceOracle predeploy. Includes fee information
+ /// and helpers for computing the L1 portion of the transaction fee.
+ address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;
+
+ /// @custom:legacy
+ /// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger
+ /// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.
+ address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;
+
+ /// @custom:legacy
+ /// @notice Address of the DeployerWhitelist predeploy. No longer active.
+ address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;
+
+ /// @custom:legacy
+ /// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the
+ /// state trie as of the Bedrock upgrade. Contract has been locked and write functions
+ /// can no longer be accessed.
+ address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;
+
+ /// @custom:legacy
+ /// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy
+ /// instead, which exposes more information about the L1 state.
+ address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;
+
+ /// @custom:legacy
+ /// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated
+ /// L2ToL1MessagePasser contract instead.
+ address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;
+
+ /// @notice Address of the ProxyAdmin predeploy.
+ address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;
+
+ /// @notice Address of the BaseFeeVault predeploy.
+ address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;
+
+ /// @notice Address of the L1FeeVault predeploy.
+ address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;
+
+ /// @notice Address of the GovernanceToken predeploy.
+ address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;
+
+ /// @notice Address of the SchemaRegistry predeploy.
+ address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020;
+
+ /// @notice Address of the EAS predeploy.
+ address internal constant EAS = 0x4200000000000000000000000000000000000021;
+}
\ No newline at end of file
diff --git a/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol
new file mode 100644
index 0000000000..ae9569a050
--- /dev/null
+++ b/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+/// @title ISemver
+/// @notice ISemver is a simple contract for ensuring that contracts are
+/// versioned using semantic versioning.
+interface ISemver {
+ /// @notice Getter for the semantic version of the contract. This is not
+ /// meant to be used onchain but instead meant to be used by offchain
+ /// tooling.
+ /// @return Semver contract version as a string.
+ function version() external view returns (string memory);
+}
\ No newline at end of file
From 5bcd414622294d8142e6cfff08f8c1b0c2dc72df Mon Sep 17 00:00:00 2001
From: Ilja Pavlovs
Date: Tue, 14 Nov 2023 15:26:34 -0400
Subject: [PATCH 148/327] =?UTF-8?q?VRF-749:=20updating=20setup-env=20scrip?=
=?UTF-8?q?t=20for=20VRF=20to=20include=20chainId=20when=20cr=E2=80=A6=20(?=
=?UTF-8?q?#11286)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* VRF-749: updating setup-env script for VRF to include chainId when creating eth keys; README update
* VRF-749: updating README.md
---
core/scripts/common/vrf/setup-envs/README.md | 83 ++++++++++++++++++--
core/scripts/common/vrf/setup-envs/main.go | 2 +
2 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/core/scripts/common/vrf/setup-envs/README.md b/core/scripts/common/vrf/setup-envs/README.md
index f3b391f0ee..9aa76ffbbb 100644
--- a/core/scripts/common/vrf/setup-envs/README.md
+++ b/core/scripts/common/vrf/setup-envs/README.md
@@ -15,6 +15,7 @@ export ETH_CHAIN_ID=
export ACCOUNT_KEY=
```
5. execute from `core/scripts/common/vrf/setup-envs` folder
+ * `--vrf-version` - "v2" or "v2plus"
```
go run . \
--vrf-version="v2plus" \
@@ -28,24 +29,96 @@ go run . \
--bhs-bk-creds-file \
--bhf-node-url=http://localhost:6614 \
--bhf-creds-file \
+--num-eth-keys=1 \
+--num-vrf-keys=1 \
+--sending-key-funding-amount="1e17" \
--deploy-contracts-and-create-jobs="true" \
--subscription-balance="1e19" \
--subscription-balance-native="1e18" \
--batch-fulfillment-enabled="true" \
--min-confs=3 \
---num-eth-keys=1 \
---num-vrf-keys=1 \
---sending-key-funding-amount="1e17" \
--register-vrf-key-against-address=
```
-Optional parameters - will not be deployed if specified (NOT WORKING YET)
+Optional parameters - will not be deployed if specified
```
--link-address \
--link-eth-feed \
+```
+
+WIP - Not working yet:
+```
--bhs-address \
--batch-bhs-address \
--coordinator-address \
--batch-coordinator-address
-```
\ No newline at end of file
+```
+
+
+## Process Example
+
+1. If the CL nodes do not have needed amount of ETH and VRF keys, you need to create them first:
+```
+go run . \
+--vrf-version="v2" \
+--vrf-primary-node-url= \
+--vrf-primary-creds-file \
+--bhs-node-url= \
+--bhs-creds-file \
+--num-eth-keys=3 \
+--num-vrf-keys=1 \
+--sending-key-funding-amount="1e17" \
+--deploy-contracts-and-create-jobs="false"
+```
+Then update corresponding deployment scripts with the new ETH addresses, specifying max gas price for each key
+
+e.g.:
+```
+[[EVM.KeySpecific]]
+Key = ''
+GasEstimator.PriceMax = '30 gwei'
+```
+
+2. If the CL nodes already have needed amount of ETH and VRF keys, you can deploy contracts and create jobs with the following command:
+NOTE - nodes will be funded at least to the amount specified in `--sending-key-funding-amount` parameter.
+```
+go run . \
+--vrf-version="v2" \
+--vrf-primary-node-url= \
+--vrf-primary-creds-file \
+--bhs-node-url= \
+--bhs-creds-file \
+--num-eth-keys=3 \
+--num-vrf-keys=1 \
+--sending-key-funding-amount="1e17" \
+--deploy-contracts-and-create-jobs="true" \
+--subscription-balance="1e19" \
+--subscription-balance-native="1e18" \
+--batch-fulfillment-enabled="true" \
+--min-confs=3 \
+--register-vrf-key-against-address="" \
+--link-address "" \
+--link-eth-feed ""
+```
+
+
+3. We can run sample rand request to see if the setup works.
+ After previous script was done, we should see the command to run in the console:
+
+ e.g. to trigger rand request:
+ 1. navigate to `core/scripts/vrfv2plus/testnet` or `core/scripts/vrfv2/testnet` folder
+ 2. set needed env variables
+ ```
+ export ETH_URL=
+ export ETH_CHAIN_ID=
+ export ACCOUNT_KEY=
+ ```
+ 3. Trigger rand request (get this command from the console after running `setup-envs` script )
+ ```bash
+ go run . eoa-load-test-request-with-metrics --consumer-address= --sub-id=1 --key-hash= --request-confirmations <> --requests 1 --runs 1 --cb-gas-limit 1_000_000
+ ```
+ 4. Then to check that rand request was fulfilled (get this command from the console after running `setup-envs` script )
+ ```bash
+ go run . eoa-load-test-read-metrics --consumer-address=
+ ```
\ No newline at end of file
diff --git a/core/scripts/common/vrf/setup-envs/main.go b/core/scripts/common/vrf/setup-envs/main.go
index 7c2530ffd4..94662aa183 100644
--- a/core/scripts/common/vrf/setup-envs/main.go
+++ b/core/scripts/common/vrf/setup-envs/main.go
@@ -506,6 +506,8 @@ func createETHKeysIfNeeded(client *clcmd.Shell, app *cli.App, output *bytes.Buff
if *maxGasPriceGwei > 0 {
helpers.PanicErr(flagSet.Set("max-gas-price-gwei", fmt.Sprintf("%d", *maxGasPriceGwei)))
}
+ err := flagSet.Parse([]string{"-evm-chain-id", os.Getenv("ETH_CHAIN_ID")})
+ helpers.PanicErr(err)
err = client.CreateETHKey(cli.NewContext(app, flagSet, nil))
helpers.PanicErr(err)
helpers.PanicErr(json.Unmarshal(output.Bytes(), &newKey))
From e7e0d42ee76ddc019abae7072187e99f98ba699e Mon Sep 17 00:00:00 2001
From: Tate
Date: Tue, 14 Nov 2023 13:53:54 -0700
Subject: [PATCH 149/327] [TT-707] chainlink-tests image build workflow
dispatch (#11288)
---
.github/actions/build-test-image/action.yml | 6 +++++-
.../workflows/integration-tests-publish.yml | 20 +++++++++++++++----
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml
index a241f51d92..252b292d03 100644
--- a/.github/actions/build-test-image/action.yml
+++ b/.github/actions/build-test-image/action.yml
@@ -17,6 +17,9 @@ inputs:
description: The test suites to build into the image
default: chaos migration performance reorg smoke soak benchmark
required: false
+ base_image_tag:
+ description: The test base image version to use, if not provided it will use the version from the ./integration-tests/go.mod file
+ required: false
QA_AWS_ROLE_TO_ASSUME:
description: The AWS role to assume as the CD user, if any. Used in configuring the docker/login-action
required: true
@@ -31,6 +34,7 @@ runs:
using: composite
steps:
- name: Get CTF Version
+ if: ${{ inputs.base_image_tag == '' }}
id: version
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
@@ -55,7 +59,7 @@ runs:
file: ./integration-tests/test.Dockerfile
build-args: |
BASE_IMAGE=${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image
- IMAGE_VERSION=${{ steps.version.outputs.version }}
+ IMAGE_VERSION=${{ inputs.base_image_tag || steps.version.outputs.version }}
SUITES="${{ inputs.suites }}"
AWS_REGION: ${{ inputs.QA_AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml
index a66ea61228..9579b83b98 100644
--- a/.github/workflows/integration-tests-publish.yml
+++ b/.github/workflows/integration-tests-publish.yml
@@ -5,9 +5,20 @@ on:
push:
branches:
- develop
+ workflow_dispatch:
+ inputs:
+ chainlink-tests-tag:
+ description: 'The tag to be pushed'
+ required: true
+ ctf-base-image-tag:
+ description: |
+ 'The tag of the CTF base image to be used,
+ typically something like v1.18.6 from https://github.com/smartcontractkit/chainlink-testing-framework/releases
+ or a custom tag or branch you have pushed.'
+ required: true
env:
- ECR_TAG: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:develop
+ ECR_TAG_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests
jobs:
publish-integration-test-image:
@@ -16,7 +27,7 @@ jobs:
id-token: write
contents: read
name: Publish Integration Test Image
- runs-on: ubuntu-latest
+ runs-on: ubuntu20.04-16cores-64GB
steps:
- name: Collect Metrics
id: collect-gha-metrics
@@ -29,11 +40,12 @@ jobs:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
- ref: ${{ github.event.pull_request.head.sha }}
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Build Image
uses: ./.github/actions/build-test-image
with:
- other_tags: ${{ env.ECR_TAG }}
+ other_tags: "${{ env.ECR_TAG_BASE }}:${{ inputs.chainlink-tests-tag || 'develop' }}"
+ base_image_tag: ${{ inputs.ctf-base-image-tag }}
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 }}
From 3a38e9052fa49df94fe309efa719ef44268f5545 Mon Sep 17 00:00:00 2001
From: Bolek <1416262+bolekk@users.noreply.github.com>
Date: Tue, 14 Nov 2023 16:21:09 -0800
Subject: [PATCH 150/327] [Functions] Offchain heartbeat support in Listener
and OCR2 plugin (#11274)
1. Add new API structs
2. Mark offchain requests in Listener
3. Introduce a simple OffchainTransmitter to pass responses from the plugin
---
core/services/functions/listener.go | 42 +++++++++++++
core/services/functions/listener_test.go | 40 +++++++++++++
.../functions/mocks/offchain_transmitter.go | 59 ++++++++++++++++++
.../functions/offchain_transmitter.go | 39 ++++++++++++
.../functions/offchain_transmitter_test.go | 31 ++++++++++
core/services/functions/request.go | 15 +++++
.../services/ocr2/plugins/functions/plugin.go | 17 +++---
.../ocr2/plugins/functions/reporting.go | 48 +++++++++------
.../ocr2/plugins/functions/reporting_test.go | 60 +++++++++++++------
9 files changed, 308 insertions(+), 43 deletions(-)
create mode 100644 core/services/functions/mocks/offchain_transmitter.go
create mode 100644 core/services/functions/offchain_transmitter.go
create mode 100644 core/services/functions/offchain_transmitter_test.go
diff --git a/core/services/functions/listener.go b/core/services/functions/listener.go
index 773ae61040..5614c5331d 100644
--- a/core/services/functions/listener.go
+++ b/core/services/functions/listener.go
@@ -111,6 +111,9 @@ const (
DefaultPruneCheckFrequencySec uint32 = 60 * 10
DefaultPruneBatchSize uint32 = 500
+ // Used in place of OnchainMetadata for all offchain requests.
+ OffchainRequestMarker string = "OFFCHAIN_REQUEST"
+
FlagCBORMaxSize uint32 = 1
FlagSecretsMaxSize uint32 = 2
)
@@ -280,6 +283,45 @@ func (l *FunctionsListener) getMaxSecretsSize(flags RequestFlags) uint32 {
return l.pluginConfig.MaxSecretsSizesList[idx]
}
+func (l *FunctionsListener) HandleOffchainRequest(ctx context.Context, request *OffchainRequest) error {
+ if request == nil {
+ return errors.New("HandleOffchainRequest: received nil request")
+ }
+ if len(request.RequestId) != RequestIDLength {
+ return fmt.Errorf("HandleOffchainRequest: invalid request ID length %d", len(request.RequestId))
+ }
+ if len(request.SubscriptionOwner) != common.AddressLength || len(request.RequestInitiator) != common.AddressLength {
+ return fmt.Errorf("HandleOffchainRequest: SubscriptionOwner and RequestInitiator must be set to valid addresses")
+ }
+
+ var requestId RequestID
+ copy(requestId[:], request.RequestId[:32])
+ subscriptionOwner := common.BytesToAddress(request.SubscriptionOwner)
+ senderAddr := common.BytesToAddress(request.RequestInitiator)
+ emptyTxHash := common.Hash{}
+ zeroCallbackGasLimit := uint32(0)
+ newReq := &Request{
+ RequestID: requestId,
+ RequestTxHash: &emptyTxHash,
+ ReceivedAt: time.Now(),
+ Flags: []byte{},
+ CallbackGasLimit: &zeroCallbackGasLimit,
+ // use sender address in place of coordinator contract to keep batches uniform
+ CoordinatorContractAddress: &senderAddr,
+ OnchainMetadata: []byte(OffchainRequestMarker),
+ }
+ if err := l.pluginORM.CreateRequest(newReq, pg.WithParentCtx(ctx)); err != nil {
+ if errors.Is(err, ErrDuplicateRequestID) {
+ l.logger.Warnw("HandleOffchainRequest: received duplicate request ID", "requestID", formatRequestId(requestId), "err", err)
+ } else {
+ l.logger.Errorw("HandleOffchainRequest: failed to create a DB entry for new request", "requestID", formatRequestId(requestId), "err", err)
+ }
+ return err
+ }
+ l.handleRequest(ctx, requestId, request.SubscriptionId, subscriptionOwner, RequestFlags{}, &request.Data)
+ return nil
+}
+
func (l *FunctionsListener) handleOracleRequestV1(request *evmrelayTypes.OracleRequest) {
defer l.shutdownWaitGroup.Done()
l.logger.Infow("handleOracleRequestV1: oracle request v1 received", "requestID", formatRequestId(request.RequestId))
diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go
index 3b7ed46988..ac2bc64184 100644
--- a/core/services/functions/listener_test.go
+++ b/core/services/functions/listener_test.go
@@ -179,6 +179,46 @@ func TestFunctionsListener_HandleOracleRequestV1_Success(t *testing.T) {
uni.service.Close()
}
+func TestFunctionsListener_HandleOffchainRequest_Success(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.bridgeAccessor.On("NewExternalAdapterClient").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", RequestID, ResultBytes, mock.Anything, mock.Anything).Return(nil)
+
+ request := &functions_service.OffchainRequest{
+ RequestId: RequestID[:],
+ RequestInitiator: SubscriptionOwner.Bytes(),
+ SubscriptionId: uint64(SubscriptionID),
+ SubscriptionOwner: SubscriptionOwner.Bytes(),
+ Data: functions_service.RequestData{},
+ }
+ require.NoError(t, uni.service.HandleOffchainRequest(testutils.Context(t), request))
+}
+
+func TestFunctionsListener_HandleOffchainRequest_Invalid(t *testing.T) {
+ testutils.SkipShortDB(t)
+ t.Parallel()
+ uni := NewFunctionsListenerUniverse(t, 0, 1_000_000)
+
+ request := &functions_service.OffchainRequest{
+ RequestId: RequestID[:],
+ RequestInitiator: []byte("invalid_address"),
+ SubscriptionId: uint64(SubscriptionID),
+ SubscriptionOwner: SubscriptionOwner.Bytes(),
+ Data: functions_service.RequestData{},
+ }
+ require.Error(t, uni.service.HandleOffchainRequest(testutils.Context(t), request))
+
+ request.RequestInitiator = SubscriptionOwner.Bytes()
+ request.SubscriptionOwner = []byte("invalid_address")
+ require.Error(t, uni.service.HandleOffchainRequest(testutils.Context(t), request))
+}
+
func TestFunctionsListener_HandleOracleRequestV1_ComputationError(t *testing.T) {
testutils.SkipShortDB(t)
t.Parallel()
diff --git a/core/services/functions/mocks/offchain_transmitter.go b/core/services/functions/mocks/offchain_transmitter.go
new file mode 100644
index 0000000000..d9a7be04dd
--- /dev/null
+++ b/core/services/functions/mocks/offchain_transmitter.go
@@ -0,0 +1,59 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ functions "github.com/smartcontractkit/chainlink/v2/core/services/functions"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// OffchainTransmitter is an autogenerated mock type for the OffchainTransmitter type
+type OffchainTransmitter struct {
+ mock.Mock
+}
+
+// ReportChannel provides a mock function with given fields:
+func (_m *OffchainTransmitter) ReportChannel() chan *functions.OffchainResponse {
+ ret := _m.Called()
+
+ var r0 chan *functions.OffchainResponse
+ if rf, ok := ret.Get(0).(func() chan *functions.OffchainResponse); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(chan *functions.OffchainResponse)
+ }
+ }
+
+ return r0
+}
+
+// TransmitReport provides a mock function with given fields: ctx, report
+func (_m *OffchainTransmitter) TransmitReport(ctx context.Context, report *functions.OffchainResponse) error {
+ ret := _m.Called(ctx, report)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *functions.OffchainResponse) error); ok {
+ r0 = rf(ctx, report)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// NewOffchainTransmitter creates a new instance of OffchainTransmitter. 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 NewOffchainTransmitter(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *OffchainTransmitter {
+ mock := &OffchainTransmitter{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/core/services/functions/offchain_transmitter.go b/core/services/functions/offchain_transmitter.go
new file mode 100644
index 0000000000..63527937f9
--- /dev/null
+++ b/core/services/functions/offchain_transmitter.go
@@ -0,0 +1,39 @@
+package functions
+
+import (
+ "context"
+
+ "github.com/pkg/errors"
+)
+
+// Simple wrapper around a channel to transmit offchain reports between
+// OCR plugin and Gateway connector
+//
+//go:generate mockery --quiet --name OffchainTransmitter --output ./mocks/ --case=underscore
+type OffchainTransmitter interface {
+ TransmitReport(ctx context.Context, report *OffchainResponse) error
+ ReportChannel() chan *OffchainResponse
+}
+
+type offchainTransmitter struct {
+ reportCh chan *OffchainResponse
+}
+
+func NewOffchainTransmitter(chanSize uint32) OffchainTransmitter {
+ return &offchainTransmitter{
+ reportCh: make(chan *OffchainResponse, chanSize),
+ }
+}
+
+func (t *offchainTransmitter) TransmitReport(ctx context.Context, report *OffchainResponse) error {
+ select {
+ case t.reportCh <- report:
+ return nil
+ case <-ctx.Done():
+ return errors.New("context cancelled")
+ }
+}
+
+func (t *offchainTransmitter) ReportChannel() chan *OffchainResponse {
+ return t.reportCh
+}
diff --git a/core/services/functions/offchain_transmitter_test.go b/core/services/functions/offchain_transmitter_test.go
new file mode 100644
index 0000000000..bec639bf27
--- /dev/null
+++ b/core/services/functions/offchain_transmitter_test.go
@@ -0,0 +1,31 @@
+package functions_test
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/core/services/functions"
+)
+
+func TestOffchainTransmitter(t *testing.T) {
+ t.Parallel()
+
+ transmitter := functions.NewOffchainTransmitter(1)
+ ch := transmitter.ReportChannel()
+ report := &functions.OffchainResponse{RequestId: []byte("testID")}
+ ctx := testutils.Context(t)
+
+ require.NoError(t, transmitter.TransmitReport(ctx, report))
+ require.Equal(t, report, <-ch)
+
+ require.NoError(t, transmitter.TransmitReport(ctx, report))
+
+ ctxTimeout, cancel := context.WithTimeout(ctx, time.Millisecond*20)
+ defer cancel()
+ // should not freeze
+ require.Error(t, transmitter.TransmitReport(ctxTimeout, report))
+}
diff --git a/core/services/functions/request.go b/core/services/functions/request.go
index 181058b83d..14c0b0d0e5 100644
--- a/core/services/functions/request.go
+++ b/core/services/functions/request.go
@@ -9,6 +9,14 @@ const (
type RequestFlags [32]byte
+type OffchainRequest struct {
+ RequestId []byte `json:"requestId"`
+ RequestInitiator []byte `json:"requestInitiator"`
+ SubscriptionId uint64 `json:"subscriptionId"`
+ SubscriptionOwner []byte `json:"subscriptionOwner"`
+ Data RequestData `json:"data"`
+}
+
type RequestData struct {
Source string `json:"source" cbor:"source"`
Language int `json:"language" cbor:"language"`
@@ -19,6 +27,13 @@ type RequestData struct {
BytesArgs [][]byte `json:"bytesArgs,omitempty" cbor:"bytesArgs"`
}
+// NOTE: to be extended with raw report and signatures when needed
+type OffchainResponse struct {
+ RequestId []byte `json:"requestId"`
+ Result []byte `json:"result"`
+ Error []byte `json:"error"`
+}
+
type DONHostedSecrets struct {
SlotID uint `json:"slotId" cbor:"slotId"`
Version uint64 `json:"version" cbor:"version"`
diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go
index 26cffac5ab..8597b8ad4c 100644
--- a/core/services/ocr2/plugins/functions/plugin.go
+++ b/core/services/ocr2/plugins/functions/plugin.go
@@ -50,9 +50,10 @@ type FunctionsServicesConfig struct {
}
const (
- FunctionsBridgeName string = "ea_bridge"
- FunctionsS4Namespace string = "functions"
- MaxAdapterResponseBytes int64 = 1_000_000
+ FunctionsBridgeName string = "ea_bridge"
+ FunctionsS4Namespace string = "functions"
+ MaxAdapterResponseBytes int64 = 1_000_000
+ DefaultOffchainTransmitterChannelSize uint32 = 1000
)
// Create all OCR2 plugin Oracles and all extra services needed to run a Functions job.
@@ -100,6 +101,7 @@ func NewFunctionsServices(functionsOracleArgs, thresholdOracleArgs, s4OracleArgs
s4Storage = s4.NewStorage(conf.Logger, *pluginConfig.S4Constraints, s4ORM, utils.NewRealClock())
}
+ offchainTransmitter := functions.NewOffchainTransmitter(DefaultOffchainTransmitterChannelSize)
listenerLogger := conf.Logger.Named("FunctionsListener")
bridgeAccessor := functions.NewBridgeAccessor(conf.BridgeORM, FunctionsBridgeName, MaxAdapterResponseBytes)
functionsListener := functions.NewFunctionsListener(
@@ -118,10 +120,11 @@ func NewFunctionsServices(functionsOracleArgs, thresholdOracleArgs, s4OracleArgs
allServices = append(allServices, functionsListener)
functionsOracleArgs.ReportingPluginFactory = FunctionsReportingPluginFactory{
- Logger: functionsOracleArgs.Logger,
- PluginORM: pluginORM,
- JobID: conf.Job.ExternalJobID,
- ContractVersion: pluginConfig.ContractVersion,
+ Logger: functionsOracleArgs.Logger,
+ PluginORM: pluginORM,
+ JobID: conf.Job.ExternalJobID,
+ ContractVersion: pluginConfig.ContractVersion,
+ OffchainTransmitter: offchainTransmitter,
}
functionsReportingPluginOracle, err := libocr2.NewOracle(*functionsOracleArgs)
if err != nil {
diff --git a/core/services/ocr2/plugins/functions/reporting.go b/core/services/ocr2/plugins/functions/reporting.go
index dfa8f575d1..36e8a88273 100644
--- a/core/services/ocr2/plugins/functions/reporting.go
+++ b/core/services/ocr2/plugins/functions/reporting.go
@@ -1,6 +1,7 @@
package functions
import (
+ "bytes"
"context"
"fmt"
@@ -21,22 +22,24 @@ import (
)
type FunctionsReportingPluginFactory struct {
- Logger commontypes.Logger
- PluginORM functions.ORM
- JobID uuid.UUID
- ContractVersion uint32
+ Logger commontypes.Logger
+ PluginORM functions.ORM
+ JobID uuid.UUID
+ ContractVersion uint32
+ OffchainTransmitter functions.OffchainTransmitter
}
var _ types.ReportingPluginFactory = (*FunctionsReportingPluginFactory)(nil)
type functionsReporting struct {
- logger commontypes.Logger
- pluginORM functions.ORM
- jobID uuid.UUID
- reportCodec encoding.ReportCodec
- genericConfig *types.ReportingPluginConfig
- specificConfig *config.ReportingPluginConfigWrapper
- contractVersion uint32
+ logger commontypes.Logger
+ pluginORM functions.ORM
+ jobID uuid.UUID
+ reportCodec encoding.ReportCodec
+ genericConfig *types.ReportingPluginConfig
+ specificConfig *config.ReportingPluginConfigWrapper
+ contractVersion uint32
+ offchainTransmitter functions.OffchainTransmitter
}
var _ types.ReportingPlugin = &functionsReporting{}
@@ -112,13 +115,14 @@ func (f FunctionsReportingPluginFactory) NewReportingPlugin(rpConfig types.Repor
},
}
plugin := functionsReporting{
- logger: f.Logger,
- pluginORM: f.PluginORM,
- jobID: f.JobID,
- reportCodec: codec,
- genericConfig: &rpConfig,
- specificConfig: pluginConfig,
- contractVersion: f.ContractVersion,
+ logger: f.Logger,
+ pluginORM: f.PluginORM,
+ jobID: f.JobID,
+ reportCodec: codec,
+ genericConfig: &rpConfig,
+ specificConfig: pluginConfig,
+ contractVersion: f.ContractVersion,
+ offchainTransmitter: f.OffchainTransmitter,
}
promReportingPlugins.WithLabelValues(f.JobID.String()).Inc()
return &plugin, info, nil
@@ -437,6 +441,14 @@ func (r *functionsReporting) ShouldAcceptFinalizedReport(ctx context.Context, ts
r.logger.Debug("FunctionsReporting ShouldAcceptFinalizedReport: state couldn't be changed to FINALIZED. Not transmitting.", commontypes.LogFields{"requestID": reqIdStr, "err": err})
continue
}
+ if bytes.Equal(item.OnchainMetadata, []byte(functions.OffchainRequestMarker)) {
+ r.logger.Debug("FunctionsReporting ShouldAcceptFinalizedReport: transmitting offchain", commontypes.LogFields{"requestID": reqIdStr})
+ result := functions.OffchainResponse{RequestId: item.RequestID, Result: item.Result, Error: item.Error}
+ if err := r.offchainTransmitter.TransmitReport(ctx, &result); err != nil {
+ r.logger.Error("FunctionsReporting ShouldAcceptFinalizedReport: unable to transmit offchain", commontypes.LogFields{"requestID": reqIdStr, "err": err})
+ }
+ continue // doesn't need onchain transmission
+ }
needTransmissionIds = append(needTransmissionIds, reqIdStr)
}
r.logger.Debug("FunctionsReporting ShouldAcceptFinalizedReport end", commontypes.LogFields{
diff --git a/core/services/ocr2/plugins/functions/reporting_test.go b/core/services/ocr2/plugins/functions/reporting_test.go
index 24b430abd9..860492bfc5 100644
--- a/core/services/ocr2/plugins/functions/reporting_test.go
+++ b/core/services/ocr2/plugins/functions/reporting_test.go
@@ -22,14 +22,16 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/encoding"
)
-func preparePlugin(t *testing.T, batchSize uint32, maxTotalGasLimit uint32) (types.ReportingPlugin, *functions_mocks.ORM, encoding.ReportCodec) {
+func preparePlugin(t *testing.T, batchSize uint32, maxTotalGasLimit uint32) (types.ReportingPlugin, *functions_mocks.ORM, encoding.ReportCodec, *functions_mocks.OffchainTransmitter) {
lggr := logger.TestLogger(t)
ocrLogger := relaylogger.NewOCRWrapper(lggr, true, func(msg string) {})
orm := functions_mocks.NewORM(t)
+ offchainTransmitter := functions_mocks.NewOffchainTransmitter(t)
factory := functions.FunctionsReportingPluginFactory{
- Logger: ocrLogger,
- PluginORM: orm,
- ContractVersion: 1,
+ Logger: ocrLogger,
+ PluginORM: orm,
+ ContractVersion: 1,
+ OffchainTransmitter: offchainTransmitter,
}
pluginConfig := config.ReportingPluginConfigWrapper{
@@ -48,7 +50,7 @@ func preparePlugin(t *testing.T, batchSize uint32, maxTotalGasLimit uint32) (typ
require.NoError(t, err)
codec, err := encoding.NewReportCodec(1)
require.NoError(t, err)
- return plugin, orm, codec
+ return plugin, orm, codec, offchainTransmitter
}
func newRequestID() functions_srv.RequestID {
@@ -130,7 +132,7 @@ func newObservation(t *testing.T, observerId uint8, requests ...*encoding.Proces
func TestFunctionsReporting_Query(t *testing.T) {
t.Parallel()
const batchSize = 10
- plugin, orm, _ := preparePlugin(t, batchSize, 0)
+ plugin, orm, _, _ := preparePlugin(t, batchSize, 0)
reqs := []functions_srv.Request{newRequest(), newRequest()}
orm.On("FindOldestEntriesByState", functions_srv.RESULT_READY, uint32(batchSize), mock.Anything).Return(reqs, nil)
@@ -148,7 +150,7 @@ func TestFunctionsReporting_Query(t *testing.T) {
func TestFunctionsReporting_Query_HandleCoordinatorMismatch(t *testing.T) {
t.Parallel()
const batchSize = 10
- plugin, orm, _ := preparePlugin(t, batchSize, 1000000)
+ plugin, orm, _, _ := preparePlugin(t, batchSize, 1000000)
reqs := []functions_srv.Request{newRequest(), newRequest()}
reqs[0].CoordinatorContractAddress = &common.Address{1}
reqs[1].CoordinatorContractAddress = &common.Address{2}
@@ -167,7 +169,7 @@ func TestFunctionsReporting_Query_HandleCoordinatorMismatch(t *testing.T) {
func TestFunctionsReporting_Observation(t *testing.T) {
t.Parallel()
- plugin, orm, _ := preparePlugin(t, 10, 0)
+ plugin, orm, _, _ := preparePlugin(t, 10, 0)
req1 := newRequestWithResult([]byte("abc"))
req2 := newRequest()
@@ -202,7 +204,7 @@ func TestFunctionsReporting_Observation(t *testing.T) {
func TestFunctionsReporting_Observation_IncorrectQuery(t *testing.T) {
t.Parallel()
- plugin, orm, _ := preparePlugin(t, 10, 0)
+ plugin, orm, _, _ := preparePlugin(t, 10, 0)
req1 := newRequestWithResult([]byte("abc"))
invalidId := []byte("invalid")
@@ -229,7 +231,7 @@ func TestFunctionsReporting_Observation_IncorrectQuery(t *testing.T) {
func TestFunctionsReporting_Report(t *testing.T) {
t.Parallel()
- plugin, _, codec := preparePlugin(t, 10, 1000000)
+ plugin, _, codec, _ := preparePlugin(t, 10, 1000000)
reqId1, reqId2, reqId3 := newRequestID(), newRequestID(), newRequestID()
compResult := []byte("aaa")
procReq1 := newProcessedRequest(reqId1, compResult, []byte{})
@@ -266,7 +268,7 @@ func TestFunctionsReporting_Report(t *testing.T) {
func TestFunctionsReporting_Report_WithGasLimitAndMetadata(t *testing.T) {
t.Parallel()
- plugin, _, codec := preparePlugin(t, 10, 300000)
+ plugin, _, codec, _ := preparePlugin(t, 10, 300000)
reqId1, reqId2, reqId3 := newRequestID(), newRequestID(), newRequestID()
compResult := []byte("aaa")
gasLimit1, gasLimit2 := uint32(100_000), uint32(200_000)
@@ -307,7 +309,7 @@ func TestFunctionsReporting_Report_WithGasLimitAndMetadata(t *testing.T) {
func TestFunctionsReporting_Report_HandleCoordinatorMismatch(t *testing.T) {
t.Parallel()
- plugin, _, codec := preparePlugin(t, 10, 300000)
+ plugin, _, codec, _ := preparePlugin(t, 10, 300000)
reqId1, reqId2, reqId3 := newRequestID(), newRequestID(), newRequestID()
compResult, meta := []byte("aaa"), []byte("meta")
coordinatorContractA, coordinatorContractB := common.Address{1}, common.Address{2}
@@ -337,7 +339,7 @@ func TestFunctionsReporting_Report_HandleCoordinatorMismatch(t *testing.T) {
func TestFunctionsReporting_Report_CallbackGasLimitExceeded(t *testing.T) {
t.Parallel()
- plugin, _, codec := preparePlugin(t, 10, 200000)
+ plugin, _, codec, _ := preparePlugin(t, 10, 200000)
reqId1, reqId2 := newRequestID(), newRequestID()
compResult := []byte("aaa")
gasLimit1, gasLimit2 := uint32(100_000), uint32(200_000)
@@ -368,7 +370,7 @@ func TestFunctionsReporting_Report_CallbackGasLimitExceeded(t *testing.T) {
func TestFunctionsReporting_Report_DeterministicOrderOfRequests(t *testing.T) {
t.Parallel()
- plugin, _, codec := preparePlugin(t, 10, 0)
+ plugin, _, codec, _ := preparePlugin(t, 10, 0)
reqId1, reqId2, reqId3 := newRequestID(), newRequestID(), newRequestID()
compResult := []byte("aaa")
@@ -397,7 +399,7 @@ func TestFunctionsReporting_Report_DeterministicOrderOfRequests(t *testing.T) {
func TestFunctionsReporting_Report_IncorrectObservation(t *testing.T) {
t.Parallel()
- plugin, _, _ := preparePlugin(t, 10, 0)
+ plugin, _, _, _ := preparePlugin(t, 10, 0)
reqId1 := newRequestID()
compResult := []byte("aaa")
@@ -416,7 +418,14 @@ func getReportBytes(t *testing.T, codec encoding.ReportCodec, reqs ...functions_
var report []*encoding.ProcessedRequest
for _, req := range reqs {
req := req
- report = append(report, &encoding.ProcessedRequest{RequestID: req.RequestID[:], Result: req.Result})
+ report = append(report, &encoding.ProcessedRequest{
+ RequestID: req.RequestID[:],
+ Result: req.Result,
+ Error: req.Error,
+ CallbackGasLimit: *req.CallbackGasLimit,
+ CoordinatorContract: req.CoordinatorContractAddress[:],
+ OnchainMetadata: req.OnchainMetadata,
+ })
}
reportBytes, err := codec.EncodeReport(report)
require.NoError(t, err)
@@ -425,7 +434,7 @@ func getReportBytes(t *testing.T, codec encoding.ReportCodec, reqs ...functions_
func TestFunctionsReporting_ShouldAcceptFinalizedReport(t *testing.T) {
t.Parallel()
- plugin, orm, codec := preparePlugin(t, 10, 0)
+ plugin, orm, codec, _ := preparePlugin(t, 10, 0)
req1 := newRequestWithResult([]byte("xxx")) // nonexistent
req2 := newRequestWithResult([]byte("abc"))
@@ -462,9 +471,24 @@ func TestFunctionsReporting_ShouldAcceptFinalizedReport(t *testing.T) {
require.True(t, should)
}
+func TestFunctionsReporting_ShouldAcceptFinalizedReport_OffchainTransmission(t *testing.T) {
+ t.Parallel()
+ plugin, orm, codec, offchainTransmitter := preparePlugin(t, 10, 0)
+ req1 := newRequestWithResult([]byte("abc"))
+ req1.OnchainMetadata = []byte(functions_srv.OffchainRequestMarker)
+
+ orm.On("FindById", req1.RequestID, mock.Anything).Return(&req1, nil)
+ orm.On("SetFinalized", req1.RequestID, mock.Anything, mock.Anything, mock.Anything).Return(nil)
+ offchainTransmitter.On("TransmitReport", mock.Anything, mock.Anything).Return(nil)
+
+ should, err := plugin.ShouldAcceptFinalizedReport(testutils.Context(t), types.ReportTimestamp{}, getReportBytes(t, codec, req1))
+ require.NoError(t, err)
+ require.False(t, should)
+}
+
func TestFunctionsReporting_ShouldTransmitAcceptedReport(t *testing.T) {
t.Parallel()
- plugin, orm, codec := preparePlugin(t, 10, 0)
+ plugin, orm, codec, _ := preparePlugin(t, 10, 0)
req1 := newRequestWithResult([]byte("xxx")) // nonexistent
req2 := newRequestWithResult([]byte("abc"))
From 75c70f730b08ce07bc4fbf2ec77d619b39d55968 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Wed, 15 Nov 2023 06:01:48 -0600
Subject: [PATCH 151/327] core/services/pg: simplify API (#11296)
---
core/services/pg/connection.go | 2 +-
core/services/pg/q.go | 2 +-
core/services/pg/sqlx.go | 2 +-
core/services/pg/transaction.go | 54 +++++++++++----------------------
4 files changed, 20 insertions(+), 40 deletions(-)
diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go
index 0bafd5dcd0..ee345bb625 100644
--- a/core/services/pg/connection.go
+++ b/core/services/pg/connection.go
@@ -42,7 +42,7 @@ func NewConnection(uri string, dialect dialects.DialectName, config ConnectionCo
lockTimeout := config.DefaultLockTimeout().Milliseconds()
idleInTxSessionTimeout := config.DefaultIdleInTxSessionTimeout().Milliseconds()
stmt := fmt.Sprintf(`SET TIME ZONE 'UTC'; SET lock_timeout = %d; SET idle_in_transaction_session_timeout = %d; SET default_transaction_isolation = %q`,
- lockTimeout, idleInTxSessionTimeout, DefaultIsolation.String())
+ lockTimeout, idleInTxSessionTimeout, defaultIsolation.String())
if _, err = db.Exec(stmt); err != nil {
return nil, err
}
diff --git a/core/services/pg/q.go b/core/services/pg/q.go
index 470d39c825..9c9c15d983 100644
--- a/core/services/pg/q.go
+++ b/core/services/pg/q.go
@@ -165,7 +165,7 @@ 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 ...TxOptions) error {
+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...)
diff --git a/core/services/pg/sqlx.go b/core/services/pg/sqlx.go
index 820cd51712..c371c29213 100644
--- a/core/services/pg/sqlx.go
+++ b/core/services/pg/sqlx.go
@@ -35,7 +35,7 @@ func WrapDbWithSqlx(rdb *sql.DB) *sqlx.DB {
return db
}
-func SqlxTransaction(ctx context.Context, q Queryer, lggr logger.Logger, fc func(q Queryer) error, txOpts ...TxOptions) (err error) {
+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
diff --git a/core/services/pg/transaction.go b/core/services/pg/transaction.go
index 92d72b3d81..74841d010b 100644
--- a/core/services/pg/transaction.go
+++ b/core/services/pg/transaction.go
@@ -15,44 +15,21 @@ import (
corelogger "github.com/smartcontractkit/chainlink/v2/core/logger"
)
-type TxOptions struct {
- sql.TxOptions
-}
+// NOTE: This is the default level in Postgres anyway, we just make it
+// explicit here
+const defaultIsolation = sql.LevelReadCommitted
-// NOTE: In an ideal world the timeouts below would be set to something sane in
-// the postgres configuration by the user. Since we do not live in an ideal
-// world, it is necessary to override them here.
-//
-// They cannot easily be set at a session level due to how Go's connection
-// pooling works.
-const (
- // NOTE: This is the default level in Postgres anyway, we just make it
- // explicit here
- DefaultIsolation = sql.LevelReadCommitted
-)
+// TxOption is a functional option for SQL transactions.
+type TxOption func(*sql.TxOptions)
-func OptReadOnlyTx() TxOptions {
- return TxOptions{TxOptions: sql.TxOptions{ReadOnly: true}}
-}
-
-func applyDefaults(optss []TxOptions) (txOpts sql.TxOptions) {
- readOnly := false
- if len(optss) > 0 {
- opts := optss[0]
- readOnly = opts.ReadOnly
- }
- txOpts = sql.TxOptions{
- ReadOnly: readOnly,
+func OptReadOnlyTx() TxOption {
+ return func(opts *sql.TxOptions) {
+ opts.ReadOnly = true
}
- return
}
-func SqlTransaction(ctx context.Context, rdb *sql.DB, lggr logger.Logger, fn func(tx *sqlx.Tx) error, optss ...TxOptions) (err error) {
+func SqlTransaction(ctx context.Context, rdb *sql.DB, lggr logger.Logger, fn func(tx *sqlx.Tx) error, opts ...TxOption) (err error) {
db := WrapDbWithSqlx(rdb)
- return sqlxTransaction(ctx, db, lggr, fn, optss...)
-}
-
-func sqlxTransaction(ctx context.Context, db *sqlx.DB, lggr logger.Logger, fn func(tx *sqlx.Tx) error, optss ...TxOptions) (err error) {
wrapFn := func(q Queryer) error {
tx, ok := q.(*sqlx.Tx)
if !ok {
@@ -60,16 +37,19 @@ func sqlxTransaction(ctx context.Context, db *sqlx.DB, lggr logger.Logger, fn fu
}
return fn(tx)
}
- return sqlxTransactionQ(ctx, db, lggr, wrapFn, optss...)
+ return sqlxTransactionQ(ctx, db, lggr, wrapFn, opts...)
}
-// TxBeginner can be a db or a conn, anything that implements BeginTxx
-type TxBeginner interface {
+// 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, optss ...TxOptions) (err error) {
- txOpts := applyDefaults(optss)
+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)
From 50fbfd2bce762745122e514329fa6be93f867e28 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Wed, 15 Nov 2023 06:03:41 -0600
Subject: [PATCH 152/327] core/store/migrate: add context and error; remove
panics (#11295)
---
core/cmd/shell.go | 6 ++---
core/cmd/shell_local.go | 34 +++++++++++++++--------
core/store/migrate/migrate.go | 43 +++++++++++++++++-------------
core/store/migrate/migrate_test.go | 11 ++++----
4 files changed, 56 insertions(+), 38 deletions(-)
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index e1ac0b99ca..07cd2185dc 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -145,7 +145,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G
return nil, err
}
- err = handleNodeVersioning(db, 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
}
@@ -229,7 +229,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G
}
// handleNodeVersioning is a setup-time helper to encapsulate version changes and db migration
-func handleNodeVersioning(db *sqlx.DB, appLggr logger.Logger, rootDir string, cfg config.Database, healthReportPort uint16) error {
+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())
@@ -260,7 +260,7 @@ func handleNodeVersioning(db *sqlx.DB, appLggr logger.Logger, rootDir string, cf
// Migrate the database
if cfg.MigrateDatabase() {
- if err = migrate.Migrate(db.DB, appLggr); err != nil {
+ if err = migrate.Migrate(ctx, db.DB, appLggr); err != nil {
return fmt.Errorf("initializeORM#Migrate: %w", err)
}
}
diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go
index 954cead5c3..70d75f761b 100644
--- a/core/cmd/shell_local.go
+++ b/core/cmd/shell_local.go
@@ -705,9 +705,17 @@ func (s *Shell) validateDB(c *cli.Context) error {
return s.configExitErr(s.Config.ValidateDB)
}
+// ctx returns a context.Context that will be cancelled when SIGINT|SIGTERM is received
+func (s *Shell) ctx() context.Context {
+ ctx, cancel := context.WithCancel(context.Background())
+ go shutdown.HandleShutdown(func(_ string) { cancel() })
+ return ctx
+}
+
// ResetDatabase drops, creates and migrates the database specified by CL_DATABASE_URL or Database.URL
// in secrets TOML. This is useful to set up the database for testing
func (s *Shell) ResetDatabase(c *cli.Context) error {
+ ctx := s.ctx()
cfg := s.Config.Database()
parsed := cfg.URL()
if parsed.String() == "" {
@@ -727,7 +735,7 @@ func (s *Shell) ResetDatabase(c *cli.Context) error {
return s.errorOut(err)
}
lggr.Debugf("Migrating database: %#v", parsed.String())
- if err := migrateDB(cfg, lggr); err != nil {
+ if err := migrateDB(ctx, cfg, lggr); err != nil {
return s.errorOut(err)
}
schema, err := dumpSchema(parsed)
@@ -736,7 +744,7 @@ func (s *Shell) ResetDatabase(c *cli.Context) error {
}
lggr.Debugf("Testing rollback and re-migrate for database: %#v", parsed.String())
var baseVersionID int64 = 54
- if err := downAndUpDB(cfg, lggr, baseVersionID); err != nil {
+ if err := downAndUpDB(ctx, cfg, lggr, baseVersionID); err != nil {
return s.errorOut(err)
}
if err := checkSchema(parsed, schema); err != nil {
@@ -828,6 +836,7 @@ func (s *Shell) PrepareTestDatabaseUserOnly(c *cli.Context) error {
// MigrateDatabase migrates the database
func (s *Shell) MigrateDatabase(_ *cli.Context) error {
+ ctx := s.ctx()
cfg := s.Config.Database()
parsed := cfg.URL()
if parsed.String() == "" {
@@ -840,7 +849,7 @@ func (s *Shell) MigrateDatabase(_ *cli.Context) error {
}
s.Logger.Infof("Migrating database: %#v", parsed.String())
- if err := migrateDB(cfg, s.Logger); err != nil {
+ if err := migrateDB(ctx, cfg, s.Logger); err != nil {
return s.errorOut(err)
}
return nil
@@ -848,6 +857,7 @@ func (s *Shell) MigrateDatabase(_ *cli.Context) error {
// RollbackDatabase rolls back the database via down migrations.
func (s *Shell) RollbackDatabase(c *cli.Context) error {
+ ctx := s.ctx()
var version null.Int
if c.Args().Present() {
arg := c.Args().First()
@@ -863,7 +873,7 @@ func (s *Shell) RollbackDatabase(c *cli.Context) error {
return fmt.Errorf("failed to initialize orm: %v", err)
}
- if err := migrate.Rollback(db.DB, s.Logger, version); err != nil {
+ if err := migrate.Rollback(ctx, db.DB, s.Logger, version); err != nil {
return fmt.Errorf("migrateDB failed: %v", err)
}
@@ -872,12 +882,13 @@ func (s *Shell) RollbackDatabase(c *cli.Context) error {
// VersionDatabase displays the current database version.
func (s *Shell) VersionDatabase(_ *cli.Context) error {
+ ctx := s.ctx()
db, err := newConnection(s.Config.Database())
if err != nil {
return fmt.Errorf("failed to initialize orm: %v", err)
}
- version, err := migrate.Current(db.DB, s.Logger)
+ version, err := migrate.Current(ctx, db.DB, s.Logger)
if err != nil {
return fmt.Errorf("migrateDB failed: %v", err)
}
@@ -888,12 +899,13 @@ func (s *Shell) VersionDatabase(_ *cli.Context) error {
// StatusDatabase displays the database migration status
func (s *Shell) StatusDatabase(_ *cli.Context) error {
+ ctx := s.ctx()
db, err := newConnection(s.Config.Database())
if err != nil {
return fmt.Errorf("failed to initialize orm: %v", err)
}
- if err = migrate.Status(db.DB, s.Logger); err != nil {
+ if err = migrate.Status(ctx, db.DB, s.Logger); err != nil {
return fmt.Errorf("Status failed: %v", err)
}
return nil
@@ -1017,27 +1029,27 @@ func dropAndCreatePristineDB(db *sqlx.DB, template string) (err error) {
return nil
}
-func migrateDB(config dbConfig, lggr logger.Logger) error {
+func migrateDB(ctx context.Context, config dbConfig, lggr logger.Logger) error {
db, err := newConnection(config)
if err != nil {
return fmt.Errorf("failed to initialize orm: %v", err)
}
- if err = migrate.Migrate(db.DB, lggr); err != nil {
+ if err = migrate.Migrate(ctx, db.DB, lggr); err != nil {
return fmt.Errorf("migrateDB failed: %v", err)
}
return db.Close()
}
-func downAndUpDB(cfg dbConfig, lggr logger.Logger, baseVersionID int64) error {
+func downAndUpDB(ctx context.Context, cfg dbConfig, lggr logger.Logger, baseVersionID int64) error {
db, err := newConnection(cfg)
if err != nil {
return fmt.Errorf("failed to initialize orm: %v", err)
}
- if err = migrate.Rollback(db.DB, lggr, null.IntFrom(baseVersionID)); err != nil {
+ if err = migrate.Rollback(ctx, db.DB, lggr, null.IntFrom(baseVersionID)); err != nil {
return fmt.Errorf("test rollback failed: %v", err)
}
- if err = migrate.Migrate(db.DB, lggr); err != nil {
+ if err = migrate.Migrate(ctx, db.DB, lggr); err != nil {
return fmt.Errorf("second migrateDB failed: %v", err)
}
return db.Close()
diff --git a/core/store/migrate/migrate.go b/core/store/migrate/migrate.go
index 1e58d7a0b0..04da4c48e9 100644
--- a/core/store/migrate/migrate.go
+++ b/core/store/migrate/migrate.go
@@ -36,22 +36,22 @@ func init() {
}
// Ensure we migrated from v1 migrations to goose_migrations
-func ensureMigrated(db *sql.DB, lggr logger.Logger) {
+func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error {
sqlxDB := pg.WrapDbWithSqlx(db)
var names []string
- err := sqlxDB.Select(&names, `SELECT id FROM migrations`)
+ err := sqlxDB.SelectContext(ctx, &names, `SELECT id FROM migrations`)
if err != nil {
// already migrated
- return
+ return nil
}
- err = pg.SqlTransaction(context.Background(), db, lggr, func(tx *sqlx.Tx) error {
+ 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)
})
if err != nil {
- panic(err)
+ return err
}
// Look for the squashed migration. If not present, the db needs to be migrated on an earlier release first
@@ -62,18 +62,18 @@ func ensureMigrated(db *sql.DB, lggr logger.Logger) {
}
}
if !found {
- panic("Database state is too old. Need to migrate to chainlink version 0.9.10 first before upgrading to this version. This upgrade is NOT REVERSIBLE, so it is STRONGLY RECOMMENDED that you take a database backup before continuing.")
+ return errors.New("database state is too old. Need to migrate to chainlink version 0.9.10 first before upgrading to this version. This upgrade is NOT REVERSIBLE, so it is STRONGLY RECOMMENDED that you take a database backup before continuing")
}
// ensure a goose migrations table exists with it's initial v0
if _, err = goose.GetDBVersion(db); err != nil {
- panic(err)
+ return err
}
// insert records for existing migrations
//nolint
sql := fmt.Sprintf(`INSERT INTO %s (version_id, is_applied) VALUES ($1, true);`, goose.TableName())
- err = pg.SqlTransaction(context.Background(), db, lggr, func(tx *sqlx.Tx) error {
+ return pg.SqlTransaction(ctx, db, lggr, func(tx *sqlx.Tx) error {
for _, name := range names {
var id int64
// the first migration doesn't follow the naming convention
@@ -100,33 +100,38 @@ func ensureMigrated(db *sql.DB, lggr logger.Logger) {
_, err = db.Exec("DROP TABLE migrations;")
return err
})
- if err != nil {
- panic(err)
- }
}
-func Migrate(db *sql.DB, lggr logger.Logger) error {
- ensureMigrated(db, lggr)
+func Migrate(ctx context.Context, db *sql.DB, lggr logger.Logger) error {
+ if err := ensureMigrated(ctx, db, lggr); err != nil {
+ return err
+ }
// WithAllowMissing is necessary when upgrading from 0.10.14 since it
// includes out-of-order migrations
return goose.Up(db, MIGRATIONS_DIR, goose.WithAllowMissing())
}
-func Rollback(db *sql.DB, lggr logger.Logger, version null.Int) error {
- ensureMigrated(db, lggr)
+func Rollback(ctx context.Context, db *sql.DB, lggr logger.Logger, version null.Int) error {
+ if err := ensureMigrated(ctx, db, lggr); err != nil {
+ return err
+ }
if version.Valid {
return goose.DownTo(db, MIGRATIONS_DIR, version.Int64)
}
return goose.Down(db, MIGRATIONS_DIR)
}
-func Current(db *sql.DB, lggr logger.Logger) (int64, error) {
- ensureMigrated(db, lggr)
+func Current(ctx context.Context, db *sql.DB, lggr logger.Logger) (int64, error) {
+ if err := ensureMigrated(ctx, db, lggr); err != nil {
+ return -1, err
+ }
return goose.EnsureDBVersion(db)
}
-func Status(db *sql.DB, lggr logger.Logger) error {
- ensureMigrated(db, lggr)
+func Status(ctx context.Context, db *sql.DB, lggr logger.Logger) error {
+ if err := ensureMigrated(ctx, db, lggr); 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 ef105c75ff..0ff0900016 100644
--- a/core/store/migrate/migrate_test.go
+++ b/core/store/migrate/migrate_test.go
@@ -391,25 +391,26 @@ 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(db.DB, lggr)
+ err = migrate.Status(ctx, db.DB, lggr)
require.NoError(t, err)
- ver, err := migrate.Current(db.DB, lggr)
+ ver, err := migrate.Current(ctx, db.DB, lggr)
require.NoError(t, err)
require.Equal(t, int64(100), ver)
- err = migrate.Migrate(db.DB, lggr)
+ err = migrate.Migrate(ctx, db.DB, lggr)
require.NoError(t, err)
- err = migrate.Rollback(db.DB, lggr, null.IntFrom(99))
+ err = migrate.Rollback(ctx, db.DB, lggr, null.IntFrom(99))
require.NoError(t, err)
- ver, err = migrate.Current(db.DB, lggr)
+ ver, err = migrate.Current(ctx, db.DB, lggr)
require.NoError(t, err)
require.Equal(t, int64(99), ver)
}
From 5fd94b0c36556dfa6b81153214f30a8c75ae0529 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Wed, 15 Nov 2023 13:38:05 +0000
Subject: [PATCH 153/327] [BCF-2788] Correctly unmarshal the plugin config
(#11283)
---
core/services/ocr2/delegate.go | 2 +-
core/services/ocr2/validate/validate.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index bbb3b5cf7a..20c1351297 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -617,7 +617,7 @@ func (d *Delegate) newServicesGenericPlugin(
Command: command,
ProviderType: cconf.ProviderType,
TelemetryType: cconf.TelemetryType,
- PluginConfig: string(p.PluginConfig),
+ PluginConfig: p.PluginConfig,
}
pr := generic.NewPipelineRunnerAdapter(pluginLggr, jb, d.pipelineRunner)
diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go
index 78802f6559..65b95cb31a 100644
--- a/core/services/ocr2/validate/validate.go
+++ b/core/services/ocr2/validate/validate.go
@@ -134,7 +134,7 @@ type coreConfig struct {
type OCR2GenericPluginConfig struct {
CoreConfig coreConfig `json:"coreConfig"`
- PluginConfig json.RawMessage
+ PluginConfig string
}
func validateOCR2GenericPluginSpec(jsonConfig job.JSONConfig) error {
From 66d9e23219831c8ecd937431ead528dc0e9afcbb Mon Sep 17 00:00:00 2001
From: george-dorin <120329946+george-dorin@users.noreply.github.com>
Date: Wed, 15 Nov 2023 18:00:10 +0200
Subject: [PATCH 154/327] Test job creation and replacement (#9934)
* Initial draft
* - Add OCR, OCR2, Automation, VRF and cron tests
* - Update keeper test
* Fix merge
* - Split functions into DeleteJobs and DeleteBridges
* Use standardCleanup
* Fix merge conflict
* Update error style
* Remove unused method
---
.../actions/ocr2_helpers_local.go | 47 ++++++++
integration-tests/client/chainlink.go | 7 +-
integration-tests/client/chainlink_models.go | 5 +
integration-tests/smoke/cron_test.go | 71 +++++++++++
integration-tests/smoke/keeper_test.go | 66 +++++++++++
.../smoke/keeper_test.go_test_list.json | 3 +
integration-tests/smoke/ocr2_test.go | 93 ++++++++++++++-
integration-tests/smoke/ocr_test.go | 66 ++++++++++-
integration-tests/smoke/vrf_test.go | 111 ++++++++++++++++++
9 files changed, 463 insertions(+), 6 deletions(-)
diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go
index 65e0a466be..e1b470bd0d 100644
--- a/integration-tests/actions/ocr2_helpers_local.go
+++ b/integration-tests/actions/ocr2_helpers_local.go
@@ -19,6 +19,7 @@ import (
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
+
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -273,3 +274,49 @@ func GetOracleIdentitiesWithKeyIndexLocal(
return S, oracleIdentities, eg.Wait()
}
+
+// DeleteJobs will delete ALL jobs from the nodes
+func DeleteJobs(nodes []*client.ChainlinkClient) error {
+ for _, node := range nodes {
+ if node == nil {
+ return fmt.Errorf("found a nil chainlink node in the list of chainlink nodes while tearing down: %v", nodes)
+ }
+ jobs, _, err := node.ReadJobs()
+ if err != nil {
+ return fmt.Errorf("error reading jobs from chainlink node: %w", err)
+ }
+ for _, maps := range jobs.Data {
+ if _, ok := maps["id"]; !ok {
+ return fmt.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data)
+ }
+ id := maps["id"].(string)
+ _, err2 := node.DeleteJob(id)
+ if err2 != nil {
+ return fmt.Errorf("error deleting job from chainlink node: %w", err)
+ }
+ }
+ }
+ return nil
+}
+
+// DeleteBridges will delete ALL bridges from the nodes
+func DeleteBridges(nodes []*client.ChainlinkClient) error {
+ for _, node := range nodes {
+ if node == nil {
+ return fmt.Errorf("found a nil chainlink node in the list of chainlink nodes while tearing down: %v", nodes)
+ }
+
+ bridges, _, err := node.ReadBridges()
+ if err != nil {
+ return err
+ }
+ for _, b := range bridges.Data {
+ _, err = node.DeleteBridge(b.Attributes.Name)
+ if err != nil {
+ return err
+ }
+ }
+
+ }
+ return nil
+}
diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go
index 7d5825c261..4603679ff8 100644
--- a/integration-tests/client/chainlink.go
+++ b/integration-tests/client/chainlink.go
@@ -5,12 +5,11 @@ import (
"fmt"
"math/big"
"net/http"
+ "os"
"strings"
"sync"
"time"
- "os"
-
"github.com/ethereum/go-ethereum/common"
"github.com/go-resty/resty/v2"
"github.com/rs/zerolog"
@@ -303,8 +302,8 @@ func (c *ChainlinkClient) ReadBridge(name string) (*BridgeType, *http.Response,
}
// ReadBridges reads bridges from the Chainlink node
-func (c *ChainlinkClient) ReadBridges() (*ResponseSlice, *resty.Response, error) {
- result := &ResponseSlice{}
+func (c *ChainlinkClient) ReadBridges() (*Bridges, *resty.Response, error) {
+ result := &Bridges{}
c.l.Info().Str(NodeURL, c.Config.URL).Msg("Getting all bridges")
resp, err := c.APIClient.R().
SetResult(&result).
diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go
index c6d1209d2e..17a0a50845 100644
--- a/integration-tests/client/chainlink_models.go
+++ b/integration-tests/client/chainlink_models.go
@@ -107,6 +107,11 @@ type BridgeTypeData struct {
Attributes BridgeTypeAttributes `json:"attributes"`
}
+// Bridges is the model that represents the bridges when read on a Chainlink node
+type Bridges struct {
+ Data []BridgeTypeData `json:"data"`
+}
+
// BridgeTypeAttributes is the model that represents the bridge when read or created on a Chainlink node
type BridgeTypeAttributes struct {
Name string `json:"name"`
diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go
index e9d20f588e..013e4c631c 100644
--- a/integration-tests/smoke/cron_test.go
+++ b/integration-tests/smoke/cron_test.go
@@ -60,3 +60,74 @@ func TestCronBasic(t *testing.T) {
}
}, "2m", "3s").Should(gomega.Succeed())
}
+
+func TestCronJobReplacement(t *testing.T) {
+ t.Parallel()
+ l := logging.GetTestLogger(t)
+
+ env, err := test_env.NewCLTestEnvBuilder().
+ WithTestLogger(t).
+ WithGeth().
+ WithMockAdapter().
+ WithCLNodes(1).
+ WithStandardCleanup().
+ Build()
+ require.NoError(t, err)
+
+ err = env.MockAdapter.SetAdapterBasedIntValuePath("/variable", []string{http.MethodGet, http.MethodPost}, 5)
+ require.NoError(t, err, "Setting value path in mockserver shouldn't fail")
+
+ bta := &client.BridgeTypeAttributes{
+ Name: fmt.Sprintf("variable-%s", uuid.NewString()),
+ URL: fmt.Sprintf("%s/variable", env.MockAdapter.InternalEndpoint),
+ RequestData: "{}",
+ }
+ err = env.ClCluster.Nodes[0].API.MustCreateBridge(bta)
+ require.NoError(t, err, "Creating bridge in chainlink node shouldn't fail")
+
+ // CRON job creation and replacement
+ job, err := env.ClCluster.Nodes[0].API.MustCreateJob(&client.CronJobSpec{
+ Schedule: "CRON_TZ=UTC * * * * * *",
+ ObservationSource: client.ObservationSourceSpecBridge(bta),
+ })
+ require.NoError(t, err, "Creating Cron Job in chainlink node shouldn't fail")
+
+ gom := gomega.NewWithT(t)
+ gom.Eventually(func(g gomega.Gomega) {
+ jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
+ if err != nil {
+ l.Info().Err(err).Msg("error while waiting for job runs")
+ }
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Reading Job run data shouldn't fail")
+
+ g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 5), "Expected number of job runs to be greater than 5, but got %d", len(jobRuns.Data))
+
+ for _, jr := range jobRuns.Data {
+ g.Expect(jr.Attributes.Errors).Should(gomega.Equal([]interface{}{nil}), "Job run %s shouldn't have errors", jr.ID)
+ }
+ }, "3m", "3s").Should(gomega.Succeed())
+
+ err = env.ClCluster.Nodes[0].API.MustDeleteJob(job.Data.ID)
+ require.NoError(t, err)
+
+ job, err = env.ClCluster.Nodes[0].API.MustCreateJob(&client.CronJobSpec{
+ Schedule: "CRON_TZ=UTC * * * * * *",
+ ObservationSource: client.ObservationSourceSpecBridge(bta),
+ })
+ require.NoError(t, err, "Recreating Cron Job in chainlink node shouldn't fail")
+
+ gom.Eventually(func(g gomega.Gomega) {
+ jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
+ if err != nil {
+ l.Info().Err(err).Msg("error while waiting for job runs")
+ }
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Reading Job run data shouldn't fail")
+
+ g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 5), "Expected number of job runs to be greater than 5, but got %d", len(jobRuns.Data))
+
+ for _, jr := range jobRuns.Data {
+ g.Expect(jr.Attributes.Errors).Should(gomega.Equal([]interface{}{nil}), "Job run %s shouldn't have errors", jr.ID)
+ }
+ }, "3m", "3s").Should(gomega.Succeed())
+
+}
diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go
index b28ab1ff10..29a819af13 100644
--- a/integration-tests/smoke/keeper_test.go
+++ b/integration-tests/smoke/keeper_test.go
@@ -1126,3 +1126,69 @@ func setupKeeperTest(t *testing.T) (
return env.EVMClient, env.ClCluster.NodeAPIs(), env.ContractDeployer, linkTokenContract, env
}
+
+func TestKeeperJobReplacement(t *testing.T) {
+ t.Parallel()
+ registryVersion := ethereum.RegistryVersion_1_3
+
+ l := logging.GetTestLogger(t)
+ chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t)
+ registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts(
+ t,
+ registryVersion,
+ keeperDefaultRegistryConfig,
+ keeperDefaultUpkeepsToDeploy,
+ keeperDefaultUpkeepGasLimit,
+ linkToken,
+ contractDeployer,
+ chainClient,
+ big.NewInt(keeperDefaultLinkFunds),
+ )
+ gom := gomega.NewGomegaWithT(t)
+
+ _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String())
+ require.NoError(t, err, "Error creating keeper jobs")
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Error creating keeper jobs")
+
+ gom.Eventually(func(g gomega.Gomega) error {
+ // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
+ for i := 0; i < len(upkeepIDs); i++ {
+ counter, err := consumers[i].Counter(utils.TestContext(t))
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
+ g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
+ "Expected consumer counter to be greater than 10, but got %d", counter.Int64())
+ l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed")
+ }
+ return nil
+ }, "5m", "1s").Should(gomega.Succeed())
+
+ for _, n := range chainlinkNodes {
+ jobs, _, err := n.ReadJobs()
+ require.NoError(t, err)
+ for _, maps := range jobs.Data {
+ _, ok := maps["id"]
+ require.Equal(t, true, ok)
+ id := maps["id"].(string)
+ _, err := n.DeleteJob(id)
+ require.NoError(t, err)
+ }
+ }
+
+ _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String())
+ require.NoError(t, err, "Error creating keeper jobs")
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Error creating keeper jobs")
+
+ gom.Eventually(func(g gomega.Gomega) error {
+ // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
+ for i := 0; i < len(upkeepIDs); i++ {
+ counter, err := consumers[i].Counter(utils.TestContext(t))
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
+ g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
+ "Expected consumer counter to be greater than 10, but got %d", counter.Int64())
+ l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed")
+ }
+ return nil
+ }, "5m", "1s").Should(gomega.Succeed())
+}
diff --git a/integration-tests/smoke/keeper_test.go_test_list.json b/integration-tests/smoke/keeper_test.go_test_list.json
index dfa2c49358..b874bc65ee 100644
--- a/integration-tests/smoke/keeper_test.go_test_list.json
+++ b/integration-tests/smoke/keeper_test.go_test_list.json
@@ -53,6 +53,9 @@
},
{
"name": "TestKeeperUpdateCheckData"
+ },
+ {
+ "name": "TestKeeperJobReplacement"
}
]
}
diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go
index 5950e9febb..bec82e633f 100644
--- a/integration-tests/smoke/ocr2_test.go
+++ b/integration-tests/smoke/ocr2_test.go
@@ -10,7 +10,6 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
-
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
@@ -92,3 +91,95 @@ func TestOCRv2Basic(t *testing.T) {
roundData.Answer.Int64(),
)
}
+
+func TestOCRv2JobReplacement(t *testing.T) {
+ l := logging.GetTestLogger(t)
+
+ env, err := test_env.NewCLTestEnvBuilder().
+ WithTestLogger(t).
+ WithGeth().
+ WithMockAdapter().
+ WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(),
+ node.WithOCR2(),
+ node.WithP2Pv2(),
+ node.WithTracing(),
+ )).
+ WithCLNodes(6).
+ WithFunding(big.NewFloat(.1)).
+ WithStandardCleanup().
+ Build()
+ require.NoError(t, err)
+
+ env.ParallelTransactions(true)
+
+ nodeClients := env.ClCluster.NodeAPIs()
+ bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:]
+
+ linkToken, err := env.ContractDeployer.DeployLinkTokenContract()
+ require.NoError(t, err, "Deploying Link Token Contract shouldn't fail")
+
+ err = actions.FundChainlinkNodesLocal(workerNodes, env.EVMClient, big.NewFloat(.05))
+ require.NoError(t, err, "Error funding Chainlink nodes")
+
+ // Gather transmitters
+ var transmitters []string
+ for _, node := range workerNodes {
+ addr, err := node.PrimaryEthAddress()
+ if err != nil {
+ require.NoError(t, fmt.Errorf("error getting node's primary ETH address: %w", err))
+ }
+ transmitters = append(transmitters, addr)
+ }
+
+ ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions()
+ aggregatorContracts, err := actions.DeployOCRv2Contracts(1, linkToken, env.ContractDeployer, transmitters, env.EVMClient, ocrOffchainOptions)
+ require.NoError(t, err, "Error deploying OCRv2 aggregator contracts")
+
+ err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, env.EVMClient.GetChainID().Uint64(), false)
+ require.NoError(t, err, "Error creating OCRv2 jobs")
+
+ ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions)
+ require.NoError(t, err, "Error building OCRv2 config")
+
+ err = actions.ConfigureOCRv2AggregatorContracts(env.EVMClient, ocrv2Config, aggregatorContracts)
+ require.NoError(t, err, "Error configuring OCRv2 aggregator contracts")
+
+ err = actions.StartNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l)
+ require.NoError(t, err, "Error starting new OCR2 round")
+ roundData, err := aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(1))
+ require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
+ require.Equal(t, int64(5), roundData.Answer.Int64(),
+ "Expected latest answer from OCR contract to be 5 but got %d",
+ roundData.Answer.Int64(),
+ )
+
+ err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10)
+ require.NoError(t, err)
+ err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l)
+ require.NoError(t, err)
+
+ roundData, err = aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(2))
+ require.NoError(t, err, "Error getting latest OCR answer")
+ require.Equal(t, int64(10), roundData.Answer.Int64(),
+ "Expected latest answer from OCR contract to be 10 but got %d",
+ roundData.Answer.Int64(),
+ )
+
+ err = actions.DeleteJobs(nodeClients)
+ require.NoError(t, err)
+
+ err = actions.DeleteBridges(nodeClients)
+ require.NoError(t, err)
+
+ err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 15, env.EVMClient.GetChainID().Uint64(), false)
+ require.NoError(t, err, "Error creating OCRv2 jobs")
+
+ err = actions.StartNewOCR2Round(3, aggregatorContracts, env.EVMClient, time.Minute*3, l)
+ require.NoError(t, err, "Error starting new OCR2 round")
+ roundData, err = aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(3))
+ require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
+ require.Equal(t, int64(15), roundData.Answer.Int64(),
+ "Expected latest answer from OCR contract to be 15 but got %d",
+ roundData.Answer.Int64(),
+ )
+}
diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go
index 45205565e2..8fbc1109e2 100644
--- a/integration-tests/smoke/ocr_test.go
+++ b/integration-tests/smoke/ocr_test.go
@@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
-
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/utils"
@@ -59,3 +58,68 @@ func TestOCRBasic(t *testing.T) {
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
+
+func TestOCRJobReplacement(t *testing.T) {
+ t.Parallel()
+ l := logging.GetTestLogger(t)
+
+ env, err := test_env.NewCLTestEnvBuilder().
+ WithTestLogger(t).
+ WithGeth().
+ WithMockAdapter().
+ WithCLNodes(6).
+ WithFunding(big.NewFloat(.1)).
+ WithStandardCleanup().
+ Build()
+ require.NoError(t, err)
+
+ env.ParallelTransactions(true)
+
+ nodeClients := env.ClCluster.NodeAPIs()
+ bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:]
+
+ linkTokenContract, err := env.ContractDeployer.DeployLinkTokenContract()
+ require.NoError(t, err, "Deploying Link Token Contract shouldn't fail")
+
+ ocrInstances, err := actions.DeployOCRContractsLocal(1, linkTokenContract, env.ContractDeployer, workerNodes, env.EVMClient)
+ require.NoError(t, err)
+ err = env.EVMClient.WaitForEvents()
+ require.NoError(t, err, "Error waiting for events")
+
+ err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String())
+ require.NoError(t, err)
+
+ err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
+ require.NoError(t, err)
+
+ answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
+ require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
+
+ err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter)
+ require.NoError(t, err)
+ err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l)
+ require.NoError(t, err)
+
+ answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ require.NoError(t, err, "Error getting latest OCR answer")
+ require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
+
+ err = actions.DeleteJobs(nodeClients)
+ require.NoError(t, err)
+
+ err = actions.DeleteBridges(nodeClients)
+ require.NoError(t, err)
+
+ //Recreate job
+ err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String())
+ require.NoError(t, err)
+
+ err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
+ require.NoError(t, err)
+
+ answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
+ require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
+
+}
diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go
index 61d2c5cdd7..e477d45926 100644
--- a/integration-tests/smoke/vrf_test.go
+++ b/integration-tests/smoke/vrf_test.go
@@ -107,3 +107,114 @@ func TestVRFBasic(t *testing.T) {
}, timeout, "1s").Should(gomega.Succeed())
}
}
+
+func TestVRFJobReplacement(t *testing.T) {
+ t.Parallel()
+ l := logging.GetTestLogger(t)
+
+ env, err := test_env.NewCLTestEnvBuilder().
+ WithTestLogger(t).
+ WithGeth().
+ WithCLNodes(1).
+ WithFunding(big.NewFloat(.1)).
+ WithStandardCleanup().
+ Build()
+ require.NoError(t, err)
+ env.ParallelTransactions(true)
+
+ lt, err := actions.DeployLINKToken(env.ContractDeployer)
+ require.NoError(t, err, "Deploying Link Token Contract shouldn't fail")
+ contracts, err := vrfv1.DeployVRFContracts(env.ContractDeployer, env.EVMClient, lt)
+ require.NoError(t, err, "Deploying VRF Contracts shouldn't fail")
+
+ err = lt.Transfer(contracts.Consumer.Address(), big.NewInt(2e18))
+ require.NoError(t, err, "Funding consumer contract shouldn't fail")
+ _, err = env.ContractDeployer.DeployVRFContract()
+ require.NoError(t, err, "Deploying VRF contract shouldn't fail")
+ err = env.EVMClient.WaitForEvents()
+ require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
+
+ for _, n := range env.ClCluster.Nodes {
+ nodeKey, err := n.API.MustCreateVRFKey()
+ require.NoError(t, err, "Creating VRF key shouldn't fail")
+ l.Debug().Interface("Key JSON", nodeKey).Msg("Created proving key")
+ pubKeyCompressed := nodeKey.Data.ID
+ jobUUID := uuid.New()
+ os := &client.VRFTxPipelineSpec{
+ Address: contracts.Coordinator.Address(),
+ }
+ ost, err := os.String()
+ require.NoError(t, err, "Building observation source spec shouldn't fail")
+ job, err := n.API.MustCreateJob(&client.VRFJobSpec{
+ Name: fmt.Sprintf("vrf-%s", jobUUID),
+ CoordinatorAddress: contracts.Coordinator.Address(),
+ MinIncomingConfirmations: 1,
+ PublicKey: pubKeyCompressed,
+ ExternalJobID: jobUUID.String(),
+ EVMChainID: env.EVMClient.GetChainID().String(),
+ ObservationSource: ost,
+ })
+ require.NoError(t, err, "Creating VRF Job shouldn't fail")
+
+ oracleAddr, err := n.API.PrimaryEthAddress()
+ require.NoError(t, err, "Getting primary ETH address of chainlink node shouldn't fail")
+ provingKey, err := actions.EncodeOnChainVRFProvingKey(*nodeKey)
+ require.NoError(t, err, "Encoding on-chain VRF Proving key shouldn't fail")
+ err = contracts.Coordinator.RegisterProvingKey(
+ big.NewInt(1),
+ oracleAddr,
+ provingKey,
+ actions.EncodeOnChainExternalJobID(jobUUID),
+ )
+ require.NoError(t, err, "Registering the on-chain VRF Proving key shouldn't fail")
+ encodedProvingKeys := make([][2]*big.Int, 0)
+ encodedProvingKeys = append(encodedProvingKeys, provingKey)
+
+ requestHash, err := contracts.Coordinator.HashOfKey(utils.TestContext(t), encodedProvingKeys[0])
+ require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail")
+ err = contracts.Consumer.RequestRandomness(requestHash, big.NewInt(1))
+ require.NoError(t, err, "Requesting randomness shouldn't fail")
+
+ gom := gomega.NewGomegaWithT(t)
+ timeout := time.Minute * 2
+ gom.Eventually(func(g gomega.Gomega) {
+ jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
+
+ out, err := contracts.Consumer.RandomnessOutput(utils.TestContext(t))
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
+ // Checks that the job has actually run
+ g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
+ fmt.Sprintf("Expected the VRF job to run once or more after %s", timeout))
+
+ g.Expect(out.Uint64()).ShouldNot(gomega.BeNumerically("==", 0), "Expected the VRF job give an answer other than 0")
+ l.Debug().Uint64("Output", out.Uint64()).Msg("Randomness fulfilled")
+ }, timeout, "1s").Should(gomega.Succeed())
+
+ err = n.API.MustDeleteJob(job.Data.ID)
+ require.NoError(t, err)
+
+ job, err = n.API.MustCreateJob(&client.VRFJobSpec{
+ Name: fmt.Sprintf("vrf-%s", jobUUID),
+ CoordinatorAddress: contracts.Coordinator.Address(),
+ MinIncomingConfirmations: 1,
+ PublicKey: pubKeyCompressed,
+ ExternalJobID: jobUUID.String(),
+ EVMChainID: env.EVMClient.GetChainID().String(),
+ ObservationSource: ost,
+ })
+ require.NoError(t, err, "Recreating VRF Job shouldn't fail")
+ gom.Eventually(func(g gomega.Gomega) {
+ jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
+
+ out, err := contracts.Consumer.RandomnessOutput(utils.TestContext(t))
+ g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
+ // Checks that the job has actually run
+ g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
+ fmt.Sprintf("Expected the VRF job to run once or more after %s", timeout))
+ g.Expect(out.Uint64()).ShouldNot(gomega.BeNumerically("==", 0), "Expected the VRF job give an answer other than 0")
+ l.Debug().Uint64("Output", out.Uint64()).Msg("Randomness fulfilled")
+ }, timeout, "1s").Should(gomega.Succeed())
+ }
+}
From a75f900e0536f3eb9282284ac5cfec57206a3ec6 Mon Sep 17 00:00:00 2001
From: Tate
Date: Wed, 15 Nov 2023 14:04:05 -0700
Subject: [PATCH 155/327] [TT-707] Add chainlink image build to test image
publish for workflow dispatch (#11304)
This allows teams to run this one dispatch and not have to make a work in progress PR before they start testing.
---
.../workflows/integration-tests-publish.yml | 62 +++++++++++++++++--
1 file changed, 56 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml
index 9579b83b98..9eb2673db2 100644
--- a/.github/workflows/integration-tests-publish.yml
+++ b/.github/workflows/integration-tests-publish.yml
@@ -7,9 +7,6 @@ on:
- develop
workflow_dispatch:
inputs:
- chainlink-tests-tag:
- description: 'The tag to be pushed'
- required: true
ctf-base-image-tag:
description: |
'The tag of the CTF base image to be used,
@@ -18,7 +15,8 @@ on:
required: true
env:
- ECR_TAG_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests
+ ECR_TAG: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:develop
+ CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink
jobs:
publish-integration-test-image:
@@ -41,19 +39,71 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
+ - name: Setup Other Tags
+ id: tags
+ env:
+ BASE_IMAGE_TAG: ${{ inputs.ctf-base-image-tag}}
+ run: |
+ if [ -z "${BASE_IMAGE_TAG+x}" ]; then
+ echo "ctf-base-image-tag is not set, we are part of a merge and want to push the develop tag"
+ echo "other_tags=${ECR_TAG}" >> $GITHUB_OUTPUT
+ fi
- name: Build Image
uses: ./.github/actions/build-test-image
with:
- other_tags: "${{ env.ECR_TAG_BASE }}:${{ inputs.chainlink-tests-tag || 'develop' }}"
+ other_tags: ${{ steps.tags.outputs.other_tags }}
base_image_tag: ${{ inputs.ctf-base-image-tag }}
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 }}
- name: Notify Slack
- if: failure()
+ # Only run this notification for merge to develop failures
+ if: failure() && github.event_name != 'workflow_dispatch'
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
env:
SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
with:
channel-id: "#team-test-tooling-internal"
slack-message: ":x: :mild-panic-intensifies: Publish Integration Test Image failed: ${{ job.html_url }}\n${{ format('https://github.com/smartcontractkit/chainlink/actions/runs/{0}', github.run_id) }}"
+ build-chainlink-image:
+ environment: integration
+ # Only run this build for workflow_dispatch
+ if: ${{ inputs.ctf-base-image-tag != '' }}
+ permissions:
+ id-token: write
+ contents: read
+ strategy:
+ matrix:
+ image:
+ - name: ""
+ dockerfile: core/chainlink.Dockerfile
+ tag-suffix: ""
+ # uncomment in the future if we end up needing to soak test the plugins image
+ # - name: (plugins)
+ # dockerfile: plugins/chainlink.Dockerfile
+ # tag-suffix: -plugins
+ name: Build Chainlink Image ${{ matrix.image.name }}
+ runs-on: ubuntu20.04-8cores-32GB
+ steps:
+ - name: Collect Metrics
+ id: collect-gha-metrics
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ with:
+ basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ this-job-name: Build Chainlink Image ${{ matrix.image.name }}
+ continue-on-error: true
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.sha }}
+ - name: Build Chainlink Image
+ uses: ./.github/actions/build-chainlink-image
+ with:
+ tag_suffix: ${{ matrix.image.tag-suffix }}
+ dockerfile: ${{ matrix.image.dockerfile }}
+ git_commit_sha: ${{ github.sha }}
+ GRAFANA_CLOUD_BASIC_AUTH: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ GRAFANA_CLOUD_HOST: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
From 2a947ccf50536601a0032650920056d7d68a0421 Mon Sep 17 00:00:00 2001
From: Justin Kaseman
Date: Wed, 15 Nov 2023 19:17:44 -0500
Subject: [PATCH 156/327] [Functions] (test): Add Functions
HasUniqueGlobalRequestId foundry test (#11306)
* (test): Add Functions HasUniqueGlobalRequestId foundry test
* Regenerate gas snapshot
---
.../gas-snapshots/functions.gas-snapshot | 35 ++++++++--------
.../v0.8/functions/tests/v1_X/BaseTest.t.sol | 2 +-
.../tests/v1_X/FunctionsBilling.t.sol | 40 +++++++++++++++++--
.../src/v0.8/functions/tests/v1_X/Setup.t.sol | 5 ++-
4 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot
index 82b5b494a7..4e6cf83cd1 100644
--- a/contracts/gas-snapshots/functions.gas-snapshot
+++ b/contracts/gas-snapshots/functions.gas-snapshot
@@ -1,12 +1,12 @@
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14577815)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14577793)
-ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14577809)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14589229)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14589206)
-ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14589178)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14589129)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14589118)
-ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14589162)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumGoerli() (gas: 14578318)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumMainnet() (gas: 14578296)
+ChainSpecificUtil__getCurrentTxL1GasFees_Arbitrum:test__getCurrentTxL1GasFees_SuccessWhenArbitrumSepolia() (gas: 14578312)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseGoerli() (gas: 14589732)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseMainnet() (gas: 14589709)
+ChainSpecificUtil__getCurrentTxL1GasFees_Base:test__getCurrentTxL1GasFees_SuccessWhenBaseSepolia() (gas: 14589681)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismGoerli() (gas: 14589632)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismMainnet() (gas: 14589621)
+ChainSpecificUtil__getCurrentTxL1GasFees_Optimism:test__getCurrentTxL1GasFees_SuccessWhenOptimismSepolia() (gas: 14589665)
FunctionsBilling_Constructor:test_Constructor_Success() (gas: 14812)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13282)
FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15897)
@@ -28,6 +28,7 @@ FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 38251)
FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8810)
FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13302)
FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 180763)
+FunctionsBilling__StartBilling:test__FulfillAndBill_HasUniqueGlobalRequestId() (gas: 398312)
FunctionsClient_Constructor:test_Constructor_Success() (gas: 7573)
FunctionsClient_FulfillRequest:test_FulfillRequest_MaximumGas() (gas: 497786)
FunctionsClient_FulfillRequest:test_FulfillRequest_MinimumGas() (gas: 198990)
@@ -51,17 +52,17 @@ FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 246)
FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 223)
FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 225)
FunctionsRouter_Constructor:test_Constructor_Success() (gas: 12007)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 167459)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 157790)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 167477)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 157808)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38115)
FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35238)
-FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 175935)
+FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 175953)
FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086)
-FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 151478)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 321037)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 334658)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2509939)
-FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 540418)
+FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 151496)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 321059)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 334680)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2509962)
+FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 540441)
FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 17983)
FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 12904)
FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 37159)
diff --git a/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol b/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol
index b012732897..ffa684e84c 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol
@@ -19,7 +19,7 @@ contract BaseTest is Test {
// BaseTest.setUp is often called multiple times from tests' setUp due to inheritance.
if (s_baseTestInitialized) return;
s_baseTestInitialized = true;
- // Set msg.sender to OWNER until stopPrank is called
+ // Set msg.sender and tx.origin to OWNER until stopPrank is called
vm.startPrank(OWNER_ADDRESS, OWNER_ADDRESS);
}
}
diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
index 6e94e4fc5f..739521c530 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol
@@ -8,7 +8,7 @@ import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"
import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol";
import {Routable} from "../../dev/v1_X/Routable.sol";
-import {FunctionsRouterSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsMultipleFulfillmentsSetup} from "./Setup.t.sol";
+import {FunctionsRouterSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsFulfillmentSetup, FunctionsMultipleFulfillmentsSetup} from "./Setup.t.sol";
/// @notice #constructor
contract FunctionsBilling_Constructor is FunctionsSubscriptionSetup {
@@ -217,8 +217,42 @@ contract FunctionsBilling__CalculateCostEstimate {
}
/// @notice #_startBilling
-contract FunctionsBilling__StartBilling {
- // TODO: make contract internal function helper
+contract FunctionsBilling__StartBilling is FunctionsFulfillmentSetup {
+ function test__FulfillAndBill_HasUniqueGlobalRequestId() public {
+ // Variables that go into a requestId:
+ // - Coordinator address
+ // - Consumer contract
+ // - Subscription ID,
+ // - Consumer initiated requests
+ // - Request data
+ // - Request data version
+ // - Request callback gas limit
+ // - Estimated total cost in Juels
+ // - Request timeout timestamp
+ // - tx.origin
+
+ // Request #1 has already been fulfilled by the test setup
+
+ // Reset the nonce (initiatedRequests) by removing and re-adding the consumer
+ s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient));
+ assertEq(s_functionsRouter.getSubscription(s_subscriptionId).consumers.length, 0);
+ s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient));
+ assertEq(s_functionsRouter.getSubscription(s_subscriptionId).consumers[0], address(s_functionsClient));
+
+ // Make Request #2
+ _sendAndStoreRequest(
+ 2,
+ s_requests[1].requestData.sourceCode,
+ s_requests[1].requestData.secrets,
+ s_requests[1].requestData.args,
+ s_requests[1].requestData.bytesArgs,
+ s_requests[1].requestData.callbackGasLimit
+ );
+
+ // Request #1 and #2 should have different request IDs, because the request timeout timestamp has advanced.
+ // A request cannot be fulfilled in the same block, which prevents removing a consumer in the same block
+ assertNotEq(s_requests[1].requestId, s_requests[2].requestId);
+ }
}
/// @notice #_fulfillAndBill
diff --git a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
index 97418958bc..41ee663e8b 100644
--- a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
+++ b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol
@@ -525,7 +525,7 @@ contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup {
// Return prank to Owner
vm.stopPrank();
- vm.startPrank(OWNER_ADDRESS);
+ vm.startPrank(OWNER_ADDRESS, OWNER_ADDRESS);
}
/// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin
@@ -604,6 +604,9 @@ contract FunctionsFulfillmentSetup is FunctionsClientRequestSetup {
function setUp() public virtual override {
FunctionsClientRequestSetup.setUp();
+ // Fast forward time by 30 seconds to simulate the DON executing the computation
+ vm.warp(block.timestamp + 30);
+
// Fulfill request 1
uint256[] memory requestNumberKeys = new uint256[](1);
requestNumberKeys[0] = 1;
From b012cc426d0ec5515b7c40a10d5924734df760a8 Mon Sep 17 00:00:00 2001
From: Bolek <1416262+bolekk@users.noreply.github.com>
Date: Wed, 15 Nov 2023 23:20:24 -0800
Subject: [PATCH 157/327] [Functions] Require minimum balance only for
secrets_set, not for list (#11309)
Additionally refactor a helper method in connector_handler.go.
---
core/services/functions/connector_handler.go | 41 ++++++++-----------
.../functions/connector_handler_test.go | 3 --
.../handlers/functions/handler.functions.go | 2 +-
.../functions/handler.functions_test.go | 3 +-
4 files changed, 20 insertions(+), 29 deletions(-)
diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go
index 8a8710e6ea..c5dbff6f10 100644
--- a/core/services/functions/connector_handler.go
+++ b/core/services/functions/connector_handler.go
@@ -76,24 +76,21 @@ func (h *functionsConnectorHandler) HandleGatewayMessage(ctx context.Context, ga
h.lggr.Errorw("request rate-limited", "id", gatewayId, "address", fromAddr)
return
}
- if balance, err := h.subscriptions.GetMaxUserBalance(fromAddr); err != nil || balance.Cmp(h.minimumBalance.ToInt()) < 0 {
- h.lggr.Errorw("user subscription has insufficient balance", "id", gatewayId, "address", fromAddr, "balance", balance, "minBalance", h.minimumBalance)
- response := functions.SecretsResponseBase{
- Success: false,
- ErrorMessage: "user subscription has insufficient balance",
- }
- if err := h.sendResponse(ctx, gatewayId, body, response); err != nil {
- h.lggr.Errorw("failed to send response to gateway", "id", gatewayId, "error", err)
- }
- return
- }
-
h.lggr.Debugw("handling gateway request", "id", gatewayId, "method", body.Method)
switch body.Method {
case functions.MethodSecretsList:
h.handleSecretsList(ctx, gatewayId, body, fromAddr)
case functions.MethodSecretsSet:
+ if balance, err := h.subscriptions.GetMaxUserBalance(fromAddr); err != nil || balance.Cmp(h.minimumBalance.ToInt()) < 0 {
+ h.lggr.Errorw("user subscription has insufficient balance", "id", gatewayId, "address", fromAddr, "balance", balance, "minBalance", h.minimumBalance)
+ response := functions.SecretsResponseBase{
+ Success: false,
+ ErrorMessage: "user subscription has insufficient balance",
+ }
+ h.sendResponseAndLog(ctx, gatewayId, body, response)
+ return
+ }
h.handleSecretsSet(ctx, gatewayId, body, fromAddr)
default:
h.lggr.Errorw("unsupported method", "id", gatewayId, "method", body.Method)
@@ -133,10 +130,7 @@ func (h *functionsConnectorHandler) handleSecretsList(ctx context.Context, gatew
} else {
response.ErrorMessage = fmt.Sprintf("Failed to list secrets: %v", err)
}
-
- if err := h.sendResponse(ctx, gatewayId, body, response); err != nil {
- h.lggr.Errorw("failed to send response to gateway", "id", gatewayId, "error", err)
- }
+ h.sendResponseAndLog(ctx, gatewayId, body, response)
}
func (h *functionsConnectorHandler) handleSecretsSet(ctx context.Context, gatewayId string, body *api.MessageBody, fromAddr ethCommon.Address) {
@@ -163,9 +157,15 @@ func (h *functionsConnectorHandler) handleSecretsSet(ctx context.Context, gatewa
} else {
response.ErrorMessage = fmt.Sprintf("Bad request to set secret: %v", err)
}
+ h.sendResponseAndLog(ctx, gatewayId, body, response)
+}
- if err := h.sendResponse(ctx, gatewayId, body, response); err != nil {
+func (h *functionsConnectorHandler) sendResponseAndLog(ctx context.Context, gatewayId string, requestBody *api.MessageBody, payload any) {
+ err := h.sendResponse(ctx, gatewayId, requestBody, payload)
+ if err != nil {
h.lggr.Errorw("failed to send response to gateway", "id", gatewayId, "error", err)
+ } else {
+ h.lggr.Debugw("sent to gateway", "id", gatewayId, "messageId", requestBody.MessageId, "donId", requestBody.DonId, "method", requestBody.Method)
}
}
@@ -187,10 +187,5 @@ func (h *functionsConnectorHandler) sendResponse(ctx context.Context, gatewayId
if err = msg.Sign(h.signerKey); err != nil {
return err
}
-
- err = h.connector.SendToGateway(ctx, gatewayId, msg)
- if err == nil {
- h.lggr.Debugw("sent to gateway", "id", gatewayId, "messageId", requestBody.MessageId, "donId", requestBody.DonId, "method", requestBody.Method)
- }
- return err
+ return h.connector.SendToGateway(ctx, gatewayId, msg)
}
diff --git a/core/services/functions/connector_handler_test.go b/core/services/functions/connector_handler_test.go
index 7bf98d7501..fa9f74712b 100644
--- a/core/services/functions/connector_handler_test.go
+++ b/core/services/functions/connector_handler_test.go
@@ -78,7 +78,6 @@ func TestFunctionsConnectorHandler(t *testing.T) {
}
storage.On("List", ctx, addr).Return(snapshot, nil).Once()
allowlist.On("Allow", addr).Return(true).Once()
- subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -91,7 +90,6 @@ func TestFunctionsConnectorHandler(t *testing.T) {
t.Run("orm error", func(t *testing.T) {
storage.On("List", ctx, addr).Return(nil, errors.New("boom")).Once()
allowlist.On("Allow", addr).Return(true).Once()
- subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
connector.On("SendToGateway", ctx, "gw1", mock.Anything).Run(func(args mock.Arguments) {
msg, ok := args[2].(*api.Message)
require.True(t, ok)
@@ -218,7 +216,6 @@ func TestFunctionsConnectorHandler(t *testing.T) {
require.NoError(t, msg.Sign(privateKey))
allowlist.On("Allow", addr).Return(true).Once()
- subscriptions.On("GetMaxUserBalance", mock.Anything).Return(big.NewInt(100), nil).Once()
handler.HandleGatewayMessage(testutils.Context(t), "gw1", &msg)
})
})
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index d0011145d4..bb6812c1f9 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -178,7 +178,7 @@ func (h *functionsHandler) HandleUserMessage(ctx context.Context, msg *api.Messa
promHandlerError.WithLabelValues(h.donConfig.DonId, ErrRateLimited.Error()).Inc()
return ErrRateLimited
}
- if h.subscriptions != nil && h.minimumBalance != nil {
+ if msg.Body.Method == MethodSecretsSet && h.subscriptions != nil && h.minimumBalance != nil {
balance, err := h.subscriptions.GetMaxUserBalance(sender)
if err != nil {
h.lggr.Debugw("error getting max user balance", "sender", msg.Body.Sender, "err", err)
diff --git a/core/services/gateway/handlers/functions/handler.functions_test.go b/core/services/gateway/handlers/functions/handler.functions_test.go
index 1446bc8457..49fdae2bb2 100644
--- a/core/services/gateway/handlers/functions/handler.functions_test.go
+++ b/core/services/gateway/handlers/functions/handler.functions_test.go
@@ -148,11 +148,10 @@ func TestFunctionsHandler_HandleUserMessage_InvalidMethod(t *testing.T) {
t.Parallel()
nodes, user := gc.NewTestNodes(t, 4), gc.NewTestNodes(t, 1)[0]
- handler, _, allowlist, subscriptions := newFunctionsHandlerForATestDON(t, nodes, time.Hour*24)
+ handler, _, allowlist, _ := newFunctionsHandlerForATestDON(t, nodes, time.Hour*24)
userRequestMsg := newSignedMessage(t, "1234", "secrets_reveal_all_please", "don_id", user.PrivateKey)
allowlist.On("Allow", common.HexToAddress(user.Address)).Return(true, nil)
- subscriptions.On("GetMaxUserBalance", common.HexToAddress(user.Address)).Return(big.NewInt(1000), nil)
err := handler.HandleUserMessage(testutils.Context(t), &userRequestMsg, make(chan handlers.UserCallbackPayload))
require.Error(t, err)
}
From bd5a35b661caed4a4ce1afe8d275d41acc372c76 Mon Sep 17 00:00:00 2001
From: Cedric
Date: Thu, 16 Nov 2023 10:41:45 +0000
Subject: [PATCH 158/327] [BCF-2738] Modify build-publish-develop ECR (#11279)
- push images to chainlink-develop in production rather than
chainlink in the sdlc environment.
---
.github/workflows/build-publish-develop.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/build-publish-develop.yml b/.github/workflows/build-publish-develop.yml
index b885972237..a7220deec4 100644
--- a/.github/workflows/build-publish-develop.yml
+++ b/.github/workflows/build-publish-develop.yml
@@ -47,9 +47,9 @@ jobs:
publish: true
aws-role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }}
aws-role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }}
- aws-region: ${{ secrets.AWS_REGION }}
- ecr-hostname: ${{ secrets.AWS_DEVELOP_ECR_HOSTNAME }}
- ecr-image-name: chainlink
+ aws-region: us-west-2
+ ecr-hostname: 804282218731.dkr.ecr.us-west-2.com
+ ecr-image-name: chainlink-develop/chainlink
ecr-tag-suffix: ${{ matrix.image.tag-suffix }}
dockerfile: ${{ matrix.image.dockerfile }}
dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
From af2f91996db2a67f69f7c2582e69e1b5e6493d4d Mon Sep 17 00:00:00 2001
From: Cedric
Date: Thu, 16 Nov 2023 11:05:47 +0000
Subject: [PATCH 159/327] Revert "[BCF-2738] Modify build-publish-develop ECR
(#11279)" (#11310)
This reverts commit bd5a35b661caed4a4ce1afe8d275d41acc372c76.
---
.github/workflows/build-publish-develop.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/build-publish-develop.yml b/.github/workflows/build-publish-develop.yml
index a7220deec4..b885972237 100644
--- a/.github/workflows/build-publish-develop.yml
+++ b/.github/workflows/build-publish-develop.yml
@@ -47,9 +47,9 @@ jobs:
publish: true
aws-role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }}
aws-role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }}
- aws-region: us-west-2
- ecr-hostname: 804282218731.dkr.ecr.us-west-2.com
- ecr-image-name: chainlink-develop/chainlink
+ aws-region: ${{ secrets.AWS_REGION }}
+ ecr-hostname: ${{ secrets.AWS_DEVELOP_ECR_HOSTNAME }}
+ ecr-image-name: chainlink
ecr-tag-suffix: ${{ matrix.image.tag-suffix }}
dockerfile: ${{ matrix.image.dockerfile }}
dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
From 26e5e3740c8629c01c330e15c9fc35f55ca841ca Mon Sep 17 00:00:00 2001
From: Dimitris Grigoriou
Date: Thu, 16 Nov 2023 17:15:56 +0200
Subject: [PATCH 160/327] Extract Link and move Eth to evm folder (#11287)
* Extract Link and move Eth to evm folder
* Move ChainType to common folder
* Fix lint
* Fix currency relay imports
* Fix relay import dependency
* Fix lint
* Address comments
---
common/client/mock_rpc_test.go | 2 +-
common/client/multi_node.go | 4 +-
common/client/multi_node_test.go | 2 +-
common/client/types.go | 2 +-
{core => common}/config/chaintype.go | 0
core/assets/currencies.go | 301 ---------------
core/assets/currencies_test.go | 357 ------------------
core/bridges/bridge_type.go | 2 +-
core/bridges/bridge_type_test.go | 2 +-
core/chains/evm/assets/assets.go | 117 ++++++
core/chains/evm/assets/assets_test.go | 116 ++++++
core/{ => chains/evm}/assets/units.go | 0
core/{ => chains/evm}/assets/units_test.go | 2 +-
core/{ => chains/evm}/assets/wei.go | 0
core/{ => chains/evm}/assets/wei_test.go | 0
core/chains/evm/chain.go | 3 +-
core/chains/evm/client/chain_client.go | 7 +-
core/chains/evm/client/client.go | 4 +-
core/chains/evm/client/helpers_test.go | 2 +-
core/chains/evm/client/mocks/client.go | 2 +-
core/chains/evm/client/null_client.go | 2 +-
core/chains/evm/client/pool.go | 2 +-
core/chains/evm/client/rpc_client.go | 9 +-
core/chains/evm/client/send_only_node_test.go | 2 +-
.../evm/client/simulated_backend_client.go | 2 +-
core/chains/evm/config/chain_scoped.go | 13 +-
.../evm/config/chain_scoped_gas_estimator.go | 2 +-
core/chains/evm/config/config.go | 8 +-
core/chains/evm/config/config_test.go | 7 +-
core/chains/evm/config/mocks/gas_estimator.go | 2 +-
core/chains/evm/config/toml/config.go | 7 +-
core/chains/evm/config/toml/defaults.go | 2 +-
core/chains/evm/gas/arbitrum_estimator.go | 2 +-
.../chains/evm/gas/arbitrum_estimator_test.go | 2 +-
.../chains/evm/gas/block_history_estimator.go | 4 +-
.../evm/gas/block_history_estimator_test.go | 4 +-
core/chains/evm/gas/chain_specific.go | 4 +-
core/chains/evm/gas/cmd/arbgas/main.go | 2 +-
core/chains/evm/gas/fixed_price_estimator.go | 2 +-
.../evm/gas/fixed_price_estimator_test.go | 2 +-
core/chains/evm/gas/gas_test.go | 2 +-
core/chains/evm/gas/helpers_test.go | 4 +-
core/chains/evm/gas/mocks/config.go | 2 +-
core/chains/evm/gas/mocks/evm_estimator.go | 2 +-
.../chains/evm/gas/mocks/evm_fee_estimator.go | 2 +-
core/chains/evm/gas/models.go | 4 +-
core/chains/evm/gas/models_test.go | 2 +-
.../evm/gas/rollups/l1_gas_price_oracle.go | 4 +-
.../gas/rollups/l1_gas_price_oracle_test.go | 4 +-
.../chains/evm/gas/rollups/mocks/l1_oracle.go | 2 +-
core/chains/evm/gas/rollups/models.go | 2 +-
.../evm/gas/suggested_price_estimator.go | 2 +-
.../evm/gas/suggested_price_estimator_test.go | 2 +-
core/chains/evm/mocks/balance_monitor.go | 2 +-
core/chains/evm/monitor/balance.go | 2 +-
core/chains/evm/monitor/balance_test.go | 2 +-
core/chains/evm/txmgr/attempts.go | 2 +-
core/chains/evm/txmgr/attempts_test.go | 2 +-
core/chains/evm/txmgr/broadcaster_test.go | 2 +-
core/chains/evm/txmgr/config.go | 6 +-
core/chains/evm/txmgr/confirmer_test.go | 2 +-
core/chains/evm/txmgr/evm_tx_store.go | 2 +-
core/chains/evm/txmgr/evm_tx_store_test.go | 2 +-
core/chains/evm/txmgr/mocks/config.go | 2 +-
core/chains/evm/txmgr/test_helpers.go | 15 +-
core/chains/evm/txmgr/transmitchecker_test.go | 2 +-
core/chains/evm/txmgr/txmgr_test.go | 2 +-
.../evm/types/block_json_benchmark_test.go | 2 +-
core/chains/evm/types/models.go | 2 +-
core/chains/evm/types/models_test.go | 2 +-
core/cmd/cosmos_node_commands_test.go | 4 +-
core/cmd/eth_keys_commands_test.go | 13 +-
core/cmd/evm_transaction_commands.go | 2 +-
core/cmd/evm_transaction_commands_test.go | 2 +-
core/cmd/shell_local.go | 2 +-
core/cmd/solana_node_commands_test.go | 6 +-
core/cmd/starknet_node_commands_test.go | 6 +-
core/config/docs/docs_test.go | 2 +-
core/config/parse/parsers.go | 9 +-
core/internal/cltest/cltest.go | 2 +-
core/internal/cltest/factories.go | 2 +-
core/internal/features/features_test.go | 2 +-
.../features/ocr2/features_ocr2_test.go | 2 +-
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
core/scripts/ocr2vrf/main.go | 2 +-
core/scripts/vrfv2/testnet/main.go | 2 +-
core/scripts/vrfv2plus/testnet/main.go | 2 +-
core/services/chainlink/config_test.go | 71 ++--
.../relayer_chain_interoperators_test.go | 18 +-
core/services/directrequest/delegate.go | 2 +-
core/services/directrequest/delegate_test.go | 2 +-
core/services/directrequest/validate.go | 2 +-
core/services/fluxmonitorv2/config.go | 2 +-
.../fluxmonitorv2/flux_monitor_test.go | 2 +-
.../fluxmonitorv2/integrations_test.go | 2 +-
.../services/fluxmonitorv2/payment_checker.go | 2 +-
.../fluxmonitorv2/payment_checker_test.go | 2 +-
core/services/fluxmonitorv2/validate_test.go | 2 +-
core/services/functions/connector_handler.go | 2 +-
.../functions/connector_handler_test.go | 2 +-
.../handlers/functions/handler.functions.go | 2 +-
.../functions/handler.functions_test.go | 2 +-
core/services/job/job_orm_test.go | 2 +-
core/services/job/models.go | 7 +-
core/services/keeper/integration_test.go | 2 +-
core/services/keeper/upkeep_executer.go | 2 +-
core/services/keeper/upkeep_executer_test.go | 2 +-
.../keeper/upkeep_executer_unit_test.go | 2 +-
core/services/keystore/keys/ethkey/address.go | 4 +-
core/services/ocr/contract_tracker.go | 2 +-
core/services/ocr/validate.go | 2 +-
.../ocr2/plugins/functions/config/config.go | 2 +-
.../v1/internal/testutils.go | 2 +-
.../services/ocr2/plugins/functions/plugin.go | 2 +-
.../ocr2/plugins/functions/plugin_test.go | 2 +-
.../ocr2/plugins/mercury/integration_test.go | 2 +-
.../evm21/logprovider/integration_test.go | 2 +-
.../plugins/ocr2keeper/integration_21_test.go | 2 +-
.../plugins/ocr2keeper/integration_test.go | 2 +-
.../internal/ocr2vrf_integration_test.go | 2 +-
.../reasonable_gas_price_provider.go | 2 +-
.../reasonable_gas_price_test.go | 2 +-
core/services/ocrcommon/block_translator.go | 2 +-
core/services/ocrcommon/config.go | 2 +-
.../relay/evm/mercury/v1/data_source_test.go | 2 +-
.../services/transmission/integration_test.go | 2 +-
core/services/vrf/delegate.go | 2 +-
core/services/vrf/delegate_test.go | 2 +-
core/services/vrf/mocks/fee_config.go | 2 +-
.../services/vrf/proof/proof_response_test.go | 2 +-
.../vrf_coordinator_interface.go | 2 +-
.../vrf_coordinator_interface_test.go | 7 +-
.../vrf_hash_to_curve_cost_test.go | 2 +-
.../vrf_solidity_crosscheck_test.go | 2 +-
.../vrf_v08_solidity_crosscheck_test.go | 2 +-
core/services/vrf/v2/bhs_feeder_test.go | 2 +-
.../vrf/v2/integration_helpers_test.go | 2 +-
.../vrf/v2/integration_v2_plus_test.go | 2 +-
core/services/vrf/v2/integration_v2_test.go | 5 +-
core/services/vrf/v2/listener_v2.go | 2 +-
.../vrf/v2/listener_v2_helpers_test.go | 2 +-
core/services/vrf/vrfcommon/types.go | 2 +-
core/services/vrf/vrfcommon/validate.go | 2 +-
core/services/vrf/vrfcommon/validate_test.go | 2 +-
core/services/vrf/vrftesthelpers/helpers.go | 2 +-
core/store/models/common.go | 2 +-
core/testdata/testspecs/v2_specs.go | 2 +-
core/utils/big.go | 3 +-
core/utils/utils.go | 16 -
core/web/bridge_types_controller.go | 2 +-
core/web/bridge_types_controller_test.go | 2 +-
core/web/eth_keys_controller.go | 9 +-
core/web/eth_keys_controller_test.go | 2 +-
core/web/evm_transactions_controller_test.go | 2 +-
core/web/evm_transfer_controller.go | 2 +-
core/web/evm_transfer_controller_test.go | 2 +-
core/web/presenters/bridges.go | 2 +-
core/web/presenters/bridges_test.go | 2 +-
core/web/presenters/eth_key.go | 21 +-
core/web/presenters/eth_key_test.go | 7 +-
core/web/presenters/eth_tx.go | 2 +-
core/web/presenters/eth_tx_test.go | 2 +-
core/web/presenters/job.go | 7 +-
core/web/presenters/job_test.go | 2 +-
core/web/resolver/bridge_test.go | 2 +-
core/web/resolver/eth_key_test.go | 9 +-
core/web/resolver/eth_transaction.go | 2 +-
core/web/resolver/eth_transaction_test.go | 2 +-
core/web/resolver/helpers.go | 2 +-
core/web/resolver/mutation.go | 2 +-
core/web/resolver/spec_test.go | 9 +-
core/web/solana_chains_controller_test.go | 6 +-
go.mod | 2 +-
go.sum | 4 +-
.../actions/vrfv2plus/vrfv2plus_steps.go | 13 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
integration-tests/types/config/node/core.go | 7 +-
tools/flakeytests/runner_test.go | 88 ++---
180 files changed, 598 insertions(+), 1017 deletions(-)
rename {core => common}/config/chaintype.go (100%)
delete mode 100644 core/assets/currencies.go
delete mode 100644 core/assets/currencies_test.go
create mode 100644 core/chains/evm/assets/assets.go
create mode 100644 core/chains/evm/assets/assets_test.go
rename core/{ => chains/evm}/assets/units.go (100%)
rename core/{ => chains/evm}/assets/units_test.go (93%)
rename core/{ => chains/evm}/assets/wei.go (100%)
rename core/{ => chains/evm}/assets/wei_test.go (100%)
diff --git a/common/client/mock_rpc_test.go b/common/client/mock_rpc_test.go
index c378b9384e..8f171302a2 100644
--- a/common/client/mock_rpc_test.go
+++ b/common/client/mock_rpc_test.go
@@ -5,7 +5,7 @@ package client
import (
big "math/big"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
context "context"
diff --git a/common/client/multi_node.go b/common/client/multi_node.go
index c268cfb23c..df91c61a9d 100644
--- a/common/client/multi_node.go
+++ b/common/client/multi_node.go
@@ -11,12 +11,12 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go
index 1fddbc3be3..3621d6d862 100644
--- a/common/client/multi_node_test.go
+++ b/common/client/multi_node_test.go
@@ -14,8 +14,8 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/common/client/types.go b/common/client/types.go
index 0e52f1db72..ef9f94dafe 100644
--- a/common/client/types.go
+++ b/common/client/types.go
@@ -4,9 +4,9 @@ import (
"context"
"math/big"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/config/chaintype.go b/common/config/chaintype.go
similarity index 100%
rename from core/config/chaintype.go
rename to common/config/chaintype.go
diff --git a/core/assets/currencies.go b/core/assets/currencies.go
deleted file mode 100644
index 1201f0be35..0000000000
--- a/core/assets/currencies.go
+++ /dev/null
@@ -1,301 +0,0 @@
-package assets
-
-import (
- "database/sql/driver"
- "fmt"
- "math/big"
- "strings"
-
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/pkg/errors"
- "github.com/shopspring/decimal"
-)
-
-var ErrNoQuotesForCurrency = errors.New("cannot unmarshal json.Number into currency")
-
-// getDenominator returns 10**precision.
-func getDenominator(precision int) *big.Int {
- x := big.NewInt(10)
- return new(big.Int).Exp(x, big.NewInt(int64(precision)), nil)
-}
-
-func format(i *big.Int, precision int) string {
- r := big.NewRat(1, 1).SetFrac(i, getDenominator(precision))
- return fmt.Sprintf("%v", r.FloatString(precision))
-}
-
-// Link contains a field to represent the smallest units of LINK
-type Link big.Int
-
-// NewLinkFromJuels returns a new struct to represent LINK from it's smallest unit
-func NewLinkFromJuels(w int64) *Link {
- return (*Link)(big.NewInt(w))
-}
-
-// String returns Link formatted as a string.
-func (l *Link) String() string {
- if l == nil {
- return "0"
- }
- return fmt.Sprintf("%v", (*big.Int)(l))
-}
-
-// Link returns Link formatted as a string, in LINK units
-func (l *Link) Link() string {
- if l == nil {
- return "0"
- }
- return format((*big.Int)(l), 18)
-}
-
-// SetInt64 delegates to *big.Int.SetInt64
-func (l *Link) SetInt64(w int64) *Link {
- return (*Link)((*big.Int)(l).SetInt64(w))
-}
-
-// ToInt returns the Link value as a *big.Int.
-func (l *Link) ToInt() *big.Int {
- return (*big.Int)(l)
-}
-
-// ToHash returns a 32 byte representation of this value
-func (l *Link) ToHash() common.Hash {
- return common.BigToHash((*big.Int)(l))
-}
-
-// Set delegates to *big.Int.Set
-func (l *Link) Set(x *Link) *Link {
- il := (*big.Int)(l)
- ix := (*big.Int)(x)
-
- w := il.Set(ix)
- return (*Link)(w)
-}
-
-// SetString delegates to *big.Int.SetString
-func (l *Link) SetString(s string, base int) (*Link, bool) {
- w, ok := (*big.Int)(l).SetString(s, base)
- return (*Link)(w), ok
-}
-
-// Cmp defers to big.Int Cmp
-func (l *Link) Cmp(y *Link) int {
- return (*big.Int)(l).Cmp((*big.Int)(y))
-}
-
-// Add defers to big.Int Add
-func (l *Link) Add(x, y *Link) *Link {
- il := (*big.Int)(l)
- ix := (*big.Int)(x)
- iy := (*big.Int)(y)
-
- return (*Link)(il.Add(ix, iy))
-}
-
-// Text defers to big.Int Text
-func (l *Link) Text(base int) string {
- return (*big.Int)(l).Text(base)
-}
-
-var linkFmtThreshold = (*Link)(new(big.Int).Exp(big.NewInt(10), big.NewInt(12), nil))
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (l *Link) MarshalText() ([]byte, error) {
- if l.Cmp(linkFmtThreshold) >= 0 {
- return []byte(fmt.Sprintf("%s link", decimal.NewFromBigInt(l.ToInt(), -18))), nil
- }
- return (*big.Int)(l).MarshalText()
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (l Link) MarshalJSON() ([]byte, error) {
- value, err := l.MarshalText()
- if err != nil {
- return nil, err
- }
- return []byte(fmt.Sprintf(`"%s"`, value)), nil
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-func (l *Link) UnmarshalJSON(data []byte) error {
- if utils.IsQuoted(data) {
- return l.UnmarshalText(utils.RemoveQuotes(data))
- }
- return ErrNoQuotesForCurrency
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (l *Link) UnmarshalText(text []byte) error {
- s := string(text)
- if strings.HasSuffix(s, "link") {
- s = strings.TrimSuffix(s, "link")
- s = strings.TrimSuffix(s, " ")
- d, err := decimal.NewFromString(s)
- if err != nil {
- return errors.Wrapf(err, "assets: cannot unmarshal %q into a *assets.Link", text)
- }
- d = d.Mul(decimal.New(1, 18))
- if !d.IsInteger() {
- err := errors.New("maximum precision is juels")
- return errors.Wrapf(err, "assets: cannot unmarshal %q into a *assets.Link", text)
- }
- l.Set((*Link)(d.Rat().Num()))
- return nil
- }
- if strings.HasSuffix(s, "juels") {
- s = strings.TrimSuffix(s, "juels")
- s = strings.TrimSuffix(s, " ")
- }
- if _, ok := l.SetString(s, 10); !ok {
- return errors.Errorf("assets: cannot unmarshal %q into a *assets.Link", text)
- }
- return nil
-}
-
-// IsZero returns true when the value is 0 and false otherwise
-func (l *Link) IsZero() bool {
- zero := big.NewInt(0)
- return (*big.Int)(l).Cmp(zero) == 0
-}
-
-// Symbol returns LINK
-func (*Link) Symbol() string {
- return "LINK"
-}
-
-// Value returns the Link value for serialization to database.
-func (l Link) Value() (driver.Value, error) {
- b := (big.Int)(l)
- return b.String(), nil
-}
-
-// Scan reads the database value and returns an instance.
-func (l *Link) Scan(value interface{}) error {
- switch v := value.(type) {
- case string:
- decoded, ok := l.SetString(v, 10)
- if !ok {
- return fmt.Errorf("unable to set string %v of %T to base 10 big.Int for Link", value, value)
- }
- *l = *decoded
- case []uint8:
- // The SQL library returns numeric() types as []uint8 of the string representation
- decoded, ok := l.SetString(string(v), 10)
- if !ok {
- return fmt.Errorf("unable to set string %v of %T to base 10 big.Int for Link", value, value)
- }
- *l = *decoded
- case int64:
- return fmt.Errorf("unable to convert %v of %T to Link, is the sql type set to varchar?", value, value)
- default:
- return fmt.Errorf("unable to convert %v of %T to Link", value, value)
- }
-
- return nil
-}
-
-// Eth contains a field to represent the smallest units of ETH
-type Eth big.Int
-
-// NewEth returns a new struct to represent ETH from it's smallest unit (wei)
-func NewEth(w int64) *Eth {
- return (*Eth)(big.NewInt(w))
-}
-
-// NewEthValue returns a new struct to represent ETH from it's smallest unit (wei)
-func NewEthValue(w int64) Eth {
- eth := NewEth(w)
- return *eth
-}
-
-// NewEthValueS returns a new struct to represent ETH from a string value of Eth (not wei)
-// the underlying value is still wei
-func NewEthValueS(s string) (Eth, error) {
- e, err := decimal.NewFromString(s)
- if err != nil {
- return Eth{}, err
- }
- w := e.Mul(decimal.RequireFromString("10").Pow(decimal.RequireFromString("18")))
- return *(*Eth)(w.BigInt()), nil
-}
-
-// Cmp delegates to *big.Int.Cmp
-func (e *Eth) Cmp(y *Eth) int {
- return e.ToInt().Cmp(y.ToInt())
-}
-
-func (e *Eth) String() string {
- if e == nil {
- return ""
- }
- return format(e.ToInt(), 18)
-}
-
-// SetInt64 delegates to *big.Int.SetInt64
-func (e *Eth) SetInt64(w int64) *Eth {
- return (*Eth)(e.ToInt().SetInt64(w))
-}
-
-// SetString delegates to *big.Int.SetString
-func (e *Eth) SetString(s string, base int) (*Eth, bool) {
- w, ok := e.ToInt().SetString(s, base)
- return (*Eth)(w), ok
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (e Eth) MarshalJSON() ([]byte, error) {
- value, err := e.MarshalText()
- if err != nil {
- return nil, err
- }
- return []byte(fmt.Sprintf(`"%s"`, value)), nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (e *Eth) MarshalText() ([]byte, error) {
- return e.ToInt().MarshalText()
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-func (e *Eth) UnmarshalJSON(data []byte) error {
- if utils.IsQuoted(data) {
- return e.UnmarshalText(utils.RemoveQuotes(data))
- }
- return ErrNoQuotesForCurrency
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (e *Eth) UnmarshalText(text []byte) error {
- if _, ok := e.SetString(string(text), 10); !ok {
- return fmt.Errorf("assets: cannot unmarshal %q into a *assets.Eth", text)
- }
- return nil
-}
-
-// IsZero returns true when the value is 0 and false otherwise
-func (e *Eth) IsZero() bool {
- zero := big.NewInt(0)
- return e.ToInt().Cmp(zero) == 0
-}
-
-// Symbol returns ETH
-func (*Eth) Symbol() string {
- return "ETH"
-}
-
-// ToInt returns the Eth value as a *big.Int.
-func (e *Eth) ToInt() *big.Int {
- return (*big.Int)(e)
-}
-
-// Scan reads the database value and returns an instance.
-func (e *Eth) Scan(value interface{}) error {
- return (*utils.Big)(e).Scan(value)
-}
-
-// Value returns the Eth value for serialization to database.
-func (e Eth) Value() (driver.Value, error) {
- return (utils.Big)(e).Value()
-}
diff --git a/core/assets/currencies_test.go b/core/assets/currencies_test.go
deleted file mode 100644
index 5f2a00223f..0000000000
--- a/core/assets/currencies_test.go
+++ /dev/null
@@ -1,357 +0,0 @@
-package assets_test
-
-import (
- "encoding/json"
- "math/big"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "github.com/ethereum/go-ethereum/common"
-
- "github.com/smartcontractkit/chainlink/v2/core/assets"
-)
-
-func TestAssets_NewLinkAndString(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(0)
-
- assert.Equal(t, "0", link.String())
-
- link.SetInt64(1)
- assert.Equal(t, "1", link.String())
-
- link.SetString("900000000000000000", 10)
- assert.Equal(t, "900000000000000000", link.String())
-
- link.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639935", 10)
- assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457584007913129639935", link.String())
-
- var nilLink *assets.Link
- assert.Equal(t, "0", nilLink.String())
-}
-
-func TestAssets_NewLinkAndLink(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(0)
-
- assert.Equal(t, "0.000000000000000000", link.Link())
-
- link.SetInt64(1)
- assert.Equal(t, "0.000000000000000001", link.Link())
-
- link.SetString("900000000000000000", 10)
- assert.Equal(t, "0.900000000000000000", link.Link())
-
- link.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639935", 10)
- assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457.584007913129639935", link.Link())
-
- link.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639936", 10)
- assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457.584007913129639936", link.Link())
-
- var nilLink *assets.Link
- assert.Equal(t, "0", nilLink.Link())
-}
-
-func TestAssets_Link_MarshalJson(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(1)
-
- b, err := json.Marshal(link)
- assert.NoError(t, err)
- assert.Equal(t, []byte(`"1"`), b)
-}
-
-func TestAssets_Link_UnmarshalJsonOk(t *testing.T) {
- t.Parallel()
-
- link := assets.Link{}
-
- err := json.Unmarshal([]byte(`"1"`), &link)
- assert.NoError(t, err)
- assert.Equal(t, "0.000000000000000001", link.Link())
-}
-
-func TestAssets_Link_UnmarshalJsonError(t *testing.T) {
- t.Parallel()
-
- link := assets.Link{}
-
- err := json.Unmarshal([]byte(`"x"`), &link)
- assert.EqualError(t, err, "assets: cannot unmarshal \"x\" into a *assets.Link")
-
- err = json.Unmarshal([]byte(`1`), &link)
- assert.Equal(t, assets.ErrNoQuotesForCurrency, err)
-}
-
-func TestAssets_NewEthAndString(t *testing.T) {
- t.Parallel()
-
- eth := assets.NewEth(0)
-
- assert.Equal(t, "0.000000000000000000", eth.String())
-
- eth.SetInt64(1)
- assert.Equal(t, "0.000000000000000001", eth.String())
-
- eth.SetString("900000000000000000", 10)
- assert.Equal(t, "0.900000000000000000", eth.String())
-
- eth.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639935", 10)
- assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457.584007913129639935", eth.String())
-
- eth.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639936", 10)
- assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457.584007913129639936", eth.String())
-}
-
-func TestAssets_Eth_IsZero(t *testing.T) {
- t.Parallel()
-
- zeroEth := assets.NewEth(0)
- assert.True(t, zeroEth.IsZero())
-
- oneLink := assets.NewEth(1)
- assert.False(t, oneLink.IsZero())
-}
-
-func TestAssets_Eth_MarshalJson(t *testing.T) {
- t.Parallel()
-
- eth := assets.NewEth(1)
-
- b, err := json.Marshal(eth)
- assert.NoError(t, err)
- assert.Equal(t, []byte(`"1"`), b)
-}
-
-func TestAssets_Eth_UnmarshalJsonOk(t *testing.T) {
- t.Parallel()
-
- eth := assets.Eth{}
-
- err := json.Unmarshal([]byte(`"1"`), ð)
- assert.NoError(t, err)
- assert.Equal(t, "0.000000000000000001", eth.String())
-}
-
-func TestAssets_Eth_UnmarshalJsonError(t *testing.T) {
- t.Parallel()
-
- eth := assets.Eth{}
-
- err := json.Unmarshal([]byte(`"x"`), ð)
- assert.EqualError(t, err, "assets: cannot unmarshal \"x\" into a *assets.Eth")
-
- err = json.Unmarshal([]byte(`1`), ð)
- assert.Equal(t, assets.ErrNoQuotesForCurrency, err)
-}
-
-func TestAssets_LinkToInt(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(0)
- assert.Equal(t, big.NewInt(0), link.ToInt())
-
- link = assets.NewLinkFromJuels(123)
- assert.Equal(t, big.NewInt(123), link.ToInt())
-}
-
-func TestAssets_LinkToHash(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(123)
- expected := common.BigToHash((*big.Int)(link))
- assert.Equal(t, expected, link.ToHash())
-}
-
-func TestAssets_LinkSetLink(t *testing.T) {
- t.Parallel()
-
- link1 := assets.NewLinkFromJuels(123)
- link2 := assets.NewLinkFromJuels(321)
- link3 := link1.Set(link2)
- assert.Equal(t, link3, link2)
-}
-
-func TestAssets_LinkCmpLink(t *testing.T) {
- t.Parallel()
-
- link1 := assets.NewLinkFromJuels(123)
- link2 := assets.NewLinkFromJuels(321)
- assert.NotZero(t, link1.Cmp(link2))
-
- link3 := assets.NewLinkFromJuels(321)
- assert.Zero(t, link3.Cmp(link2))
-}
-
-func TestAssets_LinkAddLink(t *testing.T) {
- t.Parallel()
-
- link1 := assets.NewLinkFromJuels(123)
- link2 := assets.NewLinkFromJuels(321)
- sum := assets.NewLinkFromJuels(123 + 321)
- assert.Equal(t, sum, link1.Add(link1, link2))
-}
-
-func TestAssets_LinkText(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(123)
- assert.Equal(t, "123", link.Text(10))
- assert.Equal(t, "7b", link.Text(16))
-}
-
-func TestAssets_LinkIsZero(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(123)
- assert.False(t, link.IsZero())
-
- link = assets.NewLinkFromJuels(0)
- assert.True(t, link.IsZero())
-}
-
-func TestAssets_LinkSymbol(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(123)
- assert.Equal(t, "LINK", link.Symbol())
-}
-
-func TestAssets_LinkScanValue(t *testing.T) {
- t.Parallel()
-
- link := assets.NewLinkFromJuels(123)
- v, err := link.Value()
- assert.NoError(t, err)
-
- link2 := assets.NewLinkFromJuels(0)
- err = link2.Scan(v)
- assert.NoError(t, err)
- assert.Equal(t, link2, link)
-
- err = link2.Scan("123")
- assert.NoError(t, err)
- assert.Equal(t, link2, link)
-
- err = link2.Scan([]uint8{'1', '2', '3'})
- assert.NoError(t, err)
- assert.Equal(t, link2, link)
-
- assert.ErrorContains(t, link2.Scan([]uint8{'x'}), "unable to set string")
- assert.ErrorContains(t, link2.Scan("123.56"), "unable to set string")
- assert.ErrorContains(t, link2.Scan(1.5), "unable to convert")
- assert.ErrorContains(t, link2.Scan(int64(123)), "unable to convert")
-}
-
-func TestAssets_NewEth(t *testing.T) {
- t.Parallel()
-
- ethRef := assets.NewEth(123)
- ethVal := assets.NewEthValue(123)
- ethStr, err := assets.NewEthValueS(ethRef.String())
- assert.NoError(t, err)
- assert.Equal(t, *ethRef, ethVal)
- assert.Equal(t, *ethRef, ethStr)
-}
-
-func TestAssets_EthSymbol(t *testing.T) {
- t.Parallel()
-
- eth := assets.NewEth(123)
- assert.Equal(t, "ETH", eth.Symbol())
-}
-
-func TestAssets_EthScanValue(t *testing.T) {
- t.Parallel()
-
- eth := assets.NewEth(123)
- v, err := eth.Value()
- assert.NoError(t, err)
-
- eth2 := assets.NewEth(0)
- err = eth2.Scan(v)
- assert.NoError(t, err)
-
- assert.Equal(t, eth, eth2)
-}
-
-func TestAssets_EthCmpEth(t *testing.T) {
- t.Parallel()
-
- eth1 := assets.NewEth(123)
- eth2 := assets.NewEth(321)
- assert.NotZero(t, eth1.Cmp(eth2))
-
- eth3 := assets.NewEth(321)
- assert.Zero(t, eth3.Cmp(eth2))
-}
-
-func TestLink(t *testing.T) {
- for _, tt := range []struct {
- input string
- exp string
- }{
- {"0", "0"},
- {"1", "1"},
- {"1 juels", "1"},
- {"100000000000", "100000000000"},
- {"0.0000001 link", "100000000000"},
- {"1000000000000", "0.000001 link"},
- {"100000000000000", "0.0001 link"},
- {"0.0001 link", "0.0001 link"},
- {"10000000000000000", "0.01 link"},
- {"0.01 link", "0.01 link"},
- {"100000000000000000", "0.1 link"},
- {"0.1 link", "0.1 link"},
- {"1.0 link", "1 link"},
- {"1000000000000000000", "1 link"},
- {"1000000000000000000 juels", "1 link"},
- {"1100000000000000000", "1.1 link"},
- {"1.1link", "1.1 link"},
- {"1.1 link", "1.1 link"},
- } {
- t.Run(tt.input, func(t *testing.T) {
- var l assets.Link
- err := l.UnmarshalText([]byte(tt.input))
- require.NoError(t, err)
- b, err := l.MarshalText()
- require.NoError(t, err)
- assert.Equal(t, tt.exp, string(b))
- })
- }
-}
-
-func FuzzLink(f *testing.F) {
- f.Add("1")
- f.Add("1 link")
- f.Add("1.1link")
- f.Add("2.3")
- f.Add("2.3 link")
- f.Add("00005 link")
- f.Add("0.0005link")
- f.Add("1100000000000000000000000000000")
- f.Add("1100000000000000000000000000000 juels")
- f.Fuzz(func(t *testing.T, v string) {
- if len(v) > 1_000 {
- t.Skip()
- }
- var l assets.Link
- err := l.UnmarshalText([]byte(v))
- if err != nil {
- t.Skip()
- }
-
- b, err := l.MarshalText()
- require.NoErrorf(t, err, "failed to marshal %v after unmarshaling from %q", l, v)
-
- var l2 assets.Link
- err = l2.UnmarshalText(b)
- require.NoErrorf(t, err, "failed to unmarshal %s after marshaling from %v", string(b), l)
- require.Equal(t, l, l2, "unequal values after marshal/unmarshal")
- })
-}
diff --git a/core/bridges/bridge_type.go b/core/bridges/bridge_type.go
index 9b3a8570ca..9031541f22 100644
--- a/core/bridges/bridge_type.go
+++ b/core/bridges/bridge_type.go
@@ -10,7 +10,7 @@ import (
"strings"
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/bridges/bridge_type_test.go b/core/bridges/bridge_type_test.go
index 8c4a7cbace..c04aba5c2c 100644
--- a/core/bridges/bridge_type_test.go
+++ b/core/bridges/bridge_type_test.go
@@ -11,7 +11,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
diff --git a/core/chains/evm/assets/assets.go b/core/chains/evm/assets/assets.go
new file mode 100644
index 0000000000..c6c81b5ab4
--- /dev/null
+++ b/core/chains/evm/assets/assets.go
@@ -0,0 +1,117 @@
+package assets
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "math/big"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/utils/bytes"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+
+ "github.com/shopspring/decimal"
+)
+
+// Eth contains a field to represent the smallest units of ETH
+type Eth big.Int
+
+// NewEth returns a new struct to represent ETH from it's smallest unit (wei)
+func NewEth(w int64) *Eth {
+ return (*Eth)(big.NewInt(w))
+}
+
+// NewEthValue returns a new struct to represent ETH from it's smallest unit (wei)
+func NewEthValue(w int64) Eth {
+ eth := NewEth(w)
+ return *eth
+}
+
+// NewEthValueS returns a new struct to represent ETH from a string value of Eth (not wei)
+// the underlying value is still wei
+func NewEthValueS(s string) (Eth, error) {
+ e, err := decimal.NewFromString(s)
+ if err != nil {
+ return Eth{}, err
+ }
+ w := e.Mul(decimal.RequireFromString("10").Pow(decimal.RequireFromString("18")))
+ return *(*Eth)(w.BigInt()), nil
+}
+
+// Cmp delegates to *big.Int.Cmp
+func (e *Eth) Cmp(y *Eth) int {
+ return e.ToInt().Cmp(y.ToInt())
+}
+
+func (e *Eth) String() string {
+ if e == nil {
+ return ""
+ }
+ return assets.Format(e.ToInt(), 18)
+}
+
+// SetInt64 delegates to *big.Int.SetInt64
+func (e *Eth) SetInt64(w int64) *Eth {
+ return (*Eth)(e.ToInt().SetInt64(w))
+}
+
+// SetString delegates to *big.Int.SetString
+func (e *Eth) SetString(s string, base int) (*Eth, bool) {
+ w, ok := e.ToInt().SetString(s, base)
+ return (*Eth)(w), ok
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (e Eth) MarshalJSON() ([]byte, error) {
+ value, err := e.MarshalText()
+ if err != nil {
+ return nil, err
+ }
+ return []byte(fmt.Sprintf(`"%s"`, value)), nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (e *Eth) MarshalText() ([]byte, error) {
+ return e.ToInt().MarshalText()
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (e *Eth) UnmarshalJSON(data []byte) error {
+ if bytes.HasQuotes(data) {
+ return e.UnmarshalText(bytes.TrimQuotes(data))
+ }
+ return assets.ErrNoQuotesForCurrency
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (e *Eth) UnmarshalText(text []byte) error {
+ if _, ok := e.SetString(string(text), 10); !ok {
+ return fmt.Errorf("assets: cannot unmarshal %q into a *assets.Eth", text)
+ }
+ return nil
+}
+
+// IsZero returns true when the value is 0 and false otherwise
+func (e *Eth) IsZero() bool {
+ zero := big.NewInt(0)
+ return e.ToInt().Cmp(zero) == 0
+}
+
+// Symbol returns ETH
+func (*Eth) Symbol() string {
+ return "ETH"
+}
+
+// ToInt returns the Eth value as a *big.Int.
+func (e *Eth) ToInt() *big.Int {
+ return (*big.Int)(e)
+}
+
+// Scan reads the database value and returns an instance.
+func (e *Eth) Scan(value interface{}) error {
+ return (*utils.Big)(e).Scan(value)
+}
+
+// Value returns the Eth value for serialization to database.
+func (e Eth) Value() (driver.Value, error) {
+ return (utils.Big)(e).Value()
+}
diff --git a/core/chains/evm/assets/assets_test.go b/core/chains/evm/assets/assets_test.go
new file mode 100644
index 0000000000..9496554f11
--- /dev/null
+++ b/core/chains/evm/assets/assets_test.go
@@ -0,0 +1,116 @@
+package assets_test
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
+)
+
+func TestAssets_NewEthAndString(t *testing.T) {
+ t.Parallel()
+
+ eth := assets.NewEth(0)
+
+ assert.Equal(t, "0.000000000000000000", eth.String())
+
+ eth.SetInt64(1)
+ assert.Equal(t, "0.000000000000000001", eth.String())
+
+ eth.SetString("900000000000000000", 10)
+ assert.Equal(t, "0.900000000000000000", eth.String())
+
+ eth.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639935", 10)
+ assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457.584007913129639935", eth.String())
+
+ eth.SetString("115792089237316195423570985008687907853269984665640564039457584007913129639936", 10)
+ assert.Equal(t, "115792089237316195423570985008687907853269984665640564039457.584007913129639936", eth.String())
+}
+
+func TestAssets_Eth_IsZero(t *testing.T) {
+ t.Parallel()
+
+ zeroEth := assets.NewEth(0)
+ assert.True(t, zeroEth.IsZero())
+
+ oneLink := assets.NewEth(1)
+ assert.False(t, oneLink.IsZero())
+}
+
+func TestAssets_Eth_MarshalJson(t *testing.T) {
+ t.Parallel()
+
+ eth := assets.NewEth(1)
+
+ b, err := json.Marshal(eth)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte(`"1"`), b)
+}
+
+func TestAssets_Eth_UnmarshalJsonOk(t *testing.T) {
+ t.Parallel()
+
+ eth := assets.Eth{}
+
+ err := json.Unmarshal([]byte(`"1"`), ð)
+ assert.NoError(t, err)
+ assert.Equal(t, "0.000000000000000001", eth.String())
+}
+
+func TestAssets_Eth_UnmarshalJsonError(t *testing.T) {
+ t.Parallel()
+
+ eth := assets.Eth{}
+
+ err := json.Unmarshal([]byte(`"x"`), ð)
+ assert.EqualError(t, err, "assets: cannot unmarshal \"x\" into a *assets.Eth")
+
+ err = json.Unmarshal([]byte(`1`), ð)
+ assert.Equal(t, relayassets.ErrNoQuotesForCurrency, err)
+}
+
+func TestAssets_NewEth(t *testing.T) {
+ t.Parallel()
+
+ ethRef := assets.NewEth(123)
+ ethVal := assets.NewEthValue(123)
+ ethStr, err := assets.NewEthValueS(ethRef.String())
+ assert.NoError(t, err)
+ assert.Equal(t, *ethRef, ethVal)
+ assert.Equal(t, *ethRef, ethStr)
+}
+
+func TestAssets_EthSymbol(t *testing.T) {
+ t.Parallel()
+
+ eth := assets.NewEth(123)
+ assert.Equal(t, "ETH", eth.Symbol())
+}
+
+func TestAssets_EthScanValue(t *testing.T) {
+ t.Parallel()
+
+ eth := assets.NewEth(123)
+ v, err := eth.Value()
+ assert.NoError(t, err)
+
+ eth2 := assets.NewEth(0)
+ err = eth2.Scan(v)
+ assert.NoError(t, err)
+
+ assert.Equal(t, eth, eth2)
+}
+
+func TestAssets_EthCmpEth(t *testing.T) {
+ t.Parallel()
+
+ eth1 := assets.NewEth(123)
+ eth2 := assets.NewEth(321)
+ assert.NotZero(t, eth1.Cmp(eth2))
+
+ eth3 := assets.NewEth(321)
+ assert.Zero(t, eth3.Cmp(eth2))
+}
diff --git a/core/assets/units.go b/core/chains/evm/assets/units.go
similarity index 100%
rename from core/assets/units.go
rename to core/chains/evm/assets/units.go
diff --git a/core/assets/units_test.go b/core/chains/evm/assets/units_test.go
similarity index 93%
rename from core/assets/units_test.go
rename to core/chains/evm/assets/units_test.go
index 7b23072033..37eb139325 100644
--- a/core/assets/units_test.go
+++ b/core/chains/evm/assets/units_test.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
)
func TestAssets_Units(t *testing.T) {
diff --git a/core/assets/wei.go b/core/chains/evm/assets/wei.go
similarity index 100%
rename from core/assets/wei.go
rename to core/chains/evm/assets/wei.go
diff --git a/core/assets/wei_test.go b/core/chains/evm/assets/wei_test.go
similarity index 100%
rename from core/assets/wei_test.go
rename to core/chains/evm/assets/wei_test.go
diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go
index b5896393d3..f21bf2525a 100644
--- a/core/chains/evm/chain.go
+++ b/core/chains/evm/chain.go
@@ -17,6 +17,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
@@ -473,7 +474,7 @@ func (c *chain) Logger() logger.Logger { return c.logger }
func (c *chain) BalanceMonitor() monitor.BalanceMonitor { return c.balanceMonitor }
func (c *chain) GasEstimator() gas.EvmFeeEstimator { return c.gasEstimator }
-func newEthClientFromChain(cfg evmconfig.NodePool, noNewHeadsThreshold time.Duration, lggr logger.Logger, chainID *big.Int, chainType config.ChainType, nodes []*toml.Node) (evmclient.Client, error) {
+func newEthClientFromChain(cfg evmconfig.NodePool, noNewHeadsThreshold time.Duration, lggr logger.Logger, chainID *big.Int, chainType commonconfig.ChainType, nodes []*toml.Node) (evmclient.Client, error) {
var primaries []evmclient.Node
var sendonlys []evmclient.SendOnlyNode
for i, node := range nodes {
diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go
index 4c5108745c..79a91dfc05 100644
--- a/core/chains/evm/client/chain_client.go
+++ b/core/chains/evm/client/chain_client.go
@@ -10,10 +10,11 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
@@ -182,7 +183,7 @@ func (c *chainClient) IsL2() bool {
return c.multiNode.IsL2()
}
-func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*assets.Link, error) {
+func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*relayassets.Link, error) {
return c.multiNode.LINKBalance(ctx, address, linkAddress)
}
diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go
index fb8a39f379..988a7404c9 100644
--- a/core/chains/evm/client/client.go
+++ b/core/chains/evm/client/client.go
@@ -6,11 +6,11 @@ import (
"strings"
"time"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go
index 2820ba992c..b1d477b1a2 100644
--- a/core/chains/evm/client/helpers_test.go
+++ b/core/chains/evm/client/helpers_test.go
@@ -10,9 +10,9 @@ import (
"github.com/pkg/errors"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- commonconfig "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go
index 7617a7c05f..f1ff5fab45 100644
--- a/core/chains/evm/client/mocks/client.go
+++ b/core/chains/evm/client/mocks/client.go
@@ -5,7 +5,7 @@ package mocks
import (
big "math/big"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
common "github.com/ethereum/go-ethereum/common"
diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go
index 286f62b3b8..45876d9259 100644
--- a/core/chains/evm/client/null_client.go
+++ b/core/chains/evm/client/null_client.go
@@ -9,8 +9,8 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go
index 2d679ab3d7..473ab6d1eb 100644
--- a/core/chains/evm/client/pool.go
+++ b/core/chains/evm/client/pool.go
@@ -17,8 +17,8 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go
index 04b9fad1fc..f952c04d5b 100644
--- a/core/chains/evm/client/rpc_client.go
+++ b/core/chains/evm/client/rpc_client.go
@@ -17,9 +17,10 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -868,12 +869,12 @@ func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, co
}
// LINKBalance returns the balance of LINK at the given address
-func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*assets.Link, error) {
+func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*relayassets.Link, error) {
balance, err := r.TokenBalance(ctx, address, linkAddress)
if err != nil {
- return assets.NewLinkFromJuels(0), err
+ return relayassets.NewLinkFromJuels(0), err
}
- return (*assets.Link)(balance), nil
+ return (*relayassets.Link)(balance), nil
}
func (r *rpcClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
diff --git a/core/chains/evm/client/send_only_node_test.go b/core/chains/evm/client/send_only_node_test.go
index b37ee14253..876ae9bc4d 100644
--- a/core/chains/evm/client/send_only_node_test.go
+++ b/core/chains/evm/client/send_only_node_test.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go
index f4ad6a65a1..33ecc3d0d5 100644
--- a/core/chains/evm/client/simulated_backend_client.go
+++ b/core/chains/evm/client/simulated_backend_client.go
@@ -18,8 +18,8 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/chains/evm/config/chain_scoped.go b/core/chains/evm/config/chain_scoped.go
index 7971a18d4d..6030991179 100644
--- a/core/chains/evm/config/chain_scoped.go
+++ b/core/chains/evm/config/chain_scoped.go
@@ -9,13 +9,14 @@ import (
ocr "github.com/smartcontractkit/libocr/offchainreporting"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
- gencfg "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
-func NewTOMLChainScopedConfig(appCfg gencfg.AppConfig, tomlConfig *toml.EVMConfig, lggr logger.Logger) *ChainScoped {
+func NewTOMLChainScopedConfig(appCfg config.AppConfig, tomlConfig *toml.EVMConfig, lggr logger.Logger) *ChainScoped {
return &ChainScoped{
AppConfig: appCfg,
evmConfig: &evmConfig{c: tomlConfig},
@@ -24,7 +25,7 @@ func NewTOMLChainScopedConfig(appCfg gencfg.AppConfig, tomlConfig *toml.EVMConfi
// ChainScoped implements config.ChainScopedConfig with a gencfg.BasicConfig and EVMConfig.
type ChainScoped struct {
- gencfg.AppConfig
+ config.AppConfig
lggr logger.Logger
evmConfig *evmConfig
@@ -140,11 +141,11 @@ func (e *evmConfig) BlockEmissionIdleWarningThreshold() time.Duration {
return e.c.NoNewHeadsThreshold.Duration()
}
-func (e *evmConfig) ChainType() gencfg.ChainType {
+func (e *evmConfig) ChainType() commonconfig.ChainType {
if e.c.ChainType == nil {
return ""
}
- return gencfg.ChainType(*e.c.ChainType)
+ return commonconfig.ChainType(*e.c.ChainType)
}
func (e *evmConfig) ChainID() *big.Int {
diff --git a/core/chains/evm/config/chain_scoped_gas_estimator.go b/core/chains/evm/config/chain_scoped_gas_estimator.go
index cc28ce75f0..0c52cf0a46 100644
--- a/core/chains/evm/config/chain_scoped_gas_estimator.go
+++ b/core/chains/evm/config/chain_scoped_gas_estimator.go
@@ -3,7 +3,7 @@ package config
import (
gethcommon "github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
)
diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go
index f8ec030969..ec90797d7f 100644
--- a/core/chains/evm/config/config.go
+++ b/core/chains/evm/config/config.go
@@ -6,7 +6,9 @@ import (
gethcommon "github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/config"
)
@@ -24,7 +26,7 @@ type EVM interface {
BlockBackfillSkip() bool
BlockEmissionIdleWarningThreshold() time.Duration
ChainID() *big.Int
- ChainType() config.ChainType
+ ChainType() commonconfig.ChainType
FinalityDepth() uint32
FinalityTagEnabled() bool
FlagsContractAddress() string
@@ -32,7 +34,7 @@ type EVM interface {
LogBackfillBatchSize() uint32
LogKeepBlocksDepth() uint32
LogPollInterval() time.Duration
- MinContractPayment() *assets.Link
+ MinContractPayment() *relayassets.Link
MinIncomingConfirmations() uint32
NonceAutoSync() bool
OperatorFactoryAddress() string
diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go
index 0a3fc5f41e..d34d1eae63 100644
--- a/core/chains/evm/config/config_test.go
+++ b/core/chains/evm/config/config_test.go
@@ -11,7 +11,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
@@ -402,7 +403,7 @@ func Test_chainScopedConfig_Validate(t *testing.T) {
t.Run("arbitrum-estimator", func(t *testing.T) {
t.Run("custom", func(t *testing.T) {
cfg := configWithChains(t, 0, &toml.Chain{
- ChainType: ptr(string(config.ChainArbitrum)),
+ ChainType: ptr(string(commonconfig.ChainArbitrum)),
GasEstimator: toml.GasEstimator{
Mode: ptr("BlockHistory"),
},
@@ -433,7 +434,7 @@ func Test_chainScopedConfig_Validate(t *testing.T) {
t.Run("optimism-estimator", func(t *testing.T) {
t.Run("custom", func(t *testing.T) {
cfg := configWithChains(t, 0, &toml.Chain{
- ChainType: ptr(string(config.ChainOptimismBedrock)),
+ ChainType: ptr(string(commonconfig.ChainOptimismBedrock)),
GasEstimator: toml.GasEstimator{
Mode: ptr("BlockHistory"),
},
diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go
index 8cb54132f5..6260b3cd50 100644
--- a/core/chains/evm/config/mocks/gas_estimator.go
+++ b/core/chains/evm/config/mocks/gas_estimator.go
@@ -4,7 +4,7 @@ package mocks
import (
common "github.com/ethereum/go-ethereum/common"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
config "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go
index cf2cde460e..ae0fb41c5e 100644
--- a/core/chains/evm/config/toml/config.go
+++ b/core/chains/evm/config/toml/config.go
@@ -12,12 +12,13 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
@@ -354,7 +355,7 @@ type Chain struct {
LogPollInterval *models.Duration
LogKeepBlocksDepth *uint32
MinIncomingConfirmations *uint32
- MinContractPayment *assets.Link
+ MinContractPayment *relayassets.Link
NonceAutoSync *bool
NoNewHeadsThreshold *models.Duration
OperatorFactoryAddress *ethkey.EIP55Address
diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go
index 6851338358..d362e9ac3d 100644
--- a/core/chains/evm/config/toml/defaults.go
+++ b/core/chains/evm/config/toml/defaults.go
@@ -8,7 +8,7 @@ import (
"slices"
"strings"
- "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/utils"
configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config"
)
diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go
index 78d93243bb..860126a588 100644
--- a/core/chains/evm/gas/arbitrum_estimator.go
+++ b/core/chains/evm/gas/arbitrum_estimator.go
@@ -16,7 +16,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/chains/evm/gas/arbitrum_estimator_test.go b/core/chains/evm/gas/arbitrum_estimator_test.go
index a226368edf..894b531dc9 100644
--- a/core/chains/evm/gas/arbitrum_estimator_test.go
+++ b/core/chains/evm/gas/arbitrum_estimator_test.go
@@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go
index 80ae19f109..eb35cd2751 100644
--- a/core/chains/evm/gas/block_history_estimator.go
+++ b/core/chains/evm/gas/block_history_estimator.go
@@ -16,12 +16,12 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/utils/mathutil"
diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go
index c8b193c443..2747ea067d 100644
--- a/core/chains/evm/gas/block_history_estimator_test.go
+++ b/core/chains/evm/gas/block_history_estimator_test.go
@@ -18,12 +18,12 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go
index 4f0d2e6b2f..c989cd0aa9 100644
--- a/core/chains/evm/gas/chain_specific.go
+++ b/core/chains/evm/gas/chain_specific.go
@@ -1,9 +1,9 @@
package gas
import (
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
)
// chainSpecificIsUsable allows for additional logic specific to a particular
diff --git a/core/chains/evm/gas/cmd/arbgas/main.go b/core/chains/evm/gas/cmd/arbgas/main.go
index 4ceeb0009e..6b79ff2f13 100644
--- a/core/chains/evm/gas/cmd/arbgas/main.go
+++ b/core/chains/evm/gas/cmd/arbgas/main.go
@@ -12,7 +12,7 @@ import (
"go.uber.org/zap/zapcore"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/chains/evm/gas/fixed_price_estimator.go b/core/chains/evm/gas/fixed_price_estimator.go
index a45df741a2..7eb7454dad 100644
--- a/core/chains/evm/gas/fixed_price_estimator.go
+++ b/core/chains/evm/gas/fixed_price_estimator.go
@@ -7,7 +7,7 @@ import (
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/chains/evm/gas/fixed_price_estimator_test.go b/core/chains/evm/gas/fixed_price_estimator_test.go
index a6cb313e5e..9fa0997c10 100644
--- a/core/chains/evm/gas/fixed_price_estimator_test.go
+++ b/core/chains/evm/gas/fixed_price_estimator_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/gas/gas_test.go b/core/chains/evm/gas/gas_test.go
index 4c6be2cf50..a3f7224a09 100644
--- a/core/chains/evm/gas/gas_test.go
+++ b/core/chains/evm/gas/gas_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go
index ac1f5129e0..9a5076be6d 100644
--- a/core/chains/evm/gas/helpers_test.go
+++ b/core/chains/evm/gas/helpers_test.go
@@ -6,9 +6,9 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
)
func init() {
diff --git a/core/chains/evm/gas/mocks/config.go b/core/chains/evm/gas/mocks/config.go
index eabbd0f03e..c09005b5e3 100644
--- a/core/chains/evm/gas/mocks/config.go
+++ b/core/chains/evm/gas/mocks/config.go
@@ -3,7 +3,7 @@
package mocks
import (
- config "github.com/smartcontractkit/chainlink/v2/core/config"
+ config "github.com/smartcontractkit/chainlink/v2/common/config"
mock "github.com/stretchr/testify/mock"
)
diff --git a/core/chains/evm/gas/mocks/evm_estimator.go b/core/chains/evm/gas/mocks/evm_estimator.go
index 80ab3c68cc..f2cb51f856 100644
--- a/core/chains/evm/gas/mocks/evm_estimator.go
+++ b/core/chains/evm/gas/mocks/evm_estimator.go
@@ -5,7 +5,7 @@ package mocks
import (
context "context"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/gas/mocks/evm_fee_estimator.go b/core/chains/evm/gas/mocks/evm_fee_estimator.go
index 42ea96cd50..b9b1636779 100644
--- a/core/chains/evm/gas/mocks/evm_fee_estimator.go
+++ b/core/chains/evm/gas/mocks/evm_fee_estimator.go
@@ -5,7 +5,7 @@ package mocks
import (
big "math/big"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
context "context"
diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go
index 299d7d5473..50cbddcd9b 100644
--- a/core/chains/evm/gas/models.go
+++ b/core/chains/evm/gas/models.go
@@ -11,16 +11,16 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math"
)
diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go
index c1dd9e44ff..8ac94a2269 100644
--- a/core/chains/evm/gas/models_test.go
+++ b/core/chains/evm/gas/models_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks"
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
index d990017bd0..09244e9d31 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
@@ -13,9 +13,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go
index 320c9cb71d..801d72919e 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle_test.go
@@ -13,8 +13,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
- "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle.go b/core/chains/evm/gas/rollups/mocks/l1_oracle.go
index 31407300b6..f6f8cc736a 100644
--- a/core/chains/evm/gas/rollups/mocks/l1_oracle.go
+++ b/core/chains/evm/gas/rollups/mocks/l1_oracle.go
@@ -5,7 +5,7 @@ package mocks
import (
context "context"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
mock "github.com/stretchr/testify/mock"
)
diff --git a/core/chains/evm/gas/rollups/models.go b/core/chains/evm/gas/rollups/models.go
index 83ae29f4ea..1659436071 100644
--- a/core/chains/evm/gas/rollups/models.go
+++ b/core/chains/evm/gas/rollups/models.go
@@ -3,7 +3,7 @@ package rollups
import (
"context"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services"
)
diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go
index a4ffb80997..24cf20f172 100644
--- a/core/chains/evm/gas/suggested_price_estimator.go
+++ b/core/chains/evm/gas/suggested_price_estimator.go
@@ -11,7 +11,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/gas/suggested_price_estimator_test.go b/core/chains/evm/gas/suggested_price_estimator_test.go
index 808b28a3a6..3b6b8184e3 100644
--- a/core/chains/evm/gas/suggested_price_estimator_test.go
+++ b/core/chains/evm/gas/suggested_price_estimator_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/chains/evm/mocks/balance_monitor.go b/core/chains/evm/mocks/balance_monitor.go
index 2a5e66bbc0..cdda18b7f0 100644
--- a/core/chains/evm/mocks/balance_monitor.go
+++ b/core/chains/evm/mocks/balance_monitor.go
@@ -4,7 +4,7 @@ package mocks
import (
common "github.com/ethereum/go-ethereum/common"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
context "context"
diff --git a/core/chains/evm/monitor/balance.go b/core/chains/evm/monitor/balance.go
index 5f5b8a243b..476d3c7019 100644
--- a/core/chains/evm/monitor/balance.go
+++ b/core/chains/evm/monitor/balance.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/monitor/balance_test.go b/core/chains/evm/monitor/balance_test.go
index c80d64e7ef..6a62549e49 100644
--- a/core/chains/evm/monitor/balance_test.go
+++ b/core/chains/evm/monitor/balance_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/monitor"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go
index 7b2a05a34c..06c1126b86 100644
--- a/core/chains/evm/txmgr/attempts.go
+++ b/core/chains/evm/txmgr/attempts.go
@@ -12,7 +12,7 @@ import (
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go
index 863eae4723..11304384ab 100644
--- a/core/chains/evm/txmgr/attempts_test.go
+++ b/core/chains/evm/txmgr/attempts_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 460f9629fb..48b68f9b55 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -25,7 +25,7 @@ import (
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
diff --git a/core/chains/evm/txmgr/config.go b/core/chains/evm/txmgr/config.go
index 0e6b46574a..8346a0d055 100644
--- a/core/chains/evm/txmgr/config.go
+++ b/core/chains/evm/txmgr/config.go
@@ -5,9 +5,9 @@ import (
gethcommon "github.com/ethereum/go-ethereum/common"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
- coreconfig "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
)
// ChainConfig encompasses config used by txmgr package
@@ -15,7 +15,7 @@ import (
//
//go:generate mockery --quiet --recursive --name ChainConfig --output ./mocks/ --case=underscore --structname Config --filename config.go
type ChainConfig interface {
- ChainType() coreconfig.ChainType
+ ChainType() config.ChainType
FinalityDepth() uint32
FinalityTagEnabled() bool
NonceAutoSync() bool
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index 3a0d33f7ba..31464f8f52 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -24,7 +24,7 @@ import (
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index c3371fee80..9262c85a83 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -20,7 +20,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/label"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go
index f8798f9f83..73bfc6fc85 100644
--- a/core/chains/evm/txmgr/evm_tx_store_test.go
+++ b/core/chains/evm/txmgr/evm_tx_store_test.go
@@ -9,7 +9,7 @@ import (
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/txmgr/mocks/config.go b/core/chains/evm/txmgr/mocks/config.go
index d6f961ccb5..ab98d686c8 100644
--- a/core/chains/evm/txmgr/mocks/config.go
+++ b/core/chains/evm/txmgr/mocks/config.go
@@ -3,7 +3,7 @@
package mocks
import (
- config "github.com/smartcontractkit/chainlink/v2/core/config"
+ config "github.com/smartcontractkit/chainlink/v2/common/config"
mock "github.com/stretchr/testify/mock"
)
diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go
index f9c0423a62..e279dddf5f 100644
--- a/core/chains/evm/txmgr/test_helpers.go
+++ b/core/chains/evm/txmgr/test_helpers.go
@@ -6,7 +6,8 @@ import (
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
@@ -136,12 +137,12 @@ func (c *MockConfig) EVM() evmconfig.EVM {
return c.EvmConfig
}
-func (c *MockConfig) NonceAutoSync() bool { return true }
-func (c *MockConfig) ChainType() config.ChainType { return "" }
-func (c *MockConfig) FinalityDepth() uint32 { return c.finalityDepth }
-func (c *MockConfig) SetFinalityDepth(fd uint32) { c.finalityDepth = fd }
-func (c *MockConfig) FinalityTagEnabled() bool { return c.finalityTagEnabled }
-func (c *MockConfig) RPCDefaultBatchSize() uint32 { return c.RpcDefaultBatchSize }
+func (c *MockConfig) NonceAutoSync() bool { return true }
+func (c *MockConfig) ChainType() commonconfig.ChainType { return "" }
+func (c *MockConfig) FinalityDepth() uint32 { return c.finalityDepth }
+func (c *MockConfig) SetFinalityDepth(fd uint32) { c.finalityDepth = fd }
+func (c *MockConfig) FinalityTagEnabled() bool { return c.finalityTagEnabled }
+func (c *MockConfig) RPCDefaultBatchSize() uint32 { return c.RpcDefaultBatchSize }
func MakeTestConfigs(t *testing.T) (*MockConfig, *TestDatabaseConfig, *TestEvmConfig) {
db := &TestDatabaseConfig{defaultQueryTimeout: pg.DefaultQueryTimeout}
diff --git a/core/chains/evm/txmgr/transmitchecker_test.go b/core/chains/evm/txmgr/transmitchecker_test.go
index 79868e6a64..b43fcb4f45 100644
--- a/core/chains/evm/txmgr/transmitchecker_test.go
+++ b/core/chains/evm/txmgr/transmitchecker_test.go
@@ -21,7 +21,7 @@ import (
"github.com/stretchr/testify/require"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
v1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go
index 4e201b9c6f..e27cea137b 100644
--- a/core/chains/evm/txmgr/txmgr_test.go
+++ b/core/chains/evm/txmgr/txmgr_test.go
@@ -19,7 +19,7 @@ import (
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
diff --git a/core/chains/evm/types/block_json_benchmark_test.go b/core/chains/evm/types/block_json_benchmark_test.go
index 8c5f766d63..21c58bd198 100644
--- a/core/chains/evm/types/block_json_benchmark_test.go
+++ b/core/chains/evm/types/block_json_benchmark_test.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
)
diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go
index c2d61e0070..83b90b4d53 100644
--- a/core/chains/evm/types/models.go
+++ b/core/chains/evm/types/models.go
@@ -18,7 +18,7 @@ import (
htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types"
commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types/internal/blocks"
"github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go
index 2911e426e8..3507b6a131 100644
--- a/core/chains/evm/types/models_test.go
+++ b/core/chains/evm/types/models_test.go
@@ -17,7 +17,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/cmd/cosmos_node_commands_test.go b/core/cmd/cosmos_node_commands_test.go
index 9ac7dfb2ba..591160629e 100644
--- a/core/cmd/cosmos_node_commands_test.go
+++ b/core/cmd/cosmos_node_commands_test.go
@@ -11,7 +11,7 @@ import (
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
+ relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
@@ -35,7 +35,7 @@ func TestShell_IndexCosmosNodes(t *testing.T) {
chainID := cosmostest.RandomChainID()
node := config.Node{
Name: ptr("second"),
- TendermintURL: utils.MustParseURL("http://tender.mint.test/bombay-12"),
+ TendermintURL: relaycfg.MustParseURL("http://tender.mint.test/bombay-12"),
}
chain := config.TOMLConfig{
ChainID: ptr(chainID),
diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go
index 630e76783a..d74ae231d7 100644
--- a/core/cmd/eth_keys_commands_test.go
+++ b/core/cmd/eth_keys_commands_test.go
@@ -12,7 +12,8 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
@@ -34,7 +35,7 @@ func TestEthKeysPresenter_RenderTable(t *testing.T) {
var (
address = "0x5431F5F973781809D18643b87B44921b11355d81"
ethBalance = assets.NewEth(1)
- linkBalance = assets.NewLinkFromJuels(2)
+ linkBalance = relayassets.NewLinkFromJuels(2)
isDisabled = true
createdAt = time.Now()
updatedAt = time.Now().Add(time.Second)
@@ -89,7 +90,7 @@ func TestShell_ListETHKeys(t *testing.T) {
ethClient := newEthMock(t)
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(assets.NewLinkFromJuels(13), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(13), nil)
ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil)
app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].Enabled = ptr(true)
@@ -168,7 +169,7 @@ func TestShell_CreateETHKey(t *testing.T) {
ethClient := newEthMock(t)
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(assets.NewLinkFromJuels(42), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(42), nil)
ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil)
app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
@@ -243,7 +244,7 @@ func TestShell_ImportExportETHKey_NoChains(t *testing.T) {
ethClient := newEthMock(t)
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(assets.NewLinkFromJuels(42), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(42), nil)
ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil)
app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].Enabled = ptr(true)
@@ -361,7 +362,7 @@ func TestShell_ImportExportETHKey_WithChains(t *testing.T) {
ethClient.On("Dial", mock.Anything).Maybe()
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(assets.NewLinkFromJuels(42), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(42), nil)
set := flag.NewFlagSet("test", 0)
cltest.FlagSetApplyFromAction(client.RemoteLogin, set, "")
diff --git a/core/cmd/evm_transaction_commands.go b/core/cmd/evm_transaction_commands.go
index 68fffde303..d702bc3b79 100644
--- a/core/cmd/evm_transaction_commands.go
+++ b/core/cmd/evm_transaction_commands.go
@@ -10,7 +10,7 @@ import (
"github.com/urfave/cli"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/utils/stringutils"
diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go
index 484b1ccd3d..e071d875f0 100644
--- a/core/cmd/evm_transaction_commands_test.go
+++ b/core/cmd/evm_transaction_commands_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go
index 70d75f761b..f7e17ef7fc 100644
--- a/core/cmd/shell_local.go
+++ b/core/cmd/shell_local.go
@@ -31,8 +31,8 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"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"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/cmd/solana_node_commands_test.go b/core/cmd/solana_node_commands_test.go
index 3f95ebc0d8..7c88557c6d 100644
--- a/core/cmd/solana_node_commands_test.go
+++ b/core/cmd/solana_node_commands_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
+ "github.com/smartcontractkit/chainlink-relay/pkg/config"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
@@ -35,11 +35,11 @@ func TestShell_IndexSolanaNodes(t *testing.T) {
id := solanatest.RandomChainID()
node1 := solcfg.Node{
Name: ptr("first"),
- URL: utils.MustParseURL("https://solana1.example"),
+ URL: config.MustParseURL("https://solana1.example"),
}
node2 := solcfg.Node{
Name: ptr("second"),
- URL: utils.MustParseURL("https://solana2.example"),
+ URL: config.MustParseURL("https://solana2.example"),
}
chain := solana.TOMLConfig{
ChainID: &id,
diff --git a/core/cmd/starknet_node_commands_test.go b/core/cmd/starknet_node_commands_test.go
index e799e5aac0..9d7c6fcaf4 100644
--- a/core/cmd/starknet_node_commands_test.go
+++ b/core/cmd/starknet_node_commands_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
+ relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
@@ -34,11 +34,11 @@ func TestShell_IndexStarkNetNodes(t *testing.T) {
id := "starknet chain ID"
node1 := config.Node{
Name: ptr("first"),
- URL: utils.MustParseURL("https://starknet1.example"),
+ URL: relaycfg.MustParseURL("https://starknet1.example"),
}
node2 := config.Node{
Name: ptr("second"),
- URL: utils.MustParseURL("https://starknet2.example"),
+ URL: relaycfg.MustParseURL("https://starknet2.example"),
}
chain := config.TOMLConfig{
ChainID: &id,
diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go
index 927592e448..74fa6682c9 100644
--- a/core/config/docs/docs_test.go
+++ b/core/config/docs/docs_test.go
@@ -14,7 +14,7 @@ import (
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config/docs"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/config/parse/parsers.go b/core/config/parse/parsers.go
index 93e519064b..e2f6978187 100644
--- a/core/config/parse/parsers.go
+++ b/core/config/parse/parsers.go
@@ -13,7 +13,8 @@ import (
"github.com/pkg/errors"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/static"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -22,10 +23,10 @@ func String(str string) (string, error) {
return str, nil
}
-func Link(str string) (*assets.Link, error) {
- i, ok := new(assets.Link).SetString(str, 10)
+func Link(str string) (*relayassets.Link, error) {
+ i, ok := new(relayassets.Link).SetString(str, 10)
if !ok {
- return i, fmt.Errorf("unable to parse '%v' into *assets.Link(base 10)", str)
+ return i, fmt.Errorf("unable to parse '%v' into *relayassets.Link(base 10)", str)
}
return i, nil
}
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 778ccbdb15..644c516c21 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -47,10 +47,10 @@ import (
"github.com/smartcontractkit/chainlink/v2/common/client"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go
index a52b9a5d06..741afe828f 100644
--- a/core/internal/cltest/factories.go
+++ b/core/internal/cltest/factories.go
@@ -25,9 +25,9 @@ import (
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go
index b5f42d8bf3..7749b173c5 100644
--- a/core/internal/features/features_test.go
+++ b/core/internal/features/features_test.go
@@ -41,9 +41,9 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting/confighelper"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go
index 3e22093568..387b15f76c 100644
--- a/core/internal/features/ocr2/features_ocr2_test.go
+++ b/core/internal/features/ocr2/features_ocr2_test.go
@@ -34,8 +34,8 @@ import (
confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index eb41312a6a..7bf60aff8b 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -304,7 +304,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a // indirect
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 35e85fe2c9..7139f0efa4 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1464,8 +1464,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a h1:G/pD8uI1PULRJU8Y3eLLzjqQBp9ruG9hj+wWxtyrgTo=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd h1:PRVJxNK67pQWufXuB1cxckH/xZkcQFDy8KjN9ZYqong=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd/go.mod h1:rOayi690YxLlkQy959PD8INhOAIAUi9LoN0G+J/CEf4=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/core/scripts/ocr2vrf/main.go b/core/scripts/ocr2vrf/main.go
index 60260c54d9..c698fcd730 100644
--- a/core/scripts/ocr2vrf/main.go
+++ b/core/scripts/ocr2vrf/main.go
@@ -15,7 +15,7 @@ import (
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
)
diff --git a/core/scripts/vrfv2/testnet/main.go b/core/scripts/vrfv2/testnet/main.go
index 677c0b105e..5856256504 100644
--- a/core/scripts/vrfv2/testnet/main.go
+++ b/core/scripts/vrfv2/testnet/main.go
@@ -24,7 +24,7 @@ import (
"github.com/jmoiron/sqlx"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2"
diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go
index b7940d6fda..6b1ef585a5 100644
--- a/core/scripts/vrfv2plus/testnet/main.go
+++ b/core/scripts/vrfv2plus/testnet/main.go
@@ -29,7 +29,7 @@ import (
"github.com/jmoiron/sqlx"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus"
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 34fcc4bbe9..0caae3607f 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -17,12 +17,13 @@ import (
ocrcommontypes "github.com/smartcontractkit/libocr/commontypes"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- relayutils "github.com/smartcontractkit/chainlink-relay/pkg/utils"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
legacy "github.com/smartcontractkit/chainlink/v2/core/config"
@@ -144,7 +145,7 @@ var (
MaxMsgsPerBatch: ptr[int64](13),
},
Nodes: []*coscfg.Node{
- {Name: ptr("primary"), TendermintURL: relayutils.MustParseURL("http://columbus.cosmos.com")},
+ {Name: ptr("primary"), TendermintURL: relaycfg.MustParseURL("http://columbus.cosmos.com")},
}},
{
ChainID: ptr("Malaga-420"),
@@ -152,7 +153,7 @@ var (
BlocksUntilTxTimeout: ptr[int64](20),
},
Nodes: []*coscfg.Node{
- {Name: ptr("secondary"), TendermintURL: relayutils.MustParseURL("http://bombay.cosmos.com")},
+ {Name: ptr("secondary"), TendermintURL: relaycfg.MustParseURL("http://bombay.cosmos.com")},
}},
},
Solana: []*solana.TOMLConfig{
@@ -162,16 +163,16 @@ var (
MaxRetries: ptr[int64](12),
},
Nodes: []*solcfg.Node{
- {Name: ptr("primary"), URL: relayutils.MustParseURL("http://mainnet.solana.com")},
+ {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://mainnet.solana.com")},
},
},
{
ChainID: ptr("testnet"),
Chain: solcfg.Chain{
- OCR2CachePollPeriod: relayutils.MustNewDuration(time.Minute),
+ OCR2CachePollPeriod: relaycfg.MustNewDuration(time.Minute),
},
Nodes: []*solcfg.Node{
- {Name: ptr("secondary"), URL: relayutils.MustParseURL("http://testnet.solana.com")},
+ {Name: ptr("secondary"), URL: relaycfg.MustParseURL("http://testnet.solana.com")},
},
},
},
@@ -179,10 +180,10 @@ var (
{
ChainID: ptr("foobar"),
Chain: stkcfg.Chain{
- ConfirmationPoll: relayutils.MustNewDuration(time.Hour),
+ ConfirmationPoll: relaycfg.MustNewDuration(time.Hour),
},
Nodes: []*stkcfg.Node{
- {Name: ptr("primary"), URL: relayutils.MustParseURL("http://stark.node")},
+ {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://stark.node")},
},
},
},
@@ -537,7 +538,7 @@ func TestConfig_Marshal(t *testing.T) {
LogBackfillBatchSize: ptr[uint32](17),
LogPollInterval: &minute,
LogKeepBlocksDepth: ptr[uint32](100000),
- MinContractPayment: assets.NewLinkFromJuels(math.MaxInt64),
+ MinContractPayment: relayassets.NewLinkFromJuels(math.MaxInt64),
MinIncomingConfirmations: ptr[uint32](13),
NonceAutoSync: ptr(true),
NoNewHeadsThreshold: &minute,
@@ -602,13 +603,13 @@ func TestConfig_Marshal(t *testing.T) {
ChainID: ptr("mainnet"),
Enabled: ptr(false),
Chain: solcfg.Chain{
- BalancePollPeriod: relayutils.MustNewDuration(time.Minute),
- ConfirmPollPeriod: relayutils.MustNewDuration(time.Second),
- OCR2CachePollPeriod: relayutils.MustNewDuration(time.Minute),
- OCR2CacheTTL: relayutils.MustNewDuration(time.Hour),
- TxTimeout: relayutils.MustNewDuration(time.Hour),
- TxRetryTimeout: relayutils.MustNewDuration(time.Minute),
- TxConfirmTimeout: relayutils.MustNewDuration(time.Second),
+ BalancePollPeriod: relaycfg.MustNewDuration(time.Minute),
+ ConfirmPollPeriod: relaycfg.MustNewDuration(time.Second),
+ OCR2CachePollPeriod: relaycfg.MustNewDuration(time.Minute),
+ OCR2CacheTTL: relaycfg.MustNewDuration(time.Hour),
+ TxTimeout: relaycfg.MustNewDuration(time.Hour),
+ TxRetryTimeout: relaycfg.MustNewDuration(time.Minute),
+ TxConfirmTimeout: relaycfg.MustNewDuration(time.Second),
SkipPreflight: ptr(true),
Commitment: ptr("banana"),
MaxRetries: ptr[int64](7),
@@ -616,12 +617,12 @@ func TestConfig_Marshal(t *testing.T) {
ComputeUnitPriceMax: ptr[uint64](1000),
ComputeUnitPriceMin: ptr[uint64](10),
ComputeUnitPriceDefault: ptr[uint64](100),
- FeeBumpPeriod: relayutils.MustNewDuration(time.Minute),
+ FeeBumpPeriod: relaycfg.MustNewDuration(time.Minute),
},
Nodes: []*solcfg.Node{
- {Name: ptr("primary"), URL: relayutils.MustParseURL("http://solana.web")},
- {Name: ptr("foo"), URL: relayutils.MustParseURL("http://solana.foo")},
- {Name: ptr("bar"), URL: relayutils.MustParseURL("http://solana.bar")},
+ {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://solana.web")},
+ {Name: ptr("foo"), URL: relaycfg.MustParseURL("http://solana.foo")},
+ {Name: ptr("bar"), URL: relaycfg.MustParseURL("http://solana.bar")},
},
},
}
@@ -630,14 +631,14 @@ func TestConfig_Marshal(t *testing.T) {
ChainID: ptr("foobar"),
Enabled: ptr(true),
Chain: stkcfg.Chain{
- OCR2CachePollPeriod: relayutils.MustNewDuration(6 * time.Hour),
- OCR2CacheTTL: relayutils.MustNewDuration(3 * time.Minute),
- RequestTimeout: relayutils.MustNewDuration(time.Minute + 3*time.Second),
- TxTimeout: relayutils.MustNewDuration(13 * time.Second),
- ConfirmationPoll: relayutils.MustNewDuration(42 * time.Second),
+ OCR2CachePollPeriod: relaycfg.MustNewDuration(6 * time.Hour),
+ OCR2CacheTTL: relaycfg.MustNewDuration(3 * time.Minute),
+ RequestTimeout: relaycfg.MustNewDuration(time.Minute + 3*time.Second),
+ TxTimeout: relaycfg.MustNewDuration(13 * time.Second),
+ ConfirmationPoll: relaycfg.MustNewDuration(42 * time.Second),
},
Nodes: []*stkcfg.Node{
- {Name: ptr("primary"), URL: relayutils.MustParseURL("http://stark.node")},
+ {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://stark.node")},
},
},
}
@@ -647,21 +648,21 @@ func TestConfig_Marshal(t *testing.T) {
Enabled: ptr(true),
Chain: coscfg.Chain{
Bech32Prefix: ptr("wasm"),
- BlockRate: relayutils.MustNewDuration(time.Minute),
+ BlockRate: relaycfg.MustNewDuration(time.Minute),
BlocksUntilTxTimeout: ptr[int64](12),
- ConfirmPollPeriod: relayutils.MustNewDuration(time.Second),
+ ConfirmPollPeriod: relaycfg.MustNewDuration(time.Second),
FallbackGasPrice: mustDecimal("0.001"),
GasToken: ptr("ucosm"),
GasLimitMultiplier: mustDecimal("1.2"),
MaxMsgsPerBatch: ptr[int64](17),
- OCR2CachePollPeriod: relayutils.MustNewDuration(time.Minute),
- OCR2CacheTTL: relayutils.MustNewDuration(time.Hour),
- TxMsgTimeout: relayutils.MustNewDuration(time.Second),
+ OCR2CachePollPeriod: relaycfg.MustNewDuration(time.Minute),
+ OCR2CacheTTL: relaycfg.MustNewDuration(time.Hour),
+ TxMsgTimeout: relaycfg.MustNewDuration(time.Second),
},
Nodes: []*coscfg.Node{
- {Name: ptr("primary"), TendermintURL: relayutils.MustParseURL("http://tender.mint")},
- {Name: ptr("foo"), TendermintURL: relayutils.MustParseURL("http://foo.url")},
- {Name: ptr("bar"), TendermintURL: relayutils.MustParseURL("http://bar.web")},
+ {Name: ptr("primary"), TendermintURL: relaycfg.MustParseURL("http://tender.mint")},
+ {Name: ptr("foo"), TendermintURL: relaycfg.MustParseURL("http://foo.url")},
+ {Name: ptr("bar"), TendermintURL: relaycfg.MustParseURL("http://bar.web")},
},
},
}
diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go
index 8729306964..293cc298c8 100644
--- a/core/services/chainlink/relayer_chain_interoperators_test.go
+++ b/core/services/chainlink/relayer_chain_interoperators_test.go
@@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/require"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
+ relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
- relayutils "github.com/smartcontractkit/chainlink-relay/pkg/utils"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
@@ -84,7 +84,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Chain: solcfg.Chain{},
Nodes: []*solcfg.Node{{
Name: ptr("solana chain 1 node 1"),
- URL: ((*relayutils.URL)(models.MustParseURL("http://localhost:8547").URL())),
+ URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8547").URL())),
}},
},
&solana.TOMLConfig{
@@ -93,7 +93,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Chain: solcfg.Chain{},
Nodes: []*solcfg.Node{{
Name: ptr("solana chain 2 node 1"),
- URL: ((*relayutils.URL)(models.MustParseURL("http://localhost:8527").URL())),
+ URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8527").URL())),
}},
},
}
@@ -106,15 +106,15 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: []*stkcfg.Node{
{
Name: ptr("starknet chain 1 node 1"),
- URL: ((*relayutils.URL)(models.MustParseURL("http://localhost:8547").URL())),
+ URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8547").URL())),
},
{
Name: ptr("starknet chain 1 node 2"),
- URL: ((*relayutils.URL)(models.MustParseURL("http://localhost:8548").URL())),
+ URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8548").URL())),
},
{
Name: ptr("starknet chain 1 node 3"),
- URL: ((*relayutils.URL)(models.MustParseURL("http://localhost:8549").URL())),
+ URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8549").URL())),
},
},
},
@@ -125,7 +125,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: []*stkcfg.Node{
{
Name: ptr("starknet chain 2 node 1"),
- URL: ((*relayutils.URL)(models.MustParseURL("http://localhost:3547").URL())),
+ URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:3547").URL())),
},
},
},
@@ -143,7 +143,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: coscfg.Nodes{
&coscfg.Node{
Name: ptr("cosmos chain 1 node 1"),
- TendermintURL: (*relayutils.URL)(models.MustParseURL("http://localhost:9548").URL()),
+ TendermintURL: (*relaycfg.URL)(models.MustParseURL("http://localhost:9548").URL()),
},
},
},
@@ -158,7 +158,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: coscfg.Nodes{
&coscfg.Node{
Name: ptr("cosmos chain 2 node 1"),
- TendermintURL: (*relayutils.URL)(models.MustParseURL("http://localhost:9598").URL()),
+ TendermintURL: (*relaycfg.URL)(models.MustParseURL("http://localhost:9598").URL()),
},
},
},
diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go
index 920f94b4d6..10943308b3 100644
--- a/core/services/directrequest/delegate.go
+++ b/core/services/directrequest/delegate.go
@@ -9,9 +9,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go
index 34c79a0afb..1c7929d94d 100644
--- a/core/services/directrequest/delegate_test.go
+++ b/core/services/directrequest/delegate_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
diff --git a/core/services/directrequest/validate.go b/core/services/directrequest/validate.go
index 95ea9b6023..cdb478e8aa 100644
--- a/core/services/directrequest/validate.go
+++ b/core/services/directrequest/validate.go
@@ -4,7 +4,7 @@ import (
"github.com/pelletier/go-toml"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/services/fluxmonitorv2/config.go b/core/services/fluxmonitorv2/config.go
index 5e5e56e768..0360e9ce03 100644
--- a/core/services/fluxmonitorv2/config.go
+++ b/core/services/fluxmonitorv2/config.go
@@ -3,7 +3,7 @@ package fluxmonitorv2
import (
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go
index e81e1ba9e6..e8bbf739bb 100644
--- a/core/services/fluxmonitorv2/flux_monitor_test.go
+++ b/core/services/fluxmonitorv2/flux_monitor_test.go
@@ -20,8 +20,8 @@ import (
"github.com/jmoiron/sqlx"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go
index 38c73d3ad7..729bcd76eb 100644
--- a/core/services/fluxmonitorv2/integrations_test.go
+++ b/core/services/fluxmonitorv2/integrations_test.go
@@ -26,8 +26,8 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"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"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper"
faw "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper"
diff --git a/core/services/fluxmonitorv2/payment_checker.go b/core/services/fluxmonitorv2/payment_checker.go
index 6b11ec1343..b5dbd73c06 100644
--- a/core/services/fluxmonitorv2/payment_checker.go
+++ b/core/services/fluxmonitorv2/payment_checker.go
@@ -3,7 +3,7 @@ package fluxmonitorv2
import (
"math/big"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
)
// MinFundedRounds defines the minimum number of rounds that needs to be paid
diff --git a/core/services/fluxmonitorv2/payment_checker_test.go b/core/services/fluxmonitorv2/payment_checker_test.go
index c987fdf360..48a06553cb 100644
--- a/core/services/fluxmonitorv2/payment_checker_test.go
+++ b/core/services/fluxmonitorv2/payment_checker_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2"
)
diff --git a/core/services/fluxmonitorv2/validate_test.go b/core/services/fluxmonitorv2/validate_test.go
index 78dda2e3d3..b397e6d374 100644
--- a/core/services/fluxmonitorv2/validate_test.go
+++ b/core/services/fluxmonitorv2/validate_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils/tomlutils"
diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go
index c5dbff6f10..5b67e333d2 100644
--- a/core/services/functions/connector_handler.go
+++ b/core/services/functions/connector_handler.go
@@ -10,9 +10,9 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/common"
diff --git a/core/services/functions/connector_handler_test.go b/core/services/functions/connector_handler_test.go
index fa9f74712b..1bf9f8e593 100644
--- a/core/services/functions/connector_handler_test.go
+++ b/core/services/functions/connector_handler_test.go
@@ -7,7 +7,7 @@ import (
"math/big"
"testing"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/functions"
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index bb6812c1f9..a4301ef7e9 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -13,8 +13,8 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/gateway/handlers/functions/handler.functions_test.go b/core/services/gateway/handlers/functions/handler.functions_test.go
index 49fdae2bb2..4c8ba5bec3 100644
--- a/core/services/gateway/handlers/functions/handler.functions_test.go
+++ b/core/services/gateway/handlers/functions/handler.functions_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index f4471e75c6..c2fc425918 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -16,8 +16,8 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/services/job/models.go b/core/services/job/models.go
index a474040dd4..0b3e622f59 100644
--- a/core/services/job/models.go
+++ b/core/services/job/models.go
@@ -14,10 +14,11 @@ import (
"github.com/pkg/errors"
"gopkg.in/guregu/null.v4"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
@@ -433,7 +434,7 @@ type DirectRequestSpec struct {
ContractAddress ethkey.EIP55Address `toml:"contractAddress"`
MinIncomingConfirmations clnull.Uint32 `toml:"minIncomingConfirmations"`
Requesters models.AddressCollection `toml:"requesters"`
- MinContractPayment *assets.Link `toml:"minContractPaymentLinkJuels"`
+ MinContractPayment *relayassets.Link `toml:"minContractPaymentLinkJuels"`
EVMChainID *utils.Big `toml:"evmChainID"`
CreatedAt time.Time `toml:"-"`
UpdatedAt time.Time `toml:"-"`
@@ -474,7 +475,7 @@ type FluxMonitorSpec struct {
DrumbeatSchedule string
DrumbeatRandomDelay time.Duration
DrumbeatEnabled bool
- MinPayment *assets.Link
+ MinPayment *relayassets.Link
EVMChainID *utils.Big `toml:"evmChainID"`
CreatedAt time.Time `toml:"-"`
UpdatedAt time.Time `toml:"-"`
diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go
index f76ef93574..29a0b68702 100644
--- a/core/services/keeper/integration_test.go
+++ b/core/services/keeper/integration_test.go
@@ -16,7 +16,7 @@ import (
"github.com/smartcontractkit/libocr/gethwrappers/link_token_interface"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder"
diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go
index 33ad8b7d77..30e9f36357 100644
--- a/core/services/keeper/upkeep_executer.go
+++ b/core/services/keeper/upkeep_executer.go
@@ -13,7 +13,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go
index 32b1d2c191..a064c3ed4b 100644
--- a/core/services/keeper/upkeep_executer_test.go
+++ b/core/services/keeper/upkeep_executer_test.go
@@ -15,8 +15,8 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
diff --git a/core/services/keeper/upkeep_executer_unit_test.go b/core/services/keeper/upkeep_executer_unit_test.go
index f4e99341ca..a8fc46319c 100644
--- a/core/services/keeper/upkeep_executer_unit_test.go
+++ b/core/services/keeper/upkeep_executer_unit_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/services/keystore/keys/ethkey/address.go b/core/services/keystore/keys/ethkey/address.go
index 4a161045ea..c14b602c59 100644
--- a/core/services/keystore/keys/ethkey/address.go
+++ b/core/services/keystore/keys/ethkey/address.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
+ "github.com/smartcontractkit/chainlink-relay/pkg/utils/bytes"
)
// EIP55Address is a new type for string which persists an ethereum address in
@@ -85,7 +85,7 @@ func (a *EIP55Address) UnmarshalText(input []byte) error {
// UnmarshalJSON parses a hash from a JSON string
func (a *EIP55Address) UnmarshalJSON(input []byte) error {
- input = utils.RemoveQuotes(input)
+ input = bytes.TrimQuotes(input)
return a.UnmarshalText(input)
}
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index db19bdd4f0..3e614fef4a 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -22,11 +22,11 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/offchain_aggregator_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
diff --git a/core/services/ocr/validate.go b/core/services/ocr/validate.go
index 07fdc15912..145bb7597e 100644
--- a/core/services/ocr/validate.go
+++ b/core/services/ocr/validate.go
@@ -10,9 +10,9 @@ import (
"github.com/pkg/errors"
"github.com/smartcontractkit/libocr/offchainreporting"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
diff --git a/core/services/ocr2/plugins/functions/config/config.go b/core/services/ocr2/plugins/functions/config/config.go
index 0978500deb..a179a22ce4 100644
--- a/core/services/ocr2/plugins/functions/config/config.go
+++ b/core/services/ocr2/plugins/functions/config/config.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions"
diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go
index 9f63d60eef..e576e82967 100644
--- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go
+++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go
@@ -29,8 +29,8 @@ import (
confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_allow_list"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_client_example"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator"
diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go
index 8597b8ad4c..14d7415cab 100644
--- a/core/services/ocr2/plugins/functions/plugin.go
+++ b/core/services/ocr2/plugins/functions/plugin.go
@@ -13,7 +13,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/functions/plugin_test.go b/core/services/ocr2/plugins/functions/plugin_test.go
index 2e35672e92..eea751789a 100644
--- a/core/services/ocr2/plugins/functions/plugin_test.go
+++ b/core/services/ocr2/plugins/functions/plugin_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector"
hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
diff --git a/core/services/ocr2/plugins/mercury/integration_test.go b/core/services/ocr2/plugins/mercury/integration_test.go
index e7e059289a..ae2b4ca974 100644
--- a/core/services/ocr2/plugins/mercury/integration_test.go
+++ b/core/services/ocr2/plugins/mercury/integration_test.go
@@ -39,8 +39,8 @@ import (
relaycodecv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
relaycodecv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
token "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index 9a1e99610c..0df774d5df 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -21,7 +21,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
index 562f972bc4..ee8b7cd6e9 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
@@ -33,7 +33,7 @@ import (
"github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
automationForwarderLogic "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_forwarder_logic"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/basic_upkeep_contract"
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
index f50321631c..569dc20753 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
@@ -34,7 +34,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/umbracle/ethgo/abi"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "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/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
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 0dbb6a5915..57d13a69ec 100644
--- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
@@ -31,7 +31,7 @@ import (
"github.com/smartcontractkit/ocr2vrf/ocr2vrf"
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
diff --git a/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go b/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go
index 43262d6ad5..c0e969a287 100644
--- a/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go
+++ b/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go
@@ -6,7 +6,7 @@ import (
"github.com/smartcontractkit/ocr2vrf/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
)
diff --git a/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_test.go b/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_test.go
index a33c146564..ec8b085dea 100644
--- a/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
)
func Test_ReasonableGasPrice(t *testing.T) {
diff --git a/core/services/ocrcommon/block_translator.go b/core/services/ocrcommon/block_translator.go
index 48b9641699..dcac83fd2b 100644
--- a/core/services/ocrcommon/block_translator.go
+++ b/core/services/ocrcommon/block_translator.go
@@ -4,9 +4,9 @@ import (
"context"
"math/big"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
- "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/services/ocrcommon/config.go b/core/services/ocrcommon/config.go
index a61a47519c..2fcc877610 100644
--- a/core/services/ocrcommon/config.go
+++ b/core/services/ocrcommon/config.go
@@ -5,7 +5,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
- "github.com/smartcontractkit/chainlink/v2/core/config"
+ "github.com/smartcontractkit/chainlink/v2/common/config"
)
type Config interface {
diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go
index 40542c2631..3aea503ae6 100644
--- a/core/services/relay/evm/mercury/v1/data_source_test.go
+++ b/core/services/relay/evm/mercury/v1/data_source_test.go
@@ -18,7 +18,7 @@ import (
relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/transmission/integration_test.go b/core/services/transmission/integration_test.go
index 0484b1d8cd..58521dcdf8 100644
--- a/core/services/transmission/integration_test.go
+++ b/core/services/transmission/integration_test.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08"
diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go
index e976d01b99..3b91f783b4 100644
--- a/core/services/vrf/delegate.go
+++ b/core/services/vrf/delegate.go
@@ -12,8 +12,8 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2"
diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go
index 389e1159be..3d544027d4 100644
--- a/core/services/vrf/delegate_test.go
+++ b/core/services/vrf/delegate_test.go
@@ -8,9 +8,9 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
diff --git a/core/services/vrf/mocks/fee_config.go b/core/services/vrf/mocks/fee_config.go
index 55a6360c33..067ce7e445 100644
--- a/core/services/vrf/mocks/fee_config.go
+++ b/core/services/vrf/mocks/fee_config.go
@@ -4,7 +4,7 @@ package mocks
import (
common "github.com/ethereum/go-ethereum/common"
- assets "github.com/smartcontractkit/chainlink/v2/core/assets"
+ assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
config "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
diff --git a/core/services/vrf/proof/proof_response_test.go b/core/services/vrf/proof/proof_response_test.go
index 24df77d4b3..c547be2be2 100644
--- a/core/services/vrf/proof/proof_response_test.go
+++ b/core/services/vrf/proof/proof_response_test.go
@@ -16,7 +16,7 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
)
diff --git a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go
index f0c398f8cf..a8e662c931 100644
--- a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go
+++ b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface_test.go b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface_test.go
index 9fab3737ae..2601f800e9 100644
--- a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface_test.go
+++ b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface_test.go
@@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/solidity_cross_tests"
)
@@ -18,14 +17,14 @@ var (
jobID = common.BytesToHash([]byte("1234567890abcdef1234567890abcdef"))
seed = big.NewInt(1)
sender = common.HexToAddress("0xecfcab0a285d3380e488a39b4bb21e777f8a4eac")
- fee = assets.NewLinkFromJuels(100)
+ fee = big.NewInt(100)
requestID = common.HexToHash("0xcafe")
raw = solidity_cross_tests.RawRandomnessRequestLog{
KeyHash: keyHash,
Seed: seed,
JobID: jobID,
Sender: sender,
- Fee: (*big.Int)(fee),
+ Fee: fee,
RequestID: requestID,
Raw: types.Log{
// A raw, on-the-wire RandomnessRequestLog is the concat of fields as uint256's
@@ -33,7 +32,7 @@ var (
keyHash.Bytes(),
common.BigToHash(seed).Bytes()...),
sender.Hash().Bytes()...),
- fee.ToHash().Bytes()...),
+ common.BigToHash(fee).Bytes()...),
requestID.Bytes()...),
Topics: []common.Hash{{}, jobID},
},
diff --git a/core/services/vrf/solidity_cross_tests/vrf_hash_to_curve_cost_test.go b/core/services/vrf/solidity_cross_tests/vrf_hash_to_curve_cost_test.go
index 38675e2651..29d1db437d 100644
--- a/core/services/vrf/solidity_cross_tests/vrf_hash_to_curve_cost_test.go
+++ b/core/services/vrf/solidity_cross_tests/vrf_hash_to_curve_cost_test.go
@@ -11,7 +11,7 @@ import (
"github.com/ethereum/go-ethereum/eth/ethconfig"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey"
"github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1"
diff --git a/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go
index c2896d4231..06875edd74 100644
--- a/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go
+++ b/core/services/vrf/solidity_cross_tests/vrf_solidity_crosscheck_test.go
@@ -19,7 +19,7 @@ import (
"github.com/stretchr/testify/require"
"go.dedis.ch/kyber/v3"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey"
"github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1"
diff --git a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go
index 695a9dfd2f..d1b21b5864 100644
--- a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go
+++ b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey"
"github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1"
diff --git a/core/services/vrf/v2/bhs_feeder_test.go b/core/services/vrf/v2/bhs_feeder_test.go
index 219fe1c8fd..f388f80f56 100644
--- a/core/services/vrf/v2/bhs_feeder_test.go
+++ b/core/services/vrf/v2/bhs_feeder_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight"
diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go
index a086cbbb09..a573737191 100644
--- a/core/services/vrf/v2/integration_helpers_test.go
+++ b/core/services/vrf/v2/integration_helpers_test.go
@@ -17,7 +17,7 @@ import (
"github.com/stretchr/testify/require"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go
index 75026423f4..e45e650dc8 100644
--- a/core/services/vrf/v2/integration_v2_plus_test.go
+++ b/core/services/vrf/v2/integration_v2_plus_test.go
@@ -16,7 +16,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store"
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index 1f607da2f2..df886924aa 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -30,10 +30,11 @@ import (
"github.com/jmoiron/sqlx"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
@@ -1461,7 +1462,7 @@ func simulatedOverrides(t *testing.T, defaultGasPrice *assets.Wei, ks ...toml.Ke
c.EVM[0].FinalityDepth = ptr[uint32](15)
c.EVM[0].MinIncomingConfirmations = ptr[uint32](1)
- c.EVM[0].MinContractPayment = assets.NewLinkFromJuels(100)
+ c.EVM[0].MinContractPayment = relayassets.NewLinkFromJuels(100)
c.EVM[0].KeySpecific = ks
}
}
diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go
index 17cb9ec96e..3480f63f09 100644
--- a/core/services/vrf/v2/listener_v2.go
+++ b/core/services/vrf/v2/listener_v2.go
@@ -28,8 +28,8 @@ import (
"github.com/smartcontractkit/chainlink-relay/pkg/services"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/services/vrf/v2/listener_v2_helpers_test.go b/core/services/vrf/v2/listener_v2_helpers_test.go
index fc34a115b1..401a5bcc57 100644
--- a/core/services/vrf/v2/listener_v2_helpers_test.go
+++ b/core/services/vrf/v2/listener_v2_helpers_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
v2 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
diff --git a/core/services/vrf/vrfcommon/types.go b/core/services/vrf/vrfcommon/types.go
index 03de4eb562..175b362b5a 100644
--- a/core/services/vrf/vrfcommon/types.go
+++ b/core/services/vrf/vrfcommon/types.go
@@ -5,7 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
)
diff --git a/core/services/vrf/vrfcommon/validate.go b/core/services/vrf/vrfcommon/validate.go
index d417336562..07e8676ddb 100644
--- a/core/services/vrf/vrfcommon/validate.go
+++ b/core/services/vrf/vrfcommon/validate.go
@@ -9,7 +9,7 @@ import (
"github.com/pelletier/go-toml"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1"
diff --git a/core/services/vrf/vrfcommon/validate_test.go b/core/services/vrf/vrfcommon/validate_test.go
index 03d544f818..efb1f22216 100644
--- a/core/services/vrf/vrfcommon/validate_test.go
+++ b/core/services/vrf/vrfcommon/validate_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
)
diff --git a/core/services/vrf/vrftesthelpers/helpers.go b/core/services/vrf/vrftesthelpers/helpers.go
index f36fb1ea02..2f269fbff0 100644
--- a/core/services/vrf/vrftesthelpers/helpers.go
+++ b/core/services/vrf/vrftesthelpers/helpers.go
@@ -17,7 +17,7 @@ import (
"github.com/shopspring/decimal"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_consumer_interface"
diff --git a/core/store/models/common.go b/core/store/models/common.go
index fc7f776204..10f391861e 100644
--- a/core/store/models/common.go
+++ b/core/store/models/common.go
@@ -17,7 +17,7 @@ import (
"github.com/tidwall/gjson"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go
index beda735456..0155dc0a53 100644
--- a/core/testdata/testspecs/v2_specs.go
+++ b/core/testdata/testspecs/v2_specs.go
@@ -8,7 +8,7 @@ import (
"github.com/google/uuid"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/utils/big.go b/core/utils/big.go
index 6bdb95c121..f0f9a2d96d 100644
--- a/core/utils/big.go
+++ b/core/utils/big.go
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/smartcontractkit/chainlink-relay/pkg/utils/bytes"
bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math"
)
@@ -80,7 +81,7 @@ func (b Big) MarshalJSON() ([]byte, error) {
// UnmarshalText implements encoding.TextUnmarshaler.
func (b *Big) UnmarshalText(input []byte) error {
- input = RemoveQuotes(input)
+ input = bytes.TrimQuotes(input)
str := string(input)
if HasHexPrefix(str) {
decoded, err := hexutil.DecodeBig(str)
diff --git a/core/utils/utils.go b/core/utils/utils.go
index e5541ecf55..6ea7164df1 100644
--- a/core/utils/utils.go
+++ b/core/utils/utils.go
@@ -305,22 +305,6 @@ func Sha256(in string) (string, error) {
return hex.EncodeToString(hasher.Sum(nil)), nil
}
-// IsQuoted checks if the first and last characters are either " or '.
-func IsQuoted(input []byte) bool {
- return len(input) >= 2 &&
- ((input[0] == '"' && input[len(input)-1] == '"') ||
- (input[0] == '\'' && input[len(input)-1] == '\''))
-}
-
-// RemoveQuotes removes the first and last character if they are both either
-// " or ', otherwise it is a noop.
-func RemoveQuotes(input []byte) []byte {
- if IsQuoted(input) {
- return input[1 : len(input)-1]
- }
- return input
-}
-
// EIP55CapitalizedAddress returns true iff possibleAddressString has the correct
// capitalization for an Ethereum address, per EIP 55
func EIP55CapitalizedAddress(possibleAddressString string) bool {
diff --git a/core/web/bridge_types_controller.go b/core/web/bridge_types_controller.go
index eca99f1a20..57a79e2b61 100644
--- a/core/web/bridge_types_controller.go
+++ b/core/web/bridge_types_controller.go
@@ -8,7 +8,7 @@ import (
"github.com/jackc/pgconn"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/web/bridge_types_controller_test.go b/core/web/bridge_types_controller_test.go
index 6459cad054..a65362ba9a 100644
--- a/core/web/bridge_types_controller_test.go
+++ b/core/web/bridge_types_controller_test.go
@@ -6,7 +6,7 @@ import (
"net/http"
"testing"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/web/eth_keys_controller.go b/core/web/eth_keys_controller.go
index 28afe8c43b..6e2a3b2efc 100644
--- a/core/web/eth_keys_controller.go
+++ b/core/web/eth_keys_controller.go
@@ -9,8 +9,9 @@ import (
"strconv"
"strings"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
@@ -364,13 +365,13 @@ func (ekc *ETHKeysController) getEthBalance(ctx context.Context, state ethkey.St
}
-func (ekc *ETHKeysController) setLinkBalance(bal *assets.Link) presenters.NewETHKeyOption {
+func (ekc *ETHKeysController) setLinkBalance(bal *relayassets.Link) presenters.NewETHKeyOption {
return presenters.SetETHKeyLinkBalance(bal)
}
// queries the EthClient for the LINK balance at the address associated with state
-func (ekc *ETHKeysController) getLinkBalance(ctx context.Context, state ethkey.State) *assets.Link {
- var bal *assets.Link
+func (ekc *ETHKeysController) getLinkBalance(ctx context.Context, state ethkey.State) *relayassets.Link {
+ var bal *relayassets.Link
chainID := state.EVMChainID.ToInt()
chain, err := ekc.app.GetRelayers().LegacyEVMChains().Get(chainID.String())
if err != nil {
diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go
index e3a39d541a..8941c2d2fd 100644
--- a/core/web/eth_keys_controller_test.go
+++ b/core/web/eth_keys_controller_test.go
@@ -8,9 +8,9 @@ import (
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go
index 9d8336325e..9135be432d 100644
--- a/core/web/evm_transactions_controller_test.go
+++ b/core/web/evm_transactions_controller_test.go
@@ -6,7 +6,7 @@ import (
"testing"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/web/evm_transfer_controller.go b/core/web/evm_transfer_controller.go
index f5973a20f2..7f09bc9fdc 100644
--- a/core/web/evm_transfer_controller.go
+++ b/core/web/evm_transfer_controller.go
@@ -11,8 +11,8 @@ import (
"github.com/pkg/errors"
commontxmgr "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go
index 14259637b4..c41219e189 100644
--- a/core/web/evm_transfer_controller_test.go
+++ b/core/web/evm_transfer_controller_test.go
@@ -10,7 +10,7 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/web/presenters/bridges.go b/core/web/presenters/bridges.go
index 3317895e16..440e444c61 100644
--- a/core/web/presenters/bridges.go
+++ b/core/web/presenters/bridges.go
@@ -3,7 +3,7 @@ package presenters
import (
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
)
diff --git a/core/web/presenters/bridges_test.go b/core/web/presenters/bridges_test.go
index b9fefd022d..f6ce3af756 100644
--- a/core/web/presenters/bridges_test.go
+++ b/core/web/presenters/bridges_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/core/web/presenters/eth_key.go b/core/web/presenters/eth_key.go
index 167679513e..9265442761 100644
--- a/core/web/presenters/eth_key.go
+++ b/core/web/presenters/eth_key.go
@@ -3,7 +3,8 @@ package presenters
import (
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -12,14 +13,14 @@ import (
// representation of the address plus its ETH & LINK balances
type ETHKeyResource struct {
JAID
- EVMChainID utils.Big `json:"evmChainID"`
- Address string `json:"address"`
- EthBalance *assets.Eth `json:"ethBalance"`
- LinkBalance *assets.Link `json:"linkBalance"`
- Disabled bool `json:"disabled"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- MaxGasPriceWei *utils.Big `json:"maxGasPriceWei"`
+ EVMChainID utils.Big `json:"evmChainID"`
+ Address string `json:"address"`
+ EthBalance *assets.Eth `json:"ethBalance"`
+ LinkBalance *relayassets.Link `json:"linkBalance"`
+ Disabled bool `json:"disabled"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ MaxGasPriceWei *utils.Big `json:"maxGasPriceWei"`
}
// GetName implements the api2go EntityNamer interface
@@ -62,7 +63,7 @@ func SetETHKeyEthBalance(ethBalance *assets.Eth) NewETHKeyOption {
}
}
-func SetETHKeyLinkBalance(linkBalance *assets.Link) NewETHKeyOption {
+func SetETHKeyLinkBalance(linkBalance *relayassets.Link) NewETHKeyOption {
return func(r *ETHKeyResource) {
r.LinkBalance = linkBalance
}
diff --git a/core/web/presenters/eth_key_test.go b/core/web/presenters/eth_key_test.go
index 7afb55068f..0e68fbc90c 100644
--- a/core/web/presenters/eth_key_test.go
+++ b/core/web/presenters/eth_key_test.go
@@ -5,7 +5,8 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -39,12 +40,12 @@ func TestETHKeyResource(t *testing.T) {
r := NewETHKeyResource(key, state,
SetETHKeyEthBalance(assets.NewEth(1)),
- SetETHKeyLinkBalance(assets.NewLinkFromJuels(1)),
+ SetETHKeyLinkBalance(relayassets.NewLinkFromJuels(1)),
SetETHKeyMaxGasPriceWei(utils.NewBigI(12345)),
)
assert.Equal(t, assets.NewEth(1), r.EthBalance)
- assert.Equal(t, assets.NewLinkFromJuels(1), r.LinkBalance)
+ assert.Equal(t, relayassets.NewLinkFromJuels(1), r.LinkBalance)
assert.Equal(t, utils.NewBigI(12345), r.MaxGasPriceWei)
b, err := jsonapi.Marshal(r)
diff --git a/core/web/presenters/eth_tx.go b/core/web/presenters/eth_tx.go
index 8878733d70..2c2b5b90ff 100644
--- a/core/web/presenters/eth_tx.go
+++ b/core/web/presenters/eth_tx.go
@@ -6,7 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/web/presenters/eth_tx_test.go b/core/web/presenters/eth_tx_test.go
index 10f4ceab00..2ed8e23c76 100644
--- a/core/web/presenters/eth_tx_test.go
+++ b/core/web/presenters/eth_tx_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go
index 06b9950755..d9ec1844ae 100644
--- a/core/web/presenters/job.go
+++ b/core/web/presenters/job.go
@@ -7,7 +7,8 @@ import (
"github.com/lib/pq"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
@@ -43,7 +44,7 @@ const (
type DirectRequestSpec struct {
ContractAddress ethkey.EIP55Address `json:"contractAddress"`
MinIncomingConfirmations clnull.Uint32 `json:"minIncomingConfirmations"`
- MinContractPayment *assets.Link `json:"minContractPaymentLinkJuels"`
+ MinContractPayment *relayassets.Link `json:"minContractPaymentLinkJuels"`
Requesters models.AddressCollection `json:"requesters"`
Initiator string `json:"initiator"`
CreatedAt time.Time `json:"createdAt"`
@@ -80,7 +81,7 @@ type FluxMonitorSpec struct {
DrumbeatEnabled bool `json:"drumbeatEnabled"`
DrumbeatSchedule *string `json:"drumbeatSchedule"`
DrumbeatRandomDelay *string `json:"drumbeatRandomDelay"`
- MinPayment *assets.Link `json:"minPayment"`
+ MinPayment *relayassets.Link `json:"minPayment"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
EVMChainID *utils.Big `json:"evmChainID"`
diff --git a/core/web/presenters/job_test.go b/core/web/presenters/job_test.go
index bb79c8e953..46c765a38b 100644
--- a/core/web/presenters/job_test.go
+++ b/core/web/presenters/job_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/web/resolver/bridge_test.go b/core/web/resolver/bridge_test.go
index b12186e112..e708ac92a4 100644
--- a/core/web/resolver/bridge_test.go
+++ b/core/web/resolver/bridge_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/core/web/resolver/eth_key_test.go b/core/web/resolver/eth_key_test.go
index a7f8ce56d9..f8f417ca44 100644
--- a/core/web/resolver/eth_key_test.go
+++ b/core/web/resolver/eth_key_test.go
@@ -9,8 +9,9 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/mock"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
mocks2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
@@ -95,7 +96,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil)
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
- f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(assets.NewLinkFromJuels(12), nil)
+ f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(relayassets.NewLinkFromJuels(12), nil)
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
f.Mocks.balM.On("GetEthBalance", address).Return(assets.NewEth(1))
f.Mocks.chain.On("BalanceMonitor").Return(f.Mocks.balM)
@@ -300,7 +301,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
- f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(assets.NewLinkFromJuels(12), gError)
+ f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(relayassets.NewLinkFromJuels(12), gError)
f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, nil)
f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
@@ -353,7 +354,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil)
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
- f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(assets.NewLinkFromJuels(12), nil)
+ f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(relayassets.NewLinkFromJuels(12), nil)
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
f.Mocks.chain.On("BalanceMonitor").Return(nil)
f.Mocks.chain.On("Config").Return(f.Mocks.scfg)
diff --git a/core/web/resolver/eth_transaction.go b/core/web/resolver/eth_transaction.go
index 31a96727a9..1292b6bc10 100644
--- a/core/web/resolver/eth_transaction.go
+++ b/core/web/resolver/eth_transaction.go
@@ -6,7 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/graph-gophers/graphql-go"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/utils/stringutils"
"github.com/smartcontractkit/chainlink/v2/core/web/loader"
diff --git a/core/web/resolver/eth_transaction_test.go b/core/web/resolver/eth_transaction_test.go
index 8a1685e4f7..a719c838e8 100644
--- a/core/web/resolver/eth_transaction_test.go
+++ b/core/web/resolver/eth_transaction_test.go
@@ -10,7 +10,7 @@ import (
gqlerrors "github.com/graph-gophers/graphql-go/errors"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/web/resolver/helpers.go b/core/web/resolver/helpers.go
index 5c855a1c16..2dc865674e 100644
--- a/core/web/resolver/helpers.go
+++ b/core/web/resolver/helpers.go
@@ -8,7 +8,7 @@ import (
"github.com/graph-gophers/graphql-go"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/utils/stringutils"
)
diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go
index f9eee0734a..52f914e0a8 100644
--- a/core/web/resolver/mutation.go
+++ b/core/web/resolver/mutation.go
@@ -13,7 +13,7 @@ import (
"go.uber.org/zap/zapcore"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go
index 8e4095e171..fd369088bb 100644
--- a/core/web/resolver/spec_test.go
+++ b/core/web/resolver/spec_test.go
@@ -9,9 +9,10 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
@@ -96,7 +97,7 @@ func TestResolver_DirectRequestSpec(t *testing.T) {
CreatedAt: f.Timestamp(),
EVMChainID: utils.NewBigI(42),
MinIncomingConfirmations: clnull.NewUint32(1, true),
- MinContractPayment: assets.NewLinkFromJuels(1000),
+ MinContractPayment: relayassets.NewLinkFromJuels(1000),
Requesters: models.AddressCollection{requesterAddress},
},
}, nil)
@@ -163,7 +164,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) {
DrumbeatEnabled: false,
IdleTimerDisabled: false,
IdleTimerPeriod: time.Duration(1 * time.Hour),
- MinPayment: assets.NewLinkFromJuels(1000),
+ MinPayment: relayassets.NewLinkFromJuels(1000),
PollTimerDisabled: false,
PollTimerPeriod: time.Duration(1 * time.Minute),
},
@@ -232,7 +233,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) {
DrumbeatSchedule: "CRON_TZ=UTC 0 0 1 1 *",
IdleTimerDisabled: true,
IdleTimerPeriod: time.Duration(1 * time.Hour),
- MinPayment: assets.NewLinkFromJuels(1000),
+ MinPayment: relayassets.NewLinkFromJuels(1000),
PollTimerDisabled: true,
PollTimerPeriod: time.Duration(1 * time.Minute),
},
diff --git a/core/web/solana_chains_controller_test.go b/core/web/solana_chains_controller_test.go
index 724d5cd2c3..c4023f166b 100644
--- a/core/web/solana_chains_controller_test.go
+++ b/core/web/solana_chains_controller_test.go
@@ -11,8 +11,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
"github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
@@ -84,7 +84,7 @@ Nodes = []
ChainID: ptr(validId),
Chain: config.Chain{
SkipPreflight: ptr(false),
- TxTimeout: utils.MustNewDuration(time.Hour),
+ TxTimeout: relaycfg.MustNewDuration(time.Hour),
},
})
@@ -114,7 +114,7 @@ func Test_SolanaChainsController_Index(t *testing.T) {
chainA := &solana.TOMLConfig{
ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))),
Chain: config.Chain{
- TxTimeout: utils.MustNewDuration(time.Hour),
+ TxTimeout: relaycfg.MustNewDuration(time.Hour),
},
}
chainB := &solana.TOMLConfig{
diff --git a/go.mod b/go.mod
index 0a85fe7f48..40803d504c 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
diff --git a/go.sum b/go.sum
index 7fe91a6b12..52975e722a 100644
--- a/go.sum
+++ b/go.sum
@@ -1465,8 +1465,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a h1:G/pD8uI1PULRJU8Y3eLLzjqQBp9ruG9hj+wWxtyrgTo=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd h1:PRVJxNK67pQWufXuB1cxckH/xZkcQFDy8KjN9ZYqong=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd/go.mod h1:rOayi690YxLlkQy959PD8INhOAIAUi9LoN0G+J/CEf4=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index 28fb2635ff..254f2ca6ce 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -9,7 +9,8 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/utils"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer"
"github.com/ethereum/go-ethereum/common"
@@ -868,7 +869,7 @@ func retreiveLoadTestMetrics(
func LogSubDetails(l zerolog.Logger, subscription vrf_coordinator_v2_5.GetSubscription, subID *big.Int, coordinator contracts.VRFCoordinatorV2_5) {
l.Debug().
Str("Coordinator", coordinator.Address()).
- Str("Link Balance", (*assets.Link)(subscription.Balance).Link()).
+ Str("Link Balance", (*relayassets.Link)(subscription.Balance).Link()).
Str("Native Token Balance", assets.FormatWei(subscription.NativeBalance)).
Str("Subscription ID", subID.String()).
Str("Subscription Owner", subscription.Owner.String()).
@@ -971,11 +972,11 @@ func LogFulfillmentDetailsLinkBilling(
randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled,
) {
l.Debug().
- Str("Consumer Balance Before Request (Link)", (*assets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()).
- Str("Consumer Balance After Request (Link)", (*assets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()).
+ Str("Consumer Balance Before Request (Link)", (*relayassets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()).
+ Str("Consumer Balance After Request (Link)", (*relayassets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()).
Bool("Fulfilment Status", consumerStatus.Fulfilled).
- Str("Paid by Consumer Contract (Link)", (*assets.Link)(consumerStatus.Paid).Link()).
- Str("Paid by Coordinator Sub (Link)", (*assets.Link)(randomWordsFulfilledEvent.Payment).Link()).
+ Str("Paid by Consumer Contract (Link)", (*relayassets.Link)(consumerStatus.Paid).Link()).
+ Str("Paid by Coordinator Sub (Link)", (*relayassets.Link)(randomWordsFulfilledEvent.Payment).Link()).
Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()).
Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()).
Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()).
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index a943e1c41a..a450dd235a 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,6 +22,7 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
+ github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd
github.com/smartcontractkit/chainlink-testing-framework v1.18.6
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
@@ -387,7 +388,6 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 5719c36b5a..f882a7bb57 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2369,8 +2369,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a h1:G/pD8uI1PULRJU8Y3eLLzjqQBp9ruG9hj+wWxtyrgTo=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231113174149-046d4ddaca1a/go.mod h1:M9U1JV7IQi8Sfj4JR1qSi1tIh6omgW78W/8SHN/8BUQ=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd h1:PRVJxNK67pQWufXuB1cxckH/xZkcQFDy8KjN9ZYqong=
+github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd/go.mod h1:rOayi690YxLlkQy959PD8INhOAIAUi9LoN0G+J/CEf4=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go
index 37047cdb66..7ddddafdd5 100644
--- a/integration-tests/types/config/node/core.go
+++ b/integration-tests/types/config/node/core.go
@@ -11,8 +11,9 @@ import (
"github.com/segmentio/ksuid"
+ relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
- "github.com/smartcontractkit/chainlink/v2/core/assets"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
@@ -167,7 +168,7 @@ func SetChainConfig(
chainConfig = evmcfg.Chain{
AutoCreateKey: utils2.Ptr(true),
FinalityDepth: utils2.Ptr[uint32](1),
- MinContractPayment: assets.NewLinkFromJuels(0),
+ MinContractPayment: relayassets.NewLinkFromJuels(0),
}
}
cfg.EVM = evmcfg.EVMConfigs{
@@ -193,7 +194,7 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork) NodeConfigOpt {
Chain: evmcfg.Chain{
AutoCreateKey: utils2.Ptr(true),
FinalityDepth: utils2.Ptr[uint32](50),
- MinContractPayment: assets.NewLinkFromJuels(0),
+ MinContractPayment: relayassets.NewLinkFromJuels(0),
LogPollInterval: models.MustNewDuration(1 * time.Second),
HeadTracker: evmcfg.HeadTracker{
HistoryDepth: utils2.Ptr(uint32(100)),
diff --git a/tools/flakeytests/runner_test.go b/tools/flakeytests/runner_test.go
index c4509ff2cc..31f300dcbe 100644
--- a/tools/flakeytests/runner_test.go
+++ b/tools/flakeytests/runner_test.go
@@ -25,7 +25,7 @@ func newMockReporter() *mockReporter {
}
func TestParser(t *testing.T) {
- output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
+ output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
`
r := strings.NewReader(output)
@@ -33,14 +33,14 @@ func TestParser(t *testing.T) {
require.NoError(t, err)
assert.Len(t, ts, 1)
- assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/assets"], 1)
- assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"], 1)
+ assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"], 1)
+ assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"], 1)
}
func TestParser_SkipsNonJSON(t *testing.T) {
output := `Failed tests and panics:
-------
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
`
r := strings.NewReader(output)
@@ -48,13 +48,13 @@ func TestParser_SkipsNonJSON(t *testing.T) {
require.NoError(t, err)
assert.Len(t, ts, 1)
- assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/assets"], 1)
- assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"], 1)
+ assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"], 1)
+ assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"], 1)
}
func TestParser_PanicDueToLogging(t *testing.T) {
output := `
-{"Time":"2023-09-07T16:01:40.649849+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_LinkScanValue","Output":"panic: foo\n"}
+{"Time":"2023-09-07T16:01:40.649849+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_LinkScanValue","Output":"panic: foo\n"}
`
r := strings.NewReader(output)
@@ -62,24 +62,24 @@ func TestParser_PanicDueToLogging(t *testing.T) {
require.NoError(t, err)
assert.Len(t, ts, 1)
- assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/assets"], 1)
- assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestAssets_LinkScanValue"], 1)
+ assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"], 1)
+ assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestAssets_LinkScanValue"], 1)
}
func TestParser_SuccessfulOutput(t *testing.T) {
output := `
-{"Time":"2023-09-07T16:22:52.556853+01:00","Action":"start","Package":"github.com/smartcontractkit/chainlink/v2/core/assets"}
-{"Time":"2023-09-07T16:22:52.762353+01:00","Action":"run","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString"}
-{"Time":"2023-09-07T16:22:52.762456+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString","Output":"=== RUN TestAssets_NewLinkAndString\n"}
-{"Time":"2023-09-07T16:22:52.76249+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString","Output":"=== PAUSE TestAssets_NewLinkAndString\n"}
-{"Time":"2023-09-07T16:22:52.7625+01:00","Action":"pause","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString"}
-{"Time":"2023-09-07T16:22:52.762511+01:00","Action":"cont","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString"}
-{"Time":"2023-09-07T16:22:52.762528+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString","Output":"=== CONT TestAssets_NewLinkAndString\n"}
-{"Time":"2023-09-07T16:22:52.762546+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString","Output":"--- PASS: TestAssets_NewLinkAndString (0.00s)\n"}
-{"Time":"2023-09-07T16:22:52.762557+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestAssets_NewLinkAndString","Elapsed":0}
-{"Time":"2023-09-07T16:22:52.762566+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Output":"PASS\n"}
-{"Time":"2023-09-07T16:22:52.762955+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Output":"ok \tgithub.com/smartcontractkit/chainlink/v2/core/assets\t0.206s\n"}
-{"Time":"2023-09-07T16:22:52.765598+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Elapsed":0.209}
+{"Time":"2023-09-07T16:22:52.556853+01:00","Action":"start","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"}
+{"Time":"2023-09-07T16:22:52.762353+01:00","Action":"run","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString"}
+{"Time":"2023-09-07T16:22:52.762456+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString","Output":"=== RUN TestAssets_NewLinkAndString\n"}
+{"Time":"2023-09-07T16:22:52.76249+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString","Output":"=== PAUSE TestAssets_NewLinkAndString\n"}
+{"Time":"2023-09-07T16:22:52.7625+01:00","Action":"pause","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString"}
+{"Time":"2023-09-07T16:22:52.762511+01:00","Action":"cont","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString"}
+{"Time":"2023-09-07T16:22:52.762528+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString","Output":"=== CONT TestAssets_NewLinkAndString\n"}
+{"Time":"2023-09-07T16:22:52.762546+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString","Output":"--- PASS: TestAssets_NewLinkAndString (0.00s)\n"}
+{"Time":"2023-09-07T16:22:52.762557+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestAssets_NewLinkAndString","Elapsed":0}
+{"Time":"2023-09-07T16:22:52.762566+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Output":"PASS\n"}
+{"Time":"2023-09-07T16:22:52.762955+01:00","Action":"output","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Output":"ok \tgithub.com/smartcontractkit/chainlink/v2/core/assets\t0.206s\n"}
+{"Time":"2023-09-07T16:22:52.765598+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Elapsed":0.209}
`
r := strings.NewReader(output)
@@ -95,9 +95,9 @@ func (t testAdapter) test(pkg string, tests []string, out io.Writer) error {
}
func TestRunner_WithFlake(t *testing.T) {
- initialOutput := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`
+ initialOutput := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`
outputs := []string{
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
``,
}
m := newMockReporter()
@@ -120,18 +120,18 @@ func TestRunner_WithFlake(t *testing.T) {
err := r.Run()
require.NoError(t, err)
assert.Len(t, m.entries, 1)
- _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"]
+ _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"]
assert.True(t, ok)
}
func TestRunner_WithFailedPackage(t *testing.T) {
initialOutput := `
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Elapsed":0}
`
outputs := []string{`
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Elapsed":0}
`,
``,
}
@@ -155,16 +155,16 @@ func TestRunner_WithFailedPackage(t *testing.T) {
err := r.Run()
require.NoError(t, err)
assert.Len(t, m.entries, 1)
- _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"]
+ _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"]
assert.True(t, ok)
}
func TestRunner_AllFailures(t *testing.T) {
- output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`
+ output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`
rerunOutput := `
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
`
m := newMockReporter()
r := &Runner{
@@ -184,11 +184,11 @@ func TestRunner_AllFailures(t *testing.T) {
}
func TestRunner_RerunSuccessful(t *testing.T) {
- output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`
+ output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`
rerunOutputs := []string{
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
}
m := newMockReporter()
i := 0
@@ -206,7 +206,7 @@ func TestRunner_RerunSuccessful(t *testing.T) {
err := r.Run()
require.NoError(t, err)
- _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"]
+ _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"]
assert.True(t, ok)
}
@@ -233,11 +233,11 @@ func TestRunner_RootLevelTest(t *testing.T) {
}
func TestRunner_RerunFailsWithNonzeroExitCode(t *testing.T) {
- output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`
+ output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`
rerunOutputs := []string{
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
}
m := newMockReporter()
i := 0
@@ -255,14 +255,14 @@ func TestRunner_RerunFailsWithNonzeroExitCode(t *testing.T) {
err := r.Run()
require.NoError(t, err)
- _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"]
+ _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"]
assert.True(t, ok)
}
func TestRunner_RerunWithNonZeroExitCodeDoesntStopCommand(t *testing.T) {
outputs := []io.Reader{
strings.NewReader(`
-{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}
+{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}
`),
strings.NewReader(`
{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2","Test":"TestMaybeReservedLinkV2","Elapsed":0}
@@ -270,8 +270,8 @@ func TestRunner_RerunWithNonZeroExitCodeDoesntStopCommand(t *testing.T) {
}
rerunOutputs := []string{
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
- `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
+ `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"pass","Package":"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets","Test":"TestLink","Elapsed":0}`,
`{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2","Test":"TestMaybeReservedLinkV2","Elapsed":0}`,
`{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2","Test":"TestMaybeReservedLinkV2","Elapsed":0}`,
}
@@ -295,7 +295,7 @@ func TestRunner_RerunWithNonZeroExitCodeDoesntStopCommand(t *testing.T) {
calls := index
assert.Equal(t, 4, calls)
- _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/assets"]["TestLink"]
+ _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"]
assert.True(t, ok)
}
From 6fd7be8e9e565ee3358d125f88c6f67017248e57 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Thu, 16 Nov 2023 10:35:07 -0500
Subject: [PATCH 161/327] [TT-688] Batch Keeper Benchmark Read Requests
(#11294)
* Batch Keeper Benchmark Read Requests
* Actually add number
---
.../testsetups/keeper_benchmark.go | 60 +++++++++++++------
1 file changed, 41 insertions(+), 19 deletions(-)
diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go
index bb6c582c13..d9b389a965 100644
--- a/integration-tests/testsetups/keeper_benchmark.go
+++ b/integration-tests/testsetups/keeper_benchmark.go
@@ -293,32 +293,54 @@ func (k *KeeperBenchmarkTest) Run() {
require.NoError(k.t, err, "Error waiting for keeper subscriptions")
// Collect logs for each registry to calculate test metrics
- registryLogs := make([][]types.Log, len(k.keeperRegistries))
+ // This test generates a LOT of logs, and we need to break up our reads, or risk getting rate-limited by the node
+ var (
+ endBlock = big.NewInt(0).Add(k.startingBlock, big.NewInt(u.BlockRange))
+ registryLogs = make([][]types.Log, len(k.keeperRegistries))
+ blockBatchSize int64 = 100
+ )
for rIndex := range k.keeperRegistries {
+ // Variables for the full registry
var (
- logs []types.Log
- timeout = 5 * time.Second
- addr = k.keeperRegistries[rIndex].Address()
- filterQuery = geth.FilterQuery{
+ logs []types.Log
+ timeout = 5 * time.Second
+ addr = k.keeperRegistries[rIndex].Address()
+ queryStartBlock = big.NewInt(0).Set(k.startingBlock)
+ )
+
+ // Gather logs from the registry in 100 block chunks to avoid read limits
+ for queryStartBlock.Cmp(endBlock) < 0 {
+ filterQuery := geth.FilterQuery{
Addresses: []common.Address{common.HexToAddress(addr)},
- FromBlock: k.startingBlock,
+ FromBlock: queryStartBlock,
+ ToBlock: big.NewInt(0).Add(queryStartBlock, big.NewInt(blockBatchSize)),
}
+
+ // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats.
err = fmt.Errorf("initial error") // to ensure our for loop runs at least once
- )
- for err != nil { // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats.
- ctx, cancel := context.WithTimeout(utils.TestContext(k.t), timeout)
- logs, err = k.chainClient.FilterLogs(ctx, filterQuery)
- cancel()
- if err != nil {
- k.log.Error().Err(err).
- Interface("Filter Query", filterQuery).
- Str("Timeout", timeout.String()).
- Msg("Error getting logs from chain, trying again")
- } else {
- k.log.Info().Int("Log Count", len(logs)).Str("Registry Address", addr).Msg("Collected logs")
+ for err != nil {
+ ctx, cancel := context.WithTimeout(utils.TestContext(k.t), timeout)
+ logs, err = k.chainClient.FilterLogs(ctx, filterQuery)
+ cancel()
+ if err != nil {
+ k.log.Error().
+ Err(err).
+ Interface("Filter Query", filterQuery).
+ Str("Timeout", timeout.String()).
+ Msg("Error getting logs from chain, trying again")
+ timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute)))
+ continue
+ }
+ k.log.Info().
+ Uint64("From Block", queryStartBlock.Uint64()).
+ Uint64("To Block", filterQuery.ToBlock.Uint64()).
+ Int("Log Count", len(logs)).
+ Str("Registry Address", addr).
+ Msg("Collected logs")
+ queryStartBlock.Add(queryStartBlock, big.NewInt(blockBatchSize))
+ registryLogs[rIndex] = append(registryLogs[rIndex], logs...)
}
}
- registryLogs[rIndex] = logs
}
// Count reverts and stale upkeeps
From 01fbf8e445b2ae4db616d0fc8e10fa4d44895e0b Mon Sep 17 00:00:00 2001
From: amit-momin <108959691+amit-momin@users.noreply.github.com>
Date: Thu, 16 Nov 2023 10:34:08 -0600
Subject: [PATCH 162/327] Update loading next sequence map to avoid startup
failure (#11307)
* Updated loading next sequence map to avoid startup failure
* Moved logic to populate next sequence map during runtime
* Added changelog
* Addressed feedback
* Addressed feedback
---
common/txmgr/broadcaster.go | 77 ++++++----
core/chains/evm/txmgr/broadcaster_test.go | 175 +++++++++++++++-------
docs/CHANGELOG.md | 6 +
3 files changed, 176 insertions(+), 82 deletions(-)
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index 00522abf22..1e3b2fa0a9 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"fmt"
+ "slices"
"sync"
"time"
@@ -228,10 +229,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) star
eb.sequenceLock.Lock()
defer eb.sequenceLock.Unlock()
- eb.nextSequenceMap, err = eb.loadNextSequenceMap(eb.enabledAddresses)
- if err != nil {
- return errors.Wrap(err, "Broadcaster: failed to load next sequence map")
- }
+ eb.nextSequenceMap = eb.loadNextSequenceMap(eb.enabledAddresses)
eb.isStarted = true
return nil
@@ -287,30 +285,38 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Trig
}
// Load the next sequence map using the tx table or on-chain (if not found in tx table)
-func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) loadNextSequenceMap(addresses []ADDR) (map[ADDR]SEQ, error) {
+func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) loadNextSequenceMap(addresses []ADDR) map[ADDR]SEQ {
ctx, cancel := eb.chStop.NewCtx()
defer cancel()
nextSequenceMap := make(map[ADDR]SEQ)
for _, address := range addresses {
- // Get the highest sequence from the tx table
- // Will need to be incremented since this sequence is already used
- seq, err := eb.txStore.FindLatestSequence(ctx, address, eb.chainID)
- if err != nil {
- // Look for nonce on-chain if no tx found for address in TxStore or if error occurred
- // Returns the nonce that should be used for the next transaction so no need to increment
- seq, err = eb.client.PendingSequenceAt(ctx, address)
- if err != nil {
- return nil, errors.New("failed to retrieve next sequence from on-chain causing failure to load next sequence map on broadcaster startup")
- }
-
+ seq, err := eb.getSequenceForAddr(ctx, address)
+ if err == nil {
nextSequenceMap[address] = seq
- } else {
- nextSequenceMap[address] = eb.generateNextSequence(seq)
}
}
- return nextSequenceMap, nil
+ return nextSequenceMap
+}
+
+func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) getSequenceForAddr(ctx context.Context, address ADDR) (seq SEQ, err error) {
+ // Get the highest sequence from the tx table
+ // Will need to be incremented since this sequence is already used
+ seq, err = eb.txStore.FindLatestSequence(ctx, address, eb.chainID)
+ if err == nil {
+ seq = eb.generateNextSequence(seq)
+ return seq, nil
+ }
+ // Look for nonce on-chain if no tx found for address in TxStore or if error occurred
+ // Returns the nonce that should be used for the next transaction so no need to increment
+ seq, err = eb.client.PendingSequenceAt(ctx, address)
+ if err == nil {
+ return seq, nil
+ }
+ eb.logger.Criticalw("failed to retrieve next sequence from on-chain for address: ", "address", address.String())
+ return seq, err
+
}
func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) newSequenceSyncBackoff() backoff.Backoff {
@@ -393,7 +399,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) moni
// syncSequence tries to sync the key sequence, retrying indefinitely until success or stop signal is sent
func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) SyncSequence(ctx context.Context, addr ADDR) {
sequenceSyncRetryBackoff := eb.newSequenceSyncBackoff()
- localSequence, err := eb.GetNextSequence(addr)
+ localSequence, err := eb.GetNextSequence(ctx, addr)
// Address not found in map so skip sync
if err != nil {
eb.logger.Criticalw("Failed to retrieve local next sequence for address", "address", addr.String(), "err", err)
@@ -607,7 +613,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
observeTimeUntilBroadcast(eb.chainID, etx.CreatedAt, time.Now())
// Check if from_address exists in map to ensure it is valid before broadcasting
var sequence SEQ
- sequence, err = eb.GetNextSequence(etx.FromAddress)
+ sequence, err = eb.GetNextSequence(ctx, etx.FromAddress)
if err != nil {
return err, true
}
@@ -665,7 +671,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
// Check if from_address exists in map to ensure it is valid before broadcasting
var sequence SEQ
- sequence, err = eb.GetNextSequence(etx.FromAddress)
+ sequence, err = eb.GetNextSequence(ctx, etx.FromAddress)
if err != nil {
return err, true
}
@@ -702,7 +708,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) next
return nil, errors.Wrap(err, "findNextUnstartedTransactionFromAddress failed")
}
- sequence, err := eb.GetNextSequence(etx.FromAddress)
+ sequence, err := eb.GetNextSequence(ctx, etx.FromAddress)
if err != nil {
return nil, err
}
@@ -792,15 +798,32 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) save
}
// Used to get the next usable sequence for a transaction
-func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetNextSequence(address ADDR) (seq SEQ, err error) {
+func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetNextSequence(ctx context.Context, address ADDR) (seq SEQ, err error) {
eb.sequenceLock.Lock()
defer eb.sequenceLock.Unlock()
// Get next sequence from map
seq, exists := eb.nextSequenceMap[address]
- if !exists {
- return seq, errors.New(fmt.Sprint("address not found in next sequence map: ", address))
+ if exists {
+ return seq, nil
+ }
+
+ eb.logger.Infow("address not found in local next sequence map. Attempting to search and populate sequence.", "address", address.String())
+ // Check if address is in the enabled address list
+ if !slices.Contains(eb.enabledAddresses, address) {
+ return seq, fmt.Errorf("address disabled: %s", address)
}
- return seq, nil
+
+ // Try to retrieve next sequence from tx table or on-chain to load the map
+ // A scenario could exist where loading the map during startup failed (e.g. All configured RPC's are unreachable at start)
+ // The expectation is that the node does not fail startup so sequences need to be loaded during runtime
+ foundSeq, err := eb.getSequenceForAddr(ctx, address)
+ if err != nil {
+ return seq, fmt.Errorf("failed to find next sequence for address: %s", address)
+ }
+
+ // Set sequence in map
+ eb.nextSequenceMap[address] = foundSeq
+ return foundSeq, nil
}
// Used to increment the sequence in the mapping to have the next usable one available for the next transaction
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 48b68f9b55..7967478e62 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -130,6 +130,38 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) {
require.NoError(t, eb.XXXTestCloseInternal())
}
+// Failure to load next sequnce map should not fail Broadcaster startup
+func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) {
+ db := pgtest.NewSqlxDB(t)
+ cfg := configtest.NewTestGeneralConfig(t)
+ txStore := cltest.NewTestTxStore(t, db, cfg.Database())
+ evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth()
+ cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
+ estimator := gasmocks.NewEvmFeeEstimator(t)
+ txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator)
+ ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), errors.New("Getting on-chain nonce failed"))
+ eb := txmgr.NewEvmBroadcaster(
+ txStore,
+ txmgr.NewEvmTxmClient(ethClient),
+ txmgr.NewEvmTxmConfig(evmcfg.EVM()),
+ txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()),
+ evmcfg.EVM().Transactions(),
+ evmcfg.Database().Listener(),
+ ethKeyStore,
+ txBuilder,
+ nil,
+ logger.TestLogger(t),
+ &testCheckerFactory{},
+ false,
+ )
+
+ // Instance starts without error even if loading next sequence map fails
+ err := eb.Start(testutils.Context(t))
+ require.NoError(t, err)
+}
+
func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewTestGeneralConfig(t)
@@ -946,7 +978,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
}
func getLocalNextNonce(t *testing.T, eb *txmgr.Broadcaster, fromAddress gethCommon.Address) uint64 {
- n, err := eb.GetNextSequence(fromAddress)
+ n, err := eb.GetNextSequence(testutils.Context(t), fromAddress)
require.NoError(t, err)
require.NotNil(t, n)
return uint64(n)
@@ -972,6 +1004,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, evmcfg, &testCheckerFactory{}, false)
+ ctx := testutils.Context(t)
require.NoError(t, utils.JustError(db.Exec(`SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`)))
@@ -983,7 +1016,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1019,7 +1052,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce
}), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once()
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1036,7 +1069,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// Check that the key had its nonce reset
var nonce evmtypes.Nonce
- nonce, err = eb.GetNextSequence(fromAddress)
+ nonce, err = eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
// Saved NextNonce must be the same as before because this transaction
// was not accepted by the eth node and never can be
@@ -1070,7 +1103,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce
}), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once()
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), "something exploded in the callback")
assert.True(t, retryable)
@@ -1092,7 +1125,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once()
{
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
}
@@ -1105,7 +1138,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
localNextNonce = getLocalNextNonce(t, eb, fromAddress)
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce), nil).Once()
eb2 := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), evmcfg.Database().Listener(), ethKeyStore, txBuilder, nil, lggr, &testCheckerFactory{}, false)
- retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
})
@@ -1127,7 +1160,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// another node even if the primary one returns "exceeds the configured
// cap"
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
assert.Contains(t, err.Error(), "tx fee (1.10 ether) exceeds the configured cap (1.00 ether)")
assert.Contains(t, err.Error(), "error while sending transaction")
@@ -1147,7 +1180,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// Check that the key had its nonce reset
var nonce evmtypes.Nonce
- nonce, err = eb.GetNextSequence(fromAddress)
+ nonce, err = eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
// Saved NextNonce must be the same as before because this transaction
// was not accepted by the eth node and never can be
@@ -1156,7 +1189,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// On the second try, the tx has been accepted into the mempool
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce+1), nil).Once()
- retryable, err = eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err = eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1184,7 +1217,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce), nil).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), retryableErrorExample)
assert.True(t, retryable)
@@ -1207,7 +1240,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce
}), fromAddress).Return(commonclient.Successful, nil).Once()
- retryable, err = eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err = eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1235,7 +1268,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), errors.New("pending nonce fetch failed")).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), retryableErrorExample)
require.Contains(t, err.Error(), "pending nonce fetch failed")
@@ -1259,7 +1292,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce
}), fromAddress).Return(commonclient.Successful, nil).Once()
- retryable, err = eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err = eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1288,7 +1321,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce+1), nil).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.NoError(t, err)
assert.False(t, retryable)
@@ -1330,7 +1363,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Successful, nil).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.NoError(t, err)
assert.False(t, retryable)
@@ -1366,7 +1399,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Retryable, failedToReachNodeError).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
assert.Contains(t, err.Error(), "context deadline exceeded")
assert.True(t, retryable)
@@ -1397,7 +1430,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Successful, errors.New(temporarilyUnderpricedError)).Once()
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1437,7 +1470,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Do the thing
- retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), "bumped fee price of 20 gwei is equal to original fee price of 20 gwei. ACTION REQUIRED: This is a configuration error, you must increase either FeeEstimator.BumpPercent or FeeEstimator.BumpMin")
assert.True(t, retryable)
@@ -1454,7 +1487,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce
}), fromAddress).Return(commonclient.InsufficientFunds, errors.New(insufficientEthError)).Once()
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
assert.Contains(t, err.Error(), "insufficient funds for transfer")
assert.True(t, retryable)
@@ -1484,7 +1517,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce
}), fromAddress).Return(commonclient.Retryable, errors.New(nonceGapError)).Once()
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
assert.Contains(t, err.Error(), nonceGapError)
assert.True(t, retryable)
@@ -1529,7 +1562,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once()
// Check gas tip cap verification
- retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), "bumped gas tip cap of 1 wei is less than or equal to original gas tip cap of 1 wei")
assert.True(t, retryable)
@@ -1553,7 +1586,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once()
eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, evmcfg2, &testCheckerFactory{}, false)
- retryable, err := eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), "specified gas tip cap of 0 is below min configured gas tip of 1 wei for key")
assert.True(t, retryable)
@@ -1580,7 +1613,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), big.NewInt(0).Mul(evmcfg2.EVM().GasEstimator().BumpMin().ToInt(), big.NewInt(2)))) == 0
}), fromAddress).Return(commonclient.Successful, nil).Once()
- retryable, err = eb2.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err = eb2.ProcessUnstartedTxs(ctx, fromAddress)
require.NoError(t, err)
assert.False(t, retryable)
@@ -1612,7 +1645,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) {
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Once()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, kst, evmcfg, &testCheckerFactory{}, false)
- _, err := eb.GetNextSequence(fromAddress)
+ ctx := testutils.Context(t)
+ _, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
t.Run("tx signing fails", func(t *testing.T) {
@@ -1626,7 +1660,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) {
})).Return(&tx, errors.New("could not sign transaction"))
// Do the thing
- retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress)
+ retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress)
require.Error(t, err)
require.Contains(t, err.Error(), "could not sign transaction")
assert.True(t, retryable)
@@ -1640,7 +1674,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) {
// Check that the key did not have its nonce incremented
var nonce types.Nonce
- nonce, err = eb.GetNextSequence(fromAddress)
+ nonce, err = eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
require.Equal(t, int64(localNonce), int64(nonce))
})
@@ -1678,12 +1712,13 @@ func TestEthBroadcaster_IncrementNextNonce(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, kst, evmcfg, &testCheckerFactory{}, false)
- nonce, err := eb.GetNextSequence(fromAddress)
+ ctx := testutils.Context(t)
+ nonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
eb.IncrementNextSequence(fromAddress, nonce)
// Nonce bumped to 1
- nonce, err = eb.GetNextSequence(fromAddress)
+ nonce, err = eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
require.Equal(t, int64(1), int64(nonce))
}
@@ -1737,7 +1772,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Once()
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
eb := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, nil, lggr, checkerFactory, false)
- err := eb.Start(testutils.Context(t))
+ err := eb.Start(ctx)
assert.NoError(t, err)
defer func() { assert.NoError(t, eb.Close()) }()
@@ -1763,12 +1798,12 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
testutils.WaitForLogMessage(t, observed, "Fast-forward sequence")
// Check nextSequenceMap to make sure it has correct nonce assigned
- nonce, err := eb.GetNextSequence(fromAddress)
+ nonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
- assert.Equal(t, strconv.FormatUint(ethNodeNonce, 10), nonce.String())
+ require.Equal(t, strconv.FormatUint(ethNodeNonce, 10), nonce.String())
// The disabled key did not get updated
- _, err = eb.GetNextSequence(disabledAddress)
+ _, err = eb.GetNextSequence(ctx, disabledAddress)
require.Error(t, err)
})
@@ -1797,19 +1832,19 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
testutils.WaitForLogMessage(t, observed, "Fast-forward sequence")
// Check keyState to make sure it has correct nonce assigned
- nonce, err := eb.GetNextSequence(fromAddress)
+ nonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
assert.Equal(t, int64(ethNodeNonce), int64(nonce))
// The disabled key did not get updated
- _, err = eb.GetNextSequence(disabledAddress)
+ _, err = eb.GetNextSequence(ctx, disabledAddress)
require.Error(t, err)
})
-
}
func Test_LoadSequenceMap(t *testing.T) {
t.Parallel()
+ ctx := testutils.Context(t)
t.Run("set next nonce using entries from tx table", func(t *testing.T) {
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewTestGeneralConfig(t)
@@ -1824,9 +1859,9 @@ func Test_LoadSequenceMap(t *testing.T) {
cltest.MustInsertUnconfirmedEthTx(t, txStore, int64(1), fromAddress)
eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false)
- nonce, err := eb.GetNextSequence(fromAddress)
+ nonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
- assert.Equal(t, int64(2), int64(nonce))
+ require.Equal(t, int64(2), int64(nonce))
})
t.Run("set next nonce using client when not found in tx table", func(t *testing.T) {
@@ -1842,9 +1877,9 @@ func Test_LoadSequenceMap(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(10), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false)
- nonce, err := eb.GetNextSequence(fromAddress)
+ nonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
- assert.Equal(t, int64(10), int64(nonce))
+ require.Equal(t, int64(10), int64(nonce))
})
}
@@ -1863,25 +1898,53 @@ func Test_NextNonce(t *testing.T) {
_, addr1 := cltest.MustInsertRandomKey(t, ks)
ethClient.On("PendingNonceAt", mock.Anything, addr1).Return(uint64(randNonce), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false)
-
+ ctx := testutils.Context(t)
cltest.MustInsertRandomKey(t, ks, *utils.NewBig(testutils.FixtureChainID))
- nonce, err := eb.GetNextSequence(addr1)
+ nonce, err := eb.GetNextSequence(ctx, addr1)
require.NoError(t, err)
- assert.Equal(t, randNonce, int64(nonce))
+ require.Equal(t, randNonce, int64(nonce))
randAddr1 := utils.RandomAddress()
- _, err = eb.GetNextSequence(randAddr1)
+ _, err = eb.GetNextSequence(ctx, randAddr1)
require.Error(t, err)
- assert.Contains(t, err.Error(), fmt.Sprintf("address not found in next sequence map: %s", randAddr1.Hex()))
+ require.Contains(t, err.Error(), fmt.Sprintf("address disabled: %s", randAddr1.Hex()))
randAddr2 := utils.RandomAddress()
- _, err = eb.GetNextSequence(randAddr2)
+ _, err = eb.GetNextSequence(ctx, randAddr2)
require.Error(t, err)
- assert.Contains(t, err.Error(), fmt.Sprintf("address not found in next sequence map: %s", randAddr2.Hex()))
+ require.Contains(t, err.Error(), fmt.Sprintf("address disabled: %s", randAddr2.Hex()))
}
+func Test_SetNonceAfterInit(t *testing.T) {
+ t.Parallel()
+
+ db := pgtest.NewSqlxDB(t)
+ cfg := configtest.NewTestGeneralConfig(t)
+ txStore := cltest.NewTestTxStore(t, db, cfg.Database())
+ ks := cltest.NewKeyStore(t, db, cfg.Database()).Eth()
+
+ ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ checkerFactory := &txmgr.CheckerFactory{Client: ethClient}
+ randNonce := testutils.NewRandomPositiveInt64()
+ _, addr1 := cltest.MustInsertRandomKey(t, ks)
+ ethClient.On("PendingNonceAt", mock.Anything, addr1).Return(uint64(0), errors.New("failed to retrieve nonce at startup")).Once()
+ ethClient.On("PendingNonceAt", mock.Anything, addr1).Return(uint64(randNonce), nil).Once()
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false)
+
+ ctx := testutils.Context(t)
+ nonce, err := eb.GetNextSequence(ctx, addr1)
+ require.NoError(t, err)
+ require.Equal(t, randNonce, int64(nonce))
+
+ // Test that the new nonce is set in the map and does not need a client call to retrieve on subsequent calls
+ nonce, err = eb.GetNextSequence(ctx, addr1)
+ require.NoError(t, err)
+ require.Equal(t, randNonce, int64(nonce))
+}
+
func Test_IncrementNextNonce(t *testing.T) {
t.Parallel()
@@ -1898,26 +1961,27 @@ func Test_IncrementNextNonce(t *testing.T) {
ethClient.On("PendingNonceAt", mock.Anything, addr1).Return(uint64(randNonce), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false)
- nonce, err := eb.GetNextSequence(addr1)
+ ctx := testutils.Context(t)
+ nonce, err := eb.GetNextSequence(ctx, addr1)
require.NoError(t, err)
eb.IncrementNextSequence(addr1, nonce)
- nonce, err = eb.GetNextSequence(addr1)
+ nonce, err = eb.GetNextSequence(ctx, addr1)
require.NoError(t, err)
assert.Equal(t, randNonce+1, int64(nonce))
eb.IncrementNextSequence(addr1, nonce)
- nonce, err = eb.GetNextSequence(addr1)
+ nonce, err = eb.GetNextSequence(ctx, addr1)
require.NoError(t, err)
assert.Equal(t, randNonce+2, int64(nonce))
randAddr1 := utils.RandomAddress()
- _, err = eb.GetNextSequence(randAddr1)
+ _, err = eb.GetNextSequence(ctx, randAddr1)
require.Error(t, err)
- assert.Contains(t, err.Error(), fmt.Sprintf("address not found in next sequence map: %s", randAddr1.Hex()))
+ assert.Contains(t, err.Error(), fmt.Sprintf("address disabled: %s", randAddr1.Hex()))
// verify it didnt get changed by any erroring calls
- nonce, err = eb.GetNextSequence(addr1)
+ nonce, err = eb.GetNextSequence(ctx, addr1)
require.NoError(t, err)
assert.Equal(t, randNonce+2, int64(nonce))
}
@@ -1936,14 +2000,15 @@ func Test_SetNextNonce(t *testing.T) {
_, fromAddress := cltest.MustInsertRandomKey(t, ks)
ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once()
eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false)
+ ctx := testutils.Context(t)
t.Run("update next nonce", func(t *testing.T) {
- nonce, err := eb.GetNextSequence(fromAddress)
+ nonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
assert.Equal(t, int64(0), int64(nonce))
eb.SetNextSequence(fromAddress, evmtypes.Nonce(24))
- newNextNonce, err := eb.GetNextSequence(fromAddress)
+ newNextNonce, err := eb.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
assert.Equal(t, int64(24), int64(newNextNonce))
})
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index a10f9dd1c6..1351c42134 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -36,6 +36,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
...
+## 2.7.1 - UNRELEASED
+
+### Fixed
+
+- Fixed a bug that causes the node to shutdown if all configured RPC's are unreachable during startup.
+
## 2.7.0 - UNRELEASED
### Added
From 101d5deab2db52a09744ad12c7693372a9fd8bac Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Thu, 16 Nov 2023 12:00:54 -0600
Subject: [PATCH 163/327] replace all context.TODO()s (#11313)
---
common/txmgr/confirmer.go | 8 ++++----
core/chains/evm/txmgr/confirmer_test.go | 10 +++++-----
core/cmd/shell_local.go | 7 ++++---
core/internal/cltest/cltest.go | 1 +
.../chainlink/relayer_chain_interoperators.go | 2 +-
core/services/chainlink/relayer_factory.go | 2 +-
.../ocr2/plugins/dkg/persistence/db_test.go | 14 +++++++-------
7 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go
index afb2b3003a..4d3626ffac 100644
--- a/common/txmgr/confirmer.go
+++ b/common/txmgr/confirmer.go
@@ -1025,7 +1025,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) mar
// This operates completely orthogonal to the normal Confirmer and can result in untracked attempts!
// Only for emergency usage.
// This is in case of some unforeseen scenario where the node is refusing to release the lock. KISS.
-func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ForceRebroadcast(seqs []SEQ, fee FEE, address ADDR, overrideGasLimit uint32) error {
+func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ForceRebroadcast(ctx context.Context, seqs []SEQ, fee FEE, address ADDR, overrideGasLimit uint32) error {
if len(seqs) == 0 {
ec.lggr.Infof("ForceRebroadcast: No sequences provided. Skipping")
return nil
@@ -1034,13 +1034,13 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) For
for _, seq := range seqs {
- etx, err := ec.txStore.FindTxWithSequence(context.TODO(), address, seq)
+ etx, err := ec.txStore.FindTxWithSequence(ctx, address, seq)
if err != nil {
return errors.Wrap(err, "ForceRebroadcast failed")
}
if etx == nil {
ec.lggr.Debugf("ForceRebroadcast: no tx found with sequence %s, will rebroadcast empty transaction", seq)
- hashStr, err := ec.sendEmptyTransaction(context.TODO(), address, seq, overrideGasLimit, fee)
+ hashStr, err := ec.sendEmptyTransaction(ctx, address, seq, overrideGasLimit, fee)
if err != nil {
ec.lggr.Errorw("ForceRebroadcast: failed to send empty transaction", "sequence", seq, "err", err)
continue
@@ -1058,7 +1058,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) For
}
attempt.Tx = *etx // for logging
ec.lggr.Debugw("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", etx.FeeLimit, "attempt", attempt)
- if errCode, err := ec.client.SendTransactionReturnCode(context.TODO(), *etx, attempt, ec.lggr); errCode != client.Successful && err != nil {
+ if errCode, err := ec.client.SendTransactionReturnCode(ctx, *etx, attempt, ec.lggr); errCode != client.Successful && err != nil {
ec.lggr.Errorw(fmt.Sprintf("ForceRebroadcast: failed to rebroadcast tx %v with sequence %v and gas limit %v: %s", etx.ID, *etx.Sequence, etx.FeeLimit, err.Error()), "err", err, "fee", attempt.TxFee)
continue
}
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index 31464f8f52..e17e7993cf 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -2819,7 +2819,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
tx.To().String() == etx1.ToAddress.String()
}), mock.Anything).Return(commonclient.Successful, nil).Once()
- require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{1}, gasPriceWei, fromAddress, overrideGasLimit))
+ require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{1}, gasPriceWei, fromAddress, overrideGasLimit))
})
t.Run("uses default gas limit if overrideGasLimit is 0", func(t *testing.T) {
@@ -2834,7 +2834,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
tx.To().String() == etx1.ToAddress.String()
}), mock.Anything).Return(commonclient.Successful, nil).Once()
- require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{(1)}, gasPriceWei, fromAddress, 0))
+ require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{(1)}, gasPriceWei, fromAddress, 0))
})
t.Run("rebroadcasts several eth_txes in nonce range", func(t *testing.T) {
@@ -2848,7 +2848,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
return tx.Nonce() == uint64(*etx2.Sequence) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == uint64(overrideGasLimit)
}), mock.Anything).Return(commonclient.Successful, nil).Once()
- require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{(1), (2)}, gasPriceWei, fromAddress, overrideGasLimit))
+ require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{(1), (2)}, gasPriceWei, fromAddress, overrideGasLimit))
})
t.Run("broadcasts zero transactions if eth_tx doesn't exist for that nonce", func(t *testing.T) {
@@ -2874,7 +2874,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
}
nonces := []evmtypes.Nonce{(1), (2), (3), (4), (5)}
- require.NoError(t, ec.ForceRebroadcast(nonces, gasPriceWei, fromAddress, overrideGasLimit))
+ require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), nonces, gasPriceWei, fromAddress, overrideGasLimit))
})
t.Run("zero transactions use default gas limit if override wasn't specified", func(t *testing.T) {
@@ -2885,7 +2885,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && uint32(tx.Gas()) == config.EVM().GasEstimator().LimitDefault()
}), mock.Anything).Return(commonclient.Successful, nil).Once()
- require.NoError(t, ec.ForceRebroadcast([]evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0))
+ require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0))
})
}
diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go
index f7e17ef7fc..cbd0feccbf 100644
--- a/core/cmd/shell_local.go
+++ b/core/cmd/shell_local.go
@@ -558,6 +558,7 @@ func checkFilePermissions(lggr logger.Logger, rootDir string) error {
// RebroadcastTransactions run locally to force manual rebroadcasting of
// transactions in a given nonce range.
func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) {
+ ctx := s.ctx()
beginningNonce := c.Int64("beginningNonce")
endingNonce := c.Int64("endingNonce")
gasPriceWei := c.Uint64("gasPriceWei")
@@ -587,7 +588,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) {
}
defer lggr.ErrorIfFn(db.Close, "Error closing db")
- app, err := s.AppFactory.NewApplication(context.TODO(), s.Config, lggr, db)
+ app, err := s.AppFactory.NewApplication(ctx, s.Config, lggr, db)
if err != nil {
return s.errorOut(errors.Wrap(err, "fatal error instantiating application"))
}
@@ -603,7 +604,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) {
ethClient := chain.Client()
- err = ethClient.Dial(context.TODO())
+ err = ethClient.Dial(ctx)
if err != nil {
return err
}
@@ -642,7 +643,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) {
for i := int64(0); i < totalNonces; i++ {
nonces[i] = evmtypes.Nonce(beginningNonce + i)
}
- err = ec.ForceRebroadcast(nonces, gas.EvmFee{Legacy: assets.NewWeiI(int64(gasPriceWei))}, address, uint32(overrideGasLimit))
+ err = ec.ForceRebroadcast(ctx, nonces, gas.EvmFee{Legacy: assets.NewWeiI(int64(gasPriceWei))}, address, uint32(overrideGasLimit))
return s.errorOut(err)
}
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 644c516c21..83a97833bd 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -40,6 +40,7 @@ import (
"github.com/urfave/cli"
"github.com/jmoiron/sqlx"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
"github.com/smartcontractkit/chainlink-relay/pkg/loop"
diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go
index b2ec0822d4..1183277ac0 100644
--- a/core/services/chainlink/relayer_chain_interoperators.go
+++ b/core/services/chainlink/relayer_chain_interoperators.go
@@ -121,7 +121,7 @@ func InitEVM(ctx context.Context, factory RelayerFactory, config EVMFactoryConfi
// InitCosmos is a option for instantiating Cosmos relayers
func InitCosmos(ctx context.Context, factory RelayerFactory, config CosmosFactoryConfig) CoreRelayerChainInitFunc {
return func(op *CoreRelayerChainInteroperators) (err error) {
- adapters, err2 := factory.NewCosmos(ctx, config)
+ adapters, err2 := factory.NewCosmos(config)
if err2 != nil {
return fmt.Errorf("failed to setup Cosmos relayer: %w", err2)
}
diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go
index d452decda1..4bbabea4c8 100644
--- a/core/services/chainlink/relayer_factory.go
+++ b/core/services/chainlink/relayer_factory.go
@@ -250,7 +250,7 @@ func (c CosmosFactoryConfig) Validate() error {
return err
}
-func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConfig) (map[relay.ID]CosmosLoopRelayerChainer, error) {
+func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[relay.ID]CosmosLoopRelayerChainer, error) {
err := config.Validate()
if err != nil {
return nil, fmt.Errorf("cannot create Cosmos relayer: %w", err)
diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go
index 4e029c1cb2..d4a4546fb9 100644
--- a/core/services/ocr2/plugins/dkg/persistence/db_test.go
+++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go
@@ -1,18 +1,18 @@
package persistence
import (
- "context"
"fmt"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/crypto"
"github.com/jmoiron/sqlx"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
- "github.com/smartcontractkit/ocr2vrf/types/hash"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+ "github.com/smartcontractkit/ocr2vrf/types/hash"
+
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -50,7 +50,7 @@ func TestShareDB_WriteShareRecords(t *testing.T) {
expectedRecords = append(expectedRecords, rec)
}
- err := shareDB.WriteShareRecords(context.TODO(), configDigest, keyID, expectedRecords)
+ err := shareDB.WriteShareRecords(testutils.Context(t), configDigest, keyID, expectedRecords)
require.NoError(tt, err)
rows, err := db.Query(`SELECT COUNT(*) AS count FROM dkg_shares`)
@@ -79,7 +79,7 @@ func TestShareDB_WriteShareRecords(t *testing.T) {
}
// no error, but there will be no rows inserted in the db
- err = shareDB.WriteShareRecords(context.TODO(), configDigest, keyID, records)
+ err = shareDB.WriteShareRecords(testutils.Context(t), configDigest, keyID, records)
require.NoError(tt, err)
rows, err := db.Query(`SELECT COUNT(*) AS count FROM dkg_shares`)
@@ -116,7 +116,7 @@ func TestShareDB_WriteShareRecords(t *testing.T) {
records = append(records, rec)
}
- err := shareDB.WriteShareRecords(context.TODO(), configDigest, keyID, records)
+ err := shareDB.WriteShareRecords(testutils.Context(t), configDigest, keyID, records)
require.Error(tt, err)
// no rows should have been inserted
@@ -160,7 +160,7 @@ func TestShareDBE2E(t *testing.T) {
expectedRecordsMap[*playerIdx] = rec
}
- err := shareDB.WriteShareRecords(context.TODO(), configDigest, keyID, expectedRecords)
+ err := shareDB.WriteShareRecords(testutils.Context(t), configDigest, keyID, expectedRecords)
require.NoError(t, err)
actualRecords, err := shareDB.ReadShareRecords(configDigest, keyID)
From e030073e8cfbb12ef86321f9755b2488a472c4f8 Mon Sep 17 00:00:00 2001
From: Lei
Date: Thu, 16 Nov 2023 10:10:23 -0800
Subject: [PATCH 164/327] refactor mercury (#11137)
* refactor mercury, rebase on top of PR 10878
* change back to use eth_call, sigh, simulated backend in integration test doesnt like using the registry contract directly
* fixes and include new threadctl changes
* address comments, add time in logs
* rebase and add a test
---
core/scripts/chaincli/handler/debug.go | 31 +-
core/scripts/chaincli/handler/keeper.go | 5 +-
.../handler/mercury_lookup_handler.go | 6 +-
.../ocr2keeper/evm21/block_subscriber.go | 5 +
.../ocr2keeper/evm21/encoding/interface.go | 61 +-
.../ocr2keeper/evm21/encoding/packer.go | 25 +-
.../ocr2keeper/evm21/encoding/packer_test.go | 12 +-
.../ocr2keeper/evm21/mercury/mercury.go | 122 ++
.../ocr2keeper/evm21/mercury/mercury_test.go | 49 +
.../evm21/mercury/streams/streams.go | 330 ++++
.../evm21/mercury/streams/streams_test.go | 726 +++++++++
.../evm21/mercury/upkeep_failure_reasons.go | 15 +
.../ocr2keeper/evm21/mercury/upkeep_states.go | 14 +
.../ocr2keeper/evm21/mercury/v02/request.go | 203 +++
.../evm21/mercury/v02/v02_request_test.go | 468 ++++++
.../ocr2keeper/evm21/mercury/v03/request.go | 252 +++
.../evm21/mercury/v03/v03_request_test.go | 536 +++++++
.../ocr2/plugins/ocr2keeper/evm21/registry.go | 89 +-
.../evm21/registry_check_pipeline.go | 6 +-
.../evm21/registry_check_pipeline_test.go | 56 +-
.../ocr2keeper/evm21/streams_lookup.go | 642 --------
.../ocr2keeper/evm21/streams_lookup_test.go | 1354 -----------------
.../plugins/ocr2keeper/integration_21_test.go | 9 +-
integration-tests/smoke/automation_test.go | 10 +-
24 files changed, 2928 insertions(+), 2098 deletions(-)
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury_test.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_failure_reasons.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_states.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go
delete mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
delete mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go
index daf012ee16..8f65b1f881 100644
--- a/core/scripts/chaincli/handler/debug.go
+++ b/core/scripts/chaincli/handler/debug.go
@@ -18,16 +18,18 @@ import (
gethcommon "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/ethclient"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/core/scripts/chaincli/config"
"github.com/smartcontractkit/chainlink/core/scripts/common"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
- evm "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
"github.com/smartcontractkit/chainlink/v2/core/utils"
bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
)
const (
@@ -227,6 +229,13 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
message(fmt.Sprintf("checkUpkeep failed with UpkeepFailureReason %d", checkResult.UpkeepFailureReason))
}
if checkResult.UpkeepFailureReason == uint8(encoding.UpkeepFailureReasonTargetCheckReverted) {
+ // TODO use the new streams lookup lib
+ //mc := &models.MercuryCredentials{k.cfg.MercuryLegacyURL, k.cfg.MercuryURL, k.cfg.MercuryID, k.cfg.MercuryKey}
+ //mercuryConfig := evm.NewMercuryConfig(mc, core.StreamsCompatibleABI)
+ //lggr, _ := logger.NewLogger()
+ //blockSub := &blockSubscriber{k.client}
+ //_ = streams.NewStreamsLookup(packer, mercuryConfig, blockSub, keeperRegistry21, k.rpcClient, lggr)
+
streamsLookupErr, err := packer.DecodeStreamsLookupRequest(checkResult.PerformData)
if err == nil {
message("upkeep reverted with StreamsLookup")
@@ -240,7 +249,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
}
allowed := false
if len(cfg) > 0 {
- var privilegeConfig evm.UpkeepPrivilegeConfig
+ var privilegeConfig streams.UpkeepPrivilegeConfig
if err := json.Unmarshal(cfg, &privilegeConfig); err != nil {
failUnknown("failed to unmarshal privilege config ", err)
}
@@ -307,6 +316,22 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
}
}
+type blockSubscriber struct {
+ ethClient *ethclient.Client
+}
+
+func (bs *blockSubscriber) LatestBlock() *ocr2keepers.BlockKey {
+ header, err := bs.ethClient.HeaderByNumber(context.Background(), nil)
+ if err != nil {
+ return nil
+ }
+
+ return &ocr2keepers.BlockKey{
+ Number: ocr2keepers.BlockNumber(header.Number.Uint64()),
+ Hash: header.Hash(),
+ }
+}
+
func logMatchesTriggerConfig(log *types.Log, config automation_utils_2_1.LogTriggerConfig) bool {
if log.Topics[0] != config.Topic0 {
return false
diff --git a/core/scripts/chaincli/handler/keeper.go b/core/scripts/chaincli/handler/keeper.go
index ba8276efb5..453ef43a56 100644
--- a/core/scripts/chaincli/handler/keeper.go
+++ b/core/scripts/chaincli/handler/keeper.go
@@ -14,6 +14,8 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/umbracle/ethgo/abi"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
+
"github.com/smartcontractkit/chainlink/core/scripts/chaincli/config"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
@@ -34,7 +36,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/verifiable_load_upkeep_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keeper"
- evm "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
)
// Keeper is the keepers commands handler
@@ -719,7 +720,7 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address,
log.Printf("registry version is %s", v)
log.Printf("active upkeep ids: %v", activeUpkeepIds)
- adminBytes, err := json.Marshal(evm.UpkeepPrivilegeConfig{
+ adminBytes, err := json.Marshal(streams.UpkeepPrivilegeConfig{
MercuryEnabled: true,
})
if err != nil {
diff --git a/core/scripts/chaincli/handler/mercury_lookup_handler.go b/core/scripts/chaincli/handler/mercury_lookup_handler.go
index 0db142df9f..1bd4b2e183 100644
--- a/core/scripts/chaincli/handler/mercury_lookup_handler.go
+++ b/core/scripts/chaincli/handler/mercury_lookup_handler.go
@@ -3,7 +3,9 @@ package handler
import (
"context"
"crypto/hmac"
+ "crypto/sha256"
"encoding/hex"
+ "encoding/json"
"fmt"
"io"
"math/big"
@@ -13,10 +15,6 @@ import (
"strings"
"time"
- "crypto/sha256"
-
- "encoding/json"
-
"github.com/avast/retry-go"
ethabi "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
index d97156ed18..6cc19a4d02 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
@@ -12,6 +12,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/smartcontractkit/chainlink-relay/pkg/services"
+
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -56,6 +57,10 @@ type BlockSubscriber struct {
lggr logger.Logger
}
+func (bs *BlockSubscriber) LatestBlock() *ocr2keepers.BlockKey {
+ return bs.latestBlock.Load()
+}
+
var _ ocr2keepers.BlockSubscriber = &BlockSubscriber{}
func NewBlockSubscriber(hb httypes.HeadBroadcaster, lp logpoller.LogPoller, finalityDepth uint32, lggr logger.Logger) *BlockSubscriber {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go
index 217f0dcb57..e21ecfb800 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go
@@ -5,56 +5,55 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
)
-type UpkeepFailureReason uint8
-type PipelineExecutionState uint8
-
const (
// upkeep failure onchain reasons
- UpkeepFailureReasonNone UpkeepFailureReason = 0
- UpkeepFailureReasonUpkeepCancelled UpkeepFailureReason = 1
- UpkeepFailureReasonUpkeepPaused UpkeepFailureReason = 2
- UpkeepFailureReasonTargetCheckReverted UpkeepFailureReason = 3
- UpkeepFailureReasonUpkeepNotNeeded UpkeepFailureReason = 4
- UpkeepFailureReasonPerformDataExceedsLimit UpkeepFailureReason = 5
- UpkeepFailureReasonInsufficientBalance UpkeepFailureReason = 6
- UpkeepFailureReasonMercuryCallbackReverted UpkeepFailureReason = 7
- UpkeepFailureReasonRevertDataExceedsLimit UpkeepFailureReason = 8
- UpkeepFailureReasonRegistryPaused UpkeepFailureReason = 9
+ UpkeepFailureReasonNone uint8 = 0
+ UpkeepFailureReasonUpkeepCancelled uint8 = 1
+ UpkeepFailureReasonUpkeepPaused uint8 = 2
+ UpkeepFailureReasonTargetCheckReverted uint8 = 3
+ UpkeepFailureReasonUpkeepNotNeeded uint8 = 4
+ UpkeepFailureReasonPerformDataExceedsLimit uint8 = 5
+ UpkeepFailureReasonInsufficientBalance uint8 = 6
+ UpkeepFailureReasonMercuryCallbackReverted uint8 = 7
+ UpkeepFailureReasonRevertDataExceedsLimit uint8 = 8
+ UpkeepFailureReasonRegistryPaused uint8 = 9
// leaving a gap here for more onchain failure reasons in the future
// upkeep failure offchain reasons
- UpkeepFailureReasonMercuryAccessNotAllowed UpkeepFailureReason = 32
- UpkeepFailureReasonTxHashNoLongerExists UpkeepFailureReason = 33
- UpkeepFailureReasonInvalidRevertDataInput UpkeepFailureReason = 34
- UpkeepFailureReasonSimulationFailed UpkeepFailureReason = 35
- UpkeepFailureReasonTxHashReorged UpkeepFailureReason = 36
+ UpkeepFailureReasonMercuryAccessNotAllowed uint8 = 32
+ UpkeepFailureReasonTxHashNoLongerExists uint8 = 33
+ UpkeepFailureReasonInvalidRevertDataInput uint8 = 34
+ UpkeepFailureReasonSimulationFailed uint8 = 35
+ UpkeepFailureReasonTxHashReorged uint8 = 36
// pipeline execution error
- NoPipelineError PipelineExecutionState = 0
- CheckBlockTooOld PipelineExecutionState = 1
- CheckBlockInvalid PipelineExecutionState = 2
- RpcFlakyFailure PipelineExecutionState = 3
- MercuryFlakyFailure PipelineExecutionState = 4
- PackUnpackDecodeFailed PipelineExecutionState = 5
- MercuryUnmarshalError PipelineExecutionState = 6
- InvalidMercuryRequest PipelineExecutionState = 7
- InvalidMercuryResponse PipelineExecutionState = 8 // this will only happen if Mercury server sends bad responses
- UpkeepNotAuthorized PipelineExecutionState = 9
+ NoPipelineError uint8 = 0
+ CheckBlockTooOld uint8 = 1
+ CheckBlockInvalid uint8 = 2
+ RpcFlakyFailure uint8 = 3
+ MercuryFlakyFailure uint8 = 4
+ PackUnpackDecodeFailed uint8 = 5
+ MercuryUnmarshalError uint8 = 6
+ InvalidMercuryRequest uint8 = 7
+ InvalidMercuryResponse uint8 = 8 // this will only happen if Mercury server sends bad responses
+ UpkeepNotAuthorized uint8 = 9
)
type UpkeepInfo = iregistry21.KeeperRegistryBase21UpkeepInfo
type Packer interface {
UnpackCheckResult(payload ocr2keepers.UpkeepPayload, raw string) (ocr2keepers.CheckResult, error)
- UnpackCheckCallbackResult(callbackResp []byte) (PipelineExecutionState, bool, []byte, uint8, *big.Int, error)
- UnpackPerformResult(raw string) (PipelineExecutionState, bool, error)
+ UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error)
+ UnpackPerformResult(raw string) (uint8, bool, error)
UnpackLogTriggerConfig(raw []byte) (automation_utils_2_1.LogTriggerConfig, error)
PackReport(report automation_utils_2_1.KeeperRegistryBase21Report) ([]byte, error)
UnpackReport(raw []byte) (automation_utils_2_1.KeeperRegistryBase21Report, error)
PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error)
UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error)
- DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error)
+ DecodeStreamsLookupRequest(data []byte) (*mercury.StreamsLookupError, error)
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go
index 9e070b2838..28c6c4a975 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go
@@ -6,8 +6,11 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common/hexutil"
+
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
)
@@ -80,7 +83,7 @@ func (p *abiPacker) UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error)
return bts, nil
}
-func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (PipelineExecutionState, bool, []byte, uint8, *big.Int, error) {
+func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) {
out, err := p.registryABI.Methods["checkCallback"].Outputs.UnpackValues(callbackResp)
if err != nil {
return PackUnpackDecodeFailed, false, nil, 0, nil, fmt.Errorf("%w: unpack checkUpkeep return: %s", err, hexutil.Encode(callbackResp))
@@ -94,7 +97,7 @@ func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (PipelineExec
return NoPipelineError, upkeepNeeded, rawPerformData, failureReason, gasUsed, nil
}
-func (p *abiPacker) UnpackPerformResult(raw string) (PipelineExecutionState, bool, error) {
+func (p *abiPacker) UnpackPerformResult(raw string) (uint8, bool, error) {
b, err := hexutil.Decode(raw)
if err != nil {
return PackUnpackDecodeFailed, false, err
@@ -161,16 +164,8 @@ func (p *abiPacker) UnpackReport(raw []byte) (automation_utils_2_1.KeeperRegistr
return report, nil
}
-type StreamsLookupError struct {
- FeedParamKey string
- Feeds []string
- TimeParamKey string
- Time *big.Int
- ExtraData []byte
-}
-
// DecodeStreamsLookupRequest decodes the revert error StreamsLookup(string feedParamKey, string[] feeds, string feedParamKey, uint256 time, byte[] extraData)
-func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error) {
+func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*mercury.StreamsLookupError, error) {
e := p.streamsABI.Errors["StreamsLookup"]
unpack, err := e.Unpack(data)
if err != nil {
@@ -178,7 +173,7 @@ func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError
}
errorParameters := unpack.([]interface{})
- return &StreamsLookupError{
+ return &mercury.StreamsLookupError{
FeedParamKey: *abi.ConvertType(errorParameters[0], new(string)).(*string),
Feeds: *abi.ConvertType(errorParameters[1], new([]string)).(*[]string),
TimeParamKey: *abi.ConvertType(errorParameters[2], new(string)).(*string),
@@ -188,10 +183,10 @@ func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError
}
// GetIneligibleCheckResultWithoutPerformData returns an ineligible check result with ineligibility reason and pipeline execution state but without perform data
-func GetIneligibleCheckResultWithoutPerformData(p ocr2keepers.UpkeepPayload, reason UpkeepFailureReason, state PipelineExecutionState, retryable bool) ocr2keepers.CheckResult {
+func GetIneligibleCheckResultWithoutPerformData(p ocr2keepers.UpkeepPayload, reason uint8, state uint8, retryable bool) ocr2keepers.CheckResult {
return ocr2keepers.CheckResult{
- IneligibilityReason: uint8(reason),
- PipelineExecutionState: uint8(state),
+ IneligibilityReason: reason,
+ PipelineExecutionState: state,
Retryable: retryable,
UpkeepID: p.UpkeepID,
Trigger: p.Trigger,
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go
index 1801b01857..03b55bfccc 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go
@@ -13,6 +13,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
automation21Utils "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
@@ -210,7 +212,7 @@ func TestPacker_UnpackPerformResult(t *testing.T) {
tests := []struct {
Name string
RawData string
- State PipelineExecutionState
+ State uint8
}{
{
Name: "unpack success",
@@ -238,7 +240,7 @@ func TestPacker_UnpackCheckCallbackResult(t *testing.T) {
FailureReason uint8
GasUsed *big.Int
ErrorString string
- State PipelineExecutionState
+ State uint8
}{
{
Name: "unpack upkeep needed",
@@ -441,14 +443,14 @@ func TestPacker_DecodeStreamsLookupRequest(t *testing.T) {
tests := []struct {
name string
data []byte
- expected *StreamsLookupError
- state PipelineExecutionState
+ expected *mercury.StreamsLookupError
+ state uint8
err error
}{
{
name: "success - decode to streams lookup",
data: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000002435eb50000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- expected: &StreamsLookupError{
+ expected: &mercury.StreamsLookupError{
FeedParamKey: "feedIdHex",
Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
TimeParamKey: "blockNumber",
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury.go
new file mode 100644
index 0000000000..cf6ebeafc6
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury.go
@@ -0,0 +1,122 @@
+package mercury
+
+import (
+ "context"
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "math/big"
+ "net/http"
+ "time"
+
+ "github.com/patrickmn/go-cache"
+
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
+)
+
+const (
+ FeedIDs = "feedIDs" // valid for v0.3
+ FeedIdHex = "feedIdHex" // valid for v0.2
+ BlockNumber = "blockNumber" // valid for v0.2
+ Timestamp = "timestamp" // valid for v0.3
+ totalFastPluginRetries = 5
+ totalMediumPluginRetries = 10
+)
+
+var GenerateHMACFn = func(method string, path string, body []byte, clientId string, secret string, ts int64) string {
+ bodyHash := sha256.New()
+ bodyHash.Write(body)
+ hashString := fmt.Sprintf("%s %s %s %s %d",
+ method,
+ path,
+ hex.EncodeToString(bodyHash.Sum(nil)),
+ clientId,
+ ts)
+ signedMessage := hmac.New(sha256.New, []byte(secret))
+ signedMessage.Write([]byte(hashString))
+ userHmac := hex.EncodeToString(signedMessage.Sum(nil))
+ return userHmac
+}
+
+// CalculateRetryConfig returns plugin retry interval based on how many times plugin has retried this work
+var CalculateRetryConfigFn = func(prk string, mercuryConfig MercuryConfigProvider) time.Duration {
+ var retryInterval time.Duration
+ var retries int
+ totalAttempts, ok := mercuryConfig.GetPluginRetry(prk)
+ if ok {
+ retries = totalAttempts.(int)
+ if retries < totalFastPluginRetries {
+ retryInterval = 1 * time.Second
+ } else if retries < totalMediumPluginRetries {
+ retryInterval = 5 * time.Second
+ }
+ // if the core node has retried totalMediumPluginRetries times, do not set retry interval and plugin will use
+ // the default interval
+ } else {
+ retryInterval = 1 * time.Second
+ }
+ mercuryConfig.SetPluginRetry(prk, retries+1, cache.DefaultExpiration)
+ return retryInterval
+}
+
+type MercuryData struct {
+ Index int
+ Error error
+ Retryable bool
+ Bytes [][]byte
+ State MercuryUpkeepState
+}
+
+type Packer interface {
+ UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error)
+ PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error)
+ UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error)
+ DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error)
+}
+
+type MercuryConfigProvider interface {
+ Credentials() *models.MercuryCredentials
+ IsUpkeepAllowed(string) (interface{}, bool)
+ SetUpkeepAllowed(string, interface{}, time.Duration)
+ GetPluginRetry(string) (interface{}, bool)
+ SetPluginRetry(string, interface{}, time.Duration)
+}
+
+type HttpClient interface {
+ Do(req *http.Request) (*http.Response, error)
+}
+
+type MercuryClient interface {
+ DoRequest(ctx context.Context, streamsLookup *StreamsLookup, pluginRetryKey string) (MercuryUpkeepState, MercuryUpkeepFailureReason, [][]byte, bool, time.Duration, error)
+}
+
+type StreamsLookupError struct {
+ FeedParamKey string
+ Feeds []string
+ TimeParamKey string
+ Time *big.Int
+ ExtraData []byte
+}
+
+type StreamsLookup struct {
+ *StreamsLookupError
+ UpkeepId *big.Int
+ Block uint64
+}
+
+func (l *StreamsLookup) IsMercuryVersionUnkown() bool {
+ return l.FeedParamKey != FeedIDs
+}
+
+func (l *StreamsLookup) IsMercuryV02() bool {
+ return l.FeedParamKey == FeedIdHex && l.TimeParamKey == BlockNumber
+}
+
+func (l *StreamsLookup) IsMercuryV03() bool {
+ return l.FeedParamKey == FeedIDs
+}
+
+func (l *StreamsLookup) IsMercuryUsingBatchPathV03() bool {
+ return l.TimeParamKey == BlockNumber
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury_test.go
new file mode 100644
index 0000000000..baa939dbec
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/mercury_test.go
@@ -0,0 +1,49 @@
+package mercury
+
+import (
+ "testing"
+)
+
+func TestGenerateHMACFn(t *testing.T) {
+ testCases := []struct {
+ name string
+ method string
+ path string
+ body []byte
+ clientId string
+ secret string
+ ts int64
+ expected string
+ }{
+ {
+ name: "generate hmac function",
+ method: "GET",
+ path: "/example",
+ body: []byte(""),
+ clientId: "yourClientId",
+ secret: "yourSecret",
+ ts: 1234567890,
+ expected: "17b0bb6b14f7b48ef9d24f941ff8f33ad2d5e94ac343380be02c2f1ca32fdbd8",
+ },
+ {
+ name: "generate hmac function with non-empty body",
+ method: "POST",
+ path: "/api",
+ body: []byte("request body"),
+ clientId: "anotherClientId",
+ secret: "anotherSecret",
+ ts: 1597534567,
+ expected: "d326c168c50c996e271d6b3b4c97944db01163994090f73fcf4fd42f23f06bbb",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ result := GenerateHMACFn(tc.method, tc.path, tc.body, tc.clientId, tc.secret, tc.ts)
+
+ if result != tc.expected {
+ t.Errorf("Expected: %s, Got: %s", tc.expected, result)
+ }
+ })
+ }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
new file mode 100644
index 0000000000..b83aca8a02
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
@@ -0,0 +1,330 @@
+package streams
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "net/http"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/patrickmn/go-cache"
+
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ "github.com/smartcontractkit/chainlink-relay/pkg/services"
+
+ iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+ v02 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02"
+ v03 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type Lookup interface {
+ Lookup(ctx context.Context, checkResults []ocr2keepers.CheckResult) []ocr2keepers.CheckResult
+}
+
+type latestBlockProvider interface {
+ LatestBlock() *ocr2keepers.BlockKey
+}
+
+type streamsRegistry interface {
+ GetUpkeepPrivilegeConfig(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error)
+ CheckCallback(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error)
+ Address() common.Address
+}
+
+type contextCaller interface {
+ CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error
+}
+
+type streams struct {
+ services.StateMachine
+ packer mercury.Packer
+ mercuryConfig mercury.MercuryConfigProvider
+ abi abi.ABI
+ blockSubscriber latestBlockProvider
+ registry streamsRegistry
+ client contextCaller
+ lggr logger.Logger
+ threadCtrl utils.ThreadControl
+ v02Client mercury.MercuryClient
+ v03Client mercury.MercuryClient
+}
+
+// UpkeepPrivilegeConfig represents the administrative offchain config for each upkeep. It can be set by s_upkeepPrivilegeManager
+// role on the registry. Upkeeps allowed to use Mercury server will have this set to true.
+type UpkeepPrivilegeConfig struct {
+ MercuryEnabled bool `json:"mercuryEnabled"`
+}
+
+func NewStreamsLookup(
+ packer mercury.Packer,
+ mercuryConfig mercury.MercuryConfigProvider,
+ blockSubscriber latestBlockProvider,
+ client contextCaller,
+ registry streamsRegistry,
+ lggr logger.Logger) *streams {
+ httpClient := http.DefaultClient
+ threadCtrl := utils.NewThreadControl()
+ return &streams{
+ packer: packer,
+ mercuryConfig: mercuryConfig,
+ abi: core.RegistryABI,
+ blockSubscriber: blockSubscriber,
+ registry: registry,
+ client: client,
+ lggr: lggr,
+ threadCtrl: threadCtrl,
+ v02Client: v02.NewClient(mercuryConfig, httpClient, threadCtrl, lggr),
+ v03Client: v03.NewClient(mercuryConfig, httpClient, threadCtrl, lggr),
+ }
+}
+
+// Lookup looks through check upkeep results looking for any that need off chain lookup
+func (s *streams) Lookup(ctx context.Context, checkResults []ocr2keepers.CheckResult) []ocr2keepers.CheckResult {
+ lookups := map[int]*mercury.StreamsLookup{}
+ for i, checkResult := range checkResults {
+ s.buildResult(ctx, i, checkResult, checkResults, lookups)
+ }
+
+ var wg sync.WaitGroup
+ for i, lookup := range lookups {
+ wg.Add(1)
+ func(i int, lookup *mercury.StreamsLookup) {
+ s.threadCtrl.Go(func(ctx context.Context) {
+ s.doLookup(ctx, &wg, lookup, i, checkResults)
+ })
+ }(i, lookup)
+ }
+ wg.Wait()
+
+ // don't surface error to plugin bc StreamsLookup process should be self-contained.
+ return checkResults
+}
+
+// buildResult checks if the upkeep is allowed by Mercury and builds a streams lookup request from the check result
+func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keepers.CheckResult, checkResults []ocr2keepers.CheckResult, lookups map[int]*mercury.StreamsLookup) {
+ lookupLggr := s.lggr.With("where", "StreamsLookup")
+ if checkResult.IneligibilityReason != uint8(mercury.MercuryUpkeepFailureReasonTargetCheckReverted) {
+ // Streams Lookup only works when upkeep target check reverts
+ return
+ }
+
+ block := big.NewInt(int64(checkResult.Trigger.BlockNumber))
+ upkeepId := checkResult.UpkeepID
+
+ if s.mercuryConfig.Credentials() == nil {
+ lookupLggr.Errorf("at block %d upkeep %s tries to access mercury server but mercury credential is not configured", block, upkeepId)
+ return
+ }
+
+ // Try to decode the revert error into streams lookup format. User upkeeps can revert with any reason, see if they
+ // tried to call mercury
+ lookupLggr.Infof("at block %d upkeep %s trying to DecodeStreamsLookupRequest performData=%s", block, upkeepId, hexutil.Encode(checkResults[i].PerformData))
+ streamsLookupErr, err := s.packer.DecodeStreamsLookupRequest(checkResult.PerformData)
+ if err != nil {
+ lookupLggr.Debugf("at block %d upkeep %s DecodeStreamsLookupRequest failed: %v", block, upkeepId, err)
+ // user contract did not revert with StreamsLookup error
+ return
+ }
+ streamsLookupResponse := &mercury.StreamsLookup{StreamsLookupError: streamsLookupErr}
+
+ if len(streamsLookupResponse.Feeds) == 0 {
+ checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput)
+ lookupLggr.Debugf("at block %s upkeep %s has empty feeds array", block, upkeepId)
+ return
+ }
+
+ // mercury permission checking for v0.3 is done by mercury server
+ if streamsLookupResponse.IsMercuryV02() {
+ // check permission on the registry for mercury v0.2
+ opts := s.buildCallOpts(ctx, block)
+ if state, reason, retryable, allowed, err := s.allowedToUseMercury(opts, upkeepId.BigInt()); err != nil {
+ lookupLggr.Warnf("at block %s upkeep %s failed to query mercury allow list: %s", block, upkeepId, err)
+ checkResults[i].PipelineExecutionState = uint8(state)
+ checkResults[i].IneligibilityReason = uint8(reason)
+ checkResults[i].Retryable = retryable
+ return
+ } else if !allowed {
+ lookupLggr.Debugf("at block %d upkeep %s NOT allowed to query Mercury server", block, upkeepId)
+ checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonMercuryAccessNotAllowed)
+ return
+ }
+ } else if streamsLookupResponse.IsMercuryVersionUnkown() {
+ // if mercury version cannot be determined, set failure reason
+ lookupLggr.Debugf("at block %d upkeep %s NOT allowed to query Mercury server", block, upkeepId)
+ checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput)
+ return
+ }
+
+ streamsLookupResponse.UpkeepId = upkeepId.BigInt()
+ // the block here is exclusively used to call checkCallback at this block, not to be confused with the block number
+ // in the revert for mercury v0.2, which is denoted by time in the struct bc starting from v0.3, only timestamp will be supported
+ streamsLookupResponse.Block = uint64(block.Int64())
+ lookupLggr.Infof("at block %d upkeep %s DecodeStreamsLookupRequest feedKey=%s timeKey=%s feeds=%v time=%s extraData=%s", block, upkeepId, streamsLookupResponse.FeedParamKey, streamsLookupResponse.TimeParamKey, streamsLookupResponse.Feeds, streamsLookupResponse.Time, hexutil.Encode(streamsLookupResponse.ExtraData))
+ lookups[i] = streamsLookupResponse
+}
+
+func (s *streams) doLookup(ctx context.Context, wg *sync.WaitGroup, lookup *mercury.StreamsLookup, i int, checkResults []ocr2keepers.CheckResult) {
+ defer wg.Done()
+
+ state, reason, values, retryable, retryInterval, err := mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0*time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", lookup.FeedParamKey, lookup.TimeParamKey, lookup.Feeds)
+ pluginRetryKey := generatePluginRetryKey(checkResults[i].WorkID, lookup.Block)
+
+ if lookup.IsMercuryV02() {
+ state, reason, values, retryable, retryInterval, err = s.v02Client.DoRequest(ctx, lookup, pluginRetryKey)
+ } else if lookup.IsMercuryV03() {
+ state, reason, values, retryable, retryInterval, err = s.v03Client.DoRequest(ctx, lookup, pluginRetryKey)
+ }
+
+ if err != nil {
+ s.lggr.Errorf("at block %d upkeep %s requested time %s retryable %v retryInterval %s doMercuryRequest: %s", lookup.Block, lookup.UpkeepId, lookup.Time, retryable, retryInterval, err.Error())
+ checkResults[i].Retryable = retryable
+ checkResults[i].RetryInterval = retryInterval
+ checkResults[i].PipelineExecutionState = uint8(state)
+ checkResults[i].IneligibilityReason = uint8(reason)
+ return
+ }
+
+ for j, v := range values {
+ s.lggr.Infof("at block %d upkeep %s requested time %s doMercuryRequest values[%d]: %s", lookup.Block, lookup.UpkeepId, lookup.Time, j, hexutil.Encode(v))
+ }
+
+ state, retryable, mercuryBytes, err := s.checkCallback(ctx, values, lookup)
+ if err != nil {
+ s.lggr.Errorf("at block %d upkeep %s checkCallback err: %s", lookup.Block, lookup.UpkeepId, err.Error())
+ checkResults[i].Retryable = retryable
+ checkResults[i].PipelineExecutionState = uint8(state)
+ return
+ }
+ s.lggr.Infof("at block %d upkeep %s requested time %s checkCallback mercuryBytes: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(mercuryBytes))
+
+ unpackCallBackState, needed, performData, failureReason, _, err := s.packer.UnpackCheckCallbackResult(mercuryBytes)
+ if err != nil {
+ s.lggr.Errorf("at block %d upkeep %s requested time %s UnpackCheckCallbackResult err: %s", lookup.Block, lookup.UpkeepId, lookup.Time, err.Error())
+ checkResults[i].PipelineExecutionState = unpackCallBackState
+ return
+ }
+
+ if failureReason == uint8(mercury.MercuryUpkeepFailureReasonMercuryCallbackReverted) {
+ checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonMercuryCallbackReverted)
+ s.lggr.Debugf("at block %d upkeep %s requested time %s mercury callback reverts", lookup.Block, lookup.UpkeepId, lookup.Time)
+ return
+ }
+
+ if !needed {
+ checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonUpkeepNotNeeded)
+ s.lggr.Debugf("at block %d upkeep %s requested time %s callback reports upkeep not needed", lookup.Block, lookup.UpkeepId, lookup.Time)
+ return
+ }
+
+ checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonNone)
+ checkResults[i].Eligible = true
+ checkResults[i].PerformData = performData
+ s.lggr.Infof("at block %d upkeep %s requested time %s successful with perform data: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(performData))
+}
+
+// allowedToUseMercury retrieves upkeep's administrative offchain config and decode a mercuryEnabled bool to indicate if
+// this upkeep is allowed to use Mercury service.
+func (s *streams) allowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (state mercury.MercuryUpkeepState, reason mercury.MercuryUpkeepFailureReason, retryable bool, allow bool, err error) {
+ allowed, ok := s.mercuryConfig.IsUpkeepAllowed(upkeepId.String())
+ if ok {
+ return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonNone, false, allowed.(bool), nil
+ }
+
+ payload, err := s.packer.PackGetUpkeepPrivilegeConfig(upkeepId)
+ if err != nil {
+ // pack error, no retryable
+ s.lggr.Warnf("failed to pack getUpkeepPrivilegeConfig data for upkeepId %s: %s", upkeepId, err)
+
+ return mercury.PackUnpackDecodeFailed, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to pack upkeepId: %w", err)
+ }
+
+ var resultBytes hexutil.Bytes
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+
+ // call checkCallback function at the block which OCR3 has agreed upon
+ if err = s.client.CallContext(opts.Context, &resultBytes, "eth_call", args, hexutil.EncodeBig(opts.BlockNumber)); err != nil {
+ return mercury.RpcFlakyFailure, mercury.MercuryUpkeepFailureReasonNone, true, false, fmt.Errorf("failed to get upkeep privilege config: %v", err)
+ }
+
+ var upkeepPrivilegeConfigBytes []byte
+ upkeepPrivilegeConfigBytes, err = s.packer.UnpackGetUpkeepPrivilegeConfig(resultBytes)
+ if err != nil {
+ return mercury.PackUnpackDecodeFailed, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to get upkeep privilege config: %v", err)
+ }
+
+ if len(upkeepPrivilegeConfigBytes) == 0 {
+ s.mercuryConfig.SetUpkeepAllowed(upkeepId.String(), false, cache.DefaultExpiration)
+ return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonMercuryAccessNotAllowed, false, false, fmt.Errorf("upkeep privilege config is empty")
+ }
+
+ var privilegeConfig UpkeepPrivilegeConfig
+ if err = json.Unmarshal(upkeepPrivilegeConfigBytes, &privilegeConfig); err != nil {
+ return mercury.MercuryUnmarshalError, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to unmarshal privilege config: %v", err)
+ }
+
+ s.mercuryConfig.SetUpkeepAllowed(upkeepId.String(), privilegeConfig.MercuryEnabled, cache.DefaultExpiration)
+
+ return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonNone, false, privilegeConfig.MercuryEnabled, nil
+}
+
+func (s *streams) checkCallback(ctx context.Context, values [][]byte, lookup *mercury.StreamsLookup) (mercury.MercuryUpkeepState, bool, hexutil.Bytes, error) {
+ payload, err := s.abi.Pack("checkCallback", lookup.UpkeepId, values, lookup.ExtraData)
+ if err != nil {
+ return mercury.PackUnpackDecodeFailed, false, nil, err
+ }
+
+ var b hexutil.Bytes
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+
+ // call checkCallback function at the block which OCR3 has agreed upon
+ if err := s.client.CallContext(ctx, &b, "eth_call", args, hexutil.EncodeUint64(lookup.Block)); err != nil {
+ return mercury.RpcFlakyFailure, true, nil, err
+ }
+
+ return mercury.NoPipelineError, false, b, nil
+}
+
+func (s *streams) buildCallOpts(ctx context.Context, block *big.Int) *bind.CallOpts {
+ opts := bind.CallOpts{
+ Context: ctx,
+ }
+
+ if block == nil || block.Int64() == 0 {
+ if latestBlock := s.blockSubscriber.LatestBlock(); latestBlock != nil && latestBlock.Number != 0 {
+ opts.BlockNumber = big.NewInt(int64(latestBlock.Number))
+ }
+ } else {
+ opts.BlockNumber = block
+ }
+
+ return &opts
+}
+
+// generatePluginRetryKey returns a plugin retry cache key
+func generatePluginRetryKey(workID string, block uint64) string {
+ return workID + "|" + fmt.Sprintf("%d", block)
+}
+
+func (s *streams) Close() error {
+ return s.StopOnce("streams_lookup", func() error {
+ s.threadCtrl.Close()
+ return nil
+ })
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
new file mode 100644
index 0000000000..194d74febb
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
@@ -0,0 +1,726 @@
+package streams
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "math/big"
+ "net/http"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/require"
+
+ "github.com/stretchr/testify/assert"
+
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/stretchr/testify/mock"
+
+ evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
+ iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+ v02 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02"
+ v03 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
+)
+
+type MockMercuryConfigProvider struct {
+ mock.Mock
+}
+
+func (m *MockMercuryConfigProvider) Credentials() *models.MercuryCredentials {
+ mc := &models.MercuryCredentials{
+ LegacyURL: "https://google.old.com",
+ URL: "https://google.com",
+ Username: "FakeClientID",
+ Password: "FakeClientKey",
+ }
+ return mc
+}
+
+func (m *MockMercuryConfigProvider) IsUpkeepAllowed(s string) (interface{}, bool) {
+ args := m.Called(s)
+ return args.Get(0), args.Bool(1)
+}
+
+func (m *MockMercuryConfigProvider) SetUpkeepAllowed(s string, i interface{}, d time.Duration) {
+ m.Called(s, i, d)
+}
+
+func (m *MockMercuryConfigProvider) GetPluginRetry(s string) (interface{}, bool) {
+ args := m.Called(s)
+ return args.Get(0), args.Bool(1)
+}
+
+func (m *MockMercuryConfigProvider) SetPluginRetry(s string, i interface{}, d time.Duration) {
+ m.Called(s, i, d)
+}
+
+type MockBlockSubscriber struct {
+ mock.Mock
+}
+
+func (b *MockBlockSubscriber) LatestBlock() *ocr2keepers.BlockKey {
+ return nil
+}
+
+type MockHttpClient struct {
+ mock.Mock
+}
+
+func (mock *MockHttpClient) Do(req *http.Request) (*http.Response, error) {
+ args := mock.Called(req)
+ return args.Get(0).(*http.Response), args.Error(1)
+}
+
+type mockRegistry struct {
+ GetUpkeepPrivilegeConfigFn func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error)
+ CheckCallbackFn func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error)
+}
+
+func (r *mockRegistry) Address() common.Address {
+ return common.HexToAddress("0x6cA639822c6C241Fa9A7A6b5032F6F7F1C513CAD")
+}
+
+func (r *mockRegistry) GetUpkeepPrivilegeConfig(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return r.GetUpkeepPrivilegeConfigFn(opts, upkeepId)
+}
+
+func (r *mockRegistry) CheckCallback(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return r.CheckCallbackFn(opts, id, values, extraData)
+}
+
+// setups up a streams object for tests.
+func setupStreams(t *testing.T) *streams {
+ lggr := logger.TestLogger(t)
+ packer := encoding.NewAbiPacker()
+ mercuryConfig := new(MockMercuryConfigProvider)
+ blockSubscriber := new(MockBlockSubscriber)
+ registry := &mockRegistry{}
+ client := evmClientMocks.NewClient(t)
+
+ streams := NewStreamsLookup(
+ packer,
+ mercuryConfig,
+ blockSubscriber,
+ client,
+ registry,
+ lggr,
+ )
+ return streams
+}
+
+func TestStreams_CheckCallback(t *testing.T) {
+ upkeepId := big.NewInt(123456789)
+ bn := uint64(999)
+ bs := []byte{183, 114, 215, 10, 0, 0, 0, 0, 0, 0}
+ values := [][]byte{bs}
+ tests := []struct {
+ name string
+ lookup *mercury.StreamsLookup
+ values [][]byte
+ statusCode int
+
+ callbackResp []byte
+ callbackErr error
+
+ upkeepNeeded bool
+ performData []byte
+ wantErr assert.ErrorAssertionFunc
+
+ state mercury.MercuryUpkeepState
+ retryable bool
+ registry streamsRegistry
+ }{
+ {
+ name: "success - empty extra data",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"ETD-USD", "BTC-ETH"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(100),
+ ExtraData: []byte{48, 120, 48, 48},
+ },
+ UpkeepId: upkeepId,
+ Block: bn,
+ },
+ values: values,
+ statusCode: http.StatusOK,
+ callbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48, 120, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ upkeepNeeded: true,
+ performData: []byte{48, 120, 48, 48},
+ wantErr: assert.NoError,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{
+ UpkeepNeeded: true,
+ PerformData: []byte{48, 120, 48, 48},
+ }, nil
+ },
+ },
+ },
+ {
+ name: "success - with extra data",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(18952430),
+ // this is the address of precompile contract ArbSys(0x0000000000000000000000000000000000000064)
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ Block: bn,
+ },
+ values: values,
+ statusCode: http.StatusOK,
+ callbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ upkeepNeeded: true,
+ performData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ wantErr: assert.NoError,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{
+ UpkeepNeeded: true,
+ PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ }, nil
+ },
+ },
+ },
+ {
+ name: "failure - bad response",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"ETD-USD", "BTC-ETH"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(100),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48, 120, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ },
+ UpkeepId: upkeepId,
+ Block: bn,
+ },
+ values: values,
+ statusCode: http.StatusOK,
+ callbackResp: []byte{},
+ callbackErr: errors.New("bad response"),
+ wantErr: assert.Error,
+ state: mercury.RpcFlakyFailure,
+ retryable: true,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, errors.New("bad response")
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := setupStreams(t)
+ defer r.Close()
+ r.registry = tt.registry
+
+ client := new(evmClientMocks.Client)
+ s := setupStreams(t)
+ payload, err := s.abi.Pack("checkCallback", tt.lookup.UpkeepId, values, tt.lookup.ExtraData)
+ require.Nil(t, err)
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+ client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, hexutil.EncodeUint64(tt.lookup.Block)).Return(tt.callbackErr).
+ Run(func(args mock.Arguments) {
+ by := args.Get(1).(*hexutil.Bytes)
+ *by = tt.callbackResp
+ }).Once()
+ s.client = client
+
+ state, retryable, _, err := s.checkCallback(context.Background(), tt.values, tt.lookup)
+ tt.wantErr(t, err, fmt.Sprintf("Error asserion failed: %v", tt.name))
+ assert.Equal(t, tt.state, state)
+ assert.Equal(t, tt.retryable, retryable)
+ })
+ }
+}
+
+func TestStreams_AllowedToUseMercury(t *testing.T) {
+ upkeepId, ok := new(big.Int).SetString("71022726777042968814359024671382968091267501884371696415772139504780367423725", 10)
+ assert.True(t, ok, t.Name())
+ tests := []struct {
+ name string
+ cached bool
+ allowed bool
+ ethCallErr error
+ err error
+ state mercury.MercuryUpkeepState
+ reason mercury.MercuryUpkeepFailureReason
+ registry streamsRegistry
+ retryable bool
+ config []byte
+ }{
+ {
+ name: "success - allowed via cache",
+ cached: true,
+ allowed: true,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return nil, nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ {
+ name: "success - allowed via fetching privilege config",
+ allowed: true,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ {
+ name: "success - not allowed via cache",
+ cached: true,
+ allowed: false,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return nil, nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ {
+ name: "success - not allowed via fetching privilege config",
+ allowed: false,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":false}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ {
+ name: "failure - cannot unmarshal privilege config",
+ err: fmt.Errorf("failed to unmarshal privilege config: invalid character '\\x00' looking for beginning of value"),
+ state: mercury.MercuryUnmarshalError,
+ config: []byte{0, 1},
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ {
+ name: "failure - flaky RPC",
+ retryable: true,
+ err: fmt.Errorf("failed to get upkeep privilege config: flaky RPC"),
+ state: mercury.RpcFlakyFailure,
+ ethCallErr: fmt.Errorf("flaky RPC"),
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return nil, errors.New("flaky RPC")
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ {
+ name: "failure - empty upkeep privilege config",
+ err: fmt.Errorf("upkeep privilege config is empty"),
+ reason: mercury.MercuryUpkeepFailureReasonMercuryAccessNotAllowed,
+ config: []byte{},
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(``), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{}, nil
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ s := setupStreams(t)
+ defer s.Close()
+ s.registry = tt.registry
+
+ client := new(evmClientMocks.Client)
+ s.client = client
+
+ mc := new(MockMercuryConfigProvider)
+ mc.On("IsUpkeepAllowed", mock.Anything).Return(tt.allowed, tt.cached).Once()
+ mc.On("SetUpkeepAllowed", mock.Anything, mock.Anything, mock.Anything).Return().Once()
+ s.mercuryConfig = mc
+
+ if !tt.cached {
+ if tt.err != nil {
+ bContractCfg, err := s.abi.Methods["getUpkeepPrivilegeConfig"].Outputs.PackValues([]interface{}{tt.config})
+ require.Nil(t, err)
+
+ payload, err := s.abi.Pack("getUpkeepPrivilegeConfig", upkeepId)
+ require.Nil(t, err)
+
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+
+ client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, mock.AnythingOfType("string")).
+ Return(tt.ethCallErr).
+ Run(func(args mock.Arguments) {
+ b := args.Get(1).(*hexutil.Bytes)
+ *b = bContractCfg
+ }).Once()
+ } else {
+ cfg := UpkeepPrivilegeConfig{MercuryEnabled: tt.allowed}
+ bCfg, err := json.Marshal(cfg)
+ require.Nil(t, err)
+
+ bContractCfg, err := s.abi.Methods["getUpkeepPrivilegeConfig"].Outputs.PackValues([]interface{}{bCfg})
+ require.Nil(t, err)
+
+ payload, err := s.abi.Pack("getUpkeepPrivilegeConfig", upkeepId)
+ require.Nil(t, err)
+
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+
+ client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, mock.AnythingOfType("string")).Return(nil).
+ Run(func(args mock.Arguments) {
+ b := args.Get(1).(*hexutil.Bytes)
+ *b = bContractCfg
+ }).Once()
+ }
+ }
+
+ opts := &bind.CallOpts{
+ BlockNumber: big.NewInt(10),
+ }
+
+ state, reason, retryable, allowed, err := s.allowedToUseMercury(opts, upkeepId)
+ assert.Equal(t, tt.err, err)
+ assert.Equal(t, tt.allowed, allowed)
+ assert.Equal(t, tt.state, state)
+ assert.Equal(t, tt.reason, reason)
+ assert.Equal(t, tt.retryable, retryable)
+ })
+ }
+}
+
+func TestStreams_StreamsLookup(t *testing.T) {
+ upkeepId, ok := new(big.Int).SetString("71022726777042968814359024671382968091267501884371696415772139504780367423725", 10)
+ var upkeepIdentifier [32]byte
+ copy(upkeepIdentifier[:], upkeepId.Bytes())
+ assert.True(t, ok, t.Name())
+ blockNum := ocr2keepers.BlockNumber(37974374)
+ tests := []struct {
+ name string
+ input []ocr2keepers.CheckResult
+ blobs map[string]string
+ callbackResp []byte
+ expectedResults []ocr2keepers.CheckResult
+ callbackNeeded bool
+ extraData []byte
+ checkCallbackResp []byte
+ values [][]byte
+ cachedAdminCfg bool
+ hasError bool
+ hasPermission bool
+ v3 bool
+ registry streamsRegistry
+ }{
+ {
+ name: "success - happy path no cache",
+ input: []ocr2keepers.CheckResult{
+ {
+ PerformData: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: blockNum,
+ },
+ IneligibilityReason: uint8(mercury.MercuryUpkeepFailureReasonTargetCheckReverted),
+ },
+ },
+ blobs: map[string]string{
+ "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000": "0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3",
+ "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000": "0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d",
+ },
+ cachedAdminCfg: false,
+ extraData: hexutil.MustDecode("0x0000000000000000000000000000000000000064"),
+ callbackNeeded: true,
+ checkCallbackResp: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063a400000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ values: [][]byte{hexutil.MustDecode("0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3"), hexutil.MustDecode("0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d")},
+ expectedResults: []ocr2keepers.CheckResult{
+ {
+ Eligible: true,
+ PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: blockNum,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonNone),
+ },
+ },
+ hasPermission: true,
+ v3: false,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{
+ UpkeepNeeded: true,
+ PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ }, nil
+ },
+ },
+ },
+ {
+ name: "success - happy path no cache - v0.3",
+ input: []ocr2keepers.CheckResult{
+ {
+ PerformData: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000766656564494473000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: blockNum,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
+ },
+ },
+ blobs: map[string]string{
+ "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000": "0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3",
+ "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000": "0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d",
+ },
+ cachedAdminCfg: false,
+ extraData: hexutil.MustDecode("0x0000000000000000000000000000000000000064"),
+ callbackNeeded: true,
+ checkCallbackResp: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063a400000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ values: [][]byte{hexutil.MustDecode("0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3"), hexutil.MustDecode("0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d")},
+ expectedResults: []ocr2keepers.CheckResult{
+ {
+ Eligible: true,
+ PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: blockNum,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonNone),
+ },
+ },
+ hasPermission: true,
+ v3: true,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{
+ UpkeepNeeded: true,
+ PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
+ }, nil
+ },
+ },
+ },
+ {
+ name: "skip - failure reason is insufficient balance",
+ input: []ocr2keepers.CheckResult{
+ {
+ PerformData: []byte{},
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: 26046145,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance),
+ },
+ },
+ expectedResults: []ocr2keepers.CheckResult{
+ {
+ Eligible: false,
+ PerformData: []byte{},
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: 26046145,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance),
+ },
+ },
+ hasError: true,
+ registry: &mockRegistry{
+ GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
+ return []byte(`{"mercuryEnabled":true}`), nil
+ },
+ CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) {
+ return iregistry21.CheckCallback{
+ UpkeepNeeded: true,
+ PerformData: []byte{},
+ }, nil
+ },
+ },
+ },
+ {
+ name: "skip - invalid revert data",
+ input: []ocr2keepers.CheckResult{
+ {
+ PerformData: []byte{},
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: 26046145,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
+ },
+ },
+ expectedResults: []ocr2keepers.CheckResult{
+ {
+ Eligible: false,
+ PerformData: []byte{},
+ UpkeepID: upkeepIdentifier,
+ Trigger: ocr2keepers.Trigger{
+ BlockNumber: 26046145,
+ },
+ IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
+ },
+ },
+ hasError: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ s := setupStreams(t)
+ defer s.Close()
+ s.registry = tt.registry
+
+ client := new(evmClientMocks.Client)
+ s.client = client
+
+ mc := new(MockMercuryConfigProvider)
+ mc.On("IsUpkeepAllowed", mock.Anything).Return(tt.hasPermission, tt.cachedAdminCfg).Once()
+ mc.On("SetUpkeepAllowed", mock.Anything, mock.Anything, mock.Anything).Return().Once()
+ s.mercuryConfig = mc
+
+ if !tt.cachedAdminCfg && !tt.hasError {
+ cfg := UpkeepPrivilegeConfig{MercuryEnabled: tt.hasPermission}
+ bCfg, err := json.Marshal(cfg)
+ require.Nil(t, err)
+
+ bContractCfg, err := s.abi.Methods["getUpkeepPrivilegeConfig"].Outputs.PackValues([]interface{}{bCfg})
+ require.Nil(t, err)
+
+ payload, err := s.abi.Pack("getUpkeepPrivilegeConfig", upkeepId)
+ require.Nil(t, err)
+
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+
+ client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, mock.AnythingOfType("string")).Return(nil).
+ Run(func(args mock.Arguments) {
+ b := args.Get(1).(*hexutil.Bytes)
+ *b = bContractCfg
+ }).Once()
+ }
+
+ if len(tt.blobs) > 0 {
+ if tt.v3 {
+ hc03 := new(MockHttpClient)
+ v03HttpClient := v03.NewClient(s.mercuryConfig, hc03, s.threadCtrl, s.lggr)
+ s.v03Client = v03HttpClient
+
+ mr1 := v03.MercuryV03Response{
+ Reports: []v03.MercuryV03Report{{FullReport: tt.blobs["0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"]}, {FullReport: tt.blobs["0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"]}}}
+ b1, err := json.Marshal(mr1)
+ assert.Nil(t, err)
+ resp1 := &http.Response{
+ StatusCode: http.StatusOK,
+ Body: io.NopCloser(bytes.NewReader(b1)),
+ }
+ hc03.On("Do", mock.Anything).Return(resp1, nil).Once()
+ } else {
+ hc02 := new(MockHttpClient)
+ v02HttpClient := v02.NewClient(s.mercuryConfig, hc02, s.threadCtrl, s.lggr)
+ s.v02Client = v02HttpClient
+
+ mr1 := v02.MercuryV02Response{ChainlinkBlob: tt.blobs["0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"]}
+ b1, err := json.Marshal(mr1)
+ assert.Nil(t, err)
+ resp1 := &http.Response{
+ StatusCode: http.StatusOK,
+ Body: io.NopCloser(bytes.NewReader(b1)),
+ }
+ mr2 := v02.MercuryV02Response{ChainlinkBlob: tt.blobs["0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"]}
+ b2, err := json.Marshal(mr2)
+ assert.Nil(t, err)
+ resp2 := &http.Response{
+ StatusCode: http.StatusOK,
+ Body: io.NopCloser(bytes.NewReader(b2)),
+ }
+
+ hc02.On("Do", mock.MatchedBy(func(req *http.Request) bool {
+ return strings.Contains(req.URL.String(), "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000")
+ })).Return(resp2, nil).Once()
+
+ hc02.On("Do", mock.MatchedBy(func(req *http.Request) bool {
+ return strings.Contains(req.URL.String(), "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000")
+ })).Return(resp1, nil).Once()
+ }
+ }
+
+ if tt.callbackNeeded {
+ payload, err := s.abi.Pack("checkCallback", upkeepId, tt.values, tt.extraData)
+ require.Nil(t, err)
+ args := map[string]interface{}{
+ "to": s.registry.Address().Hex(),
+ "data": hexutil.Bytes(payload),
+ }
+ client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, hexutil.EncodeUint64(uint64(blockNum))).Return(nil).
+ Run(func(args mock.Arguments) {
+ b := args.Get(1).(*hexutil.Bytes)
+ *b = tt.checkCallbackResp
+ }).Once()
+ }
+
+ got := s.Lookup(context.Background(), tt.input)
+ assert.Equal(t, tt.expectedResults, got, tt.name)
+ })
+ }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_failure_reasons.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_failure_reasons.go
new file mode 100644
index 0000000000..261fc33bd4
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_failure_reasons.go
@@ -0,0 +1,15 @@
+package mercury
+
+type MercuryUpkeepFailureReason uint8
+
+const (
+ // upkeep failure onchain reasons
+ MercuryUpkeepFailureReasonNone MercuryUpkeepFailureReason = 0
+ MercuryUpkeepFailureReasonTargetCheckReverted MercuryUpkeepFailureReason = 3
+ MercuryUpkeepFailureReasonUpkeepNotNeeded MercuryUpkeepFailureReason = 4
+ MercuryUpkeepFailureReasonMercuryCallbackReverted MercuryUpkeepFailureReason = 7
+ // leaving a gap here for more onchain failure reasons in the future
+ // upkeep failure offchain reasons
+ MercuryUpkeepFailureReasonMercuryAccessNotAllowed MercuryUpkeepFailureReason = 32
+ MercuryUpkeepFailureReasonInvalidRevertDataInput MercuryUpkeepFailureReason = 34
+)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_states.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_states.go
new file mode 100644
index 0000000000..4e9cd14aee
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/upkeep_states.go
@@ -0,0 +1,14 @@
+package mercury
+
+type MercuryUpkeepState uint8
+
+const (
+ NoPipelineError MercuryUpkeepState = 0
+ RpcFlakyFailure MercuryUpkeepState = 3
+ MercuryFlakyFailure MercuryUpkeepState = 4
+ PackUnpackDecodeFailed MercuryUpkeepState = 5
+ MercuryUnmarshalError MercuryUpkeepState = 6
+ InvalidMercuryRequest MercuryUpkeepState = 7
+ InvalidMercuryResponse MercuryUpkeepState = 8 // this will only happen if Mercury server sends bad responses
+ UpkeepNotAuthorized MercuryUpkeepState = 9
+)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go
new file mode 100644
index 0000000000..55436937d1
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go
@@ -0,0 +1,203 @@
+package v02
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+
+ "github.com/avast/retry-go/v4"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+const (
+ mercuryPathV02 = "/client?" // only used to access mercury v0.2 server
+ retryDelay = 500 * time.Millisecond
+ totalAttempt = 3
+ contentTypeHeader = "Content-Type"
+ authorizationHeader = "Authorization"
+ timestampHeader = "X-Authorization-Timestamp"
+ signatureHeader = "X-Authorization-Signature-SHA256"
+)
+
+type MercuryV02Response struct {
+ ChainlinkBlob string `json:"chainlinkBlob"`
+}
+
+type client struct {
+ utils.StartStopOnce
+ mercuryConfig mercury.MercuryConfigProvider
+ httpClient mercury.HttpClient
+ threadCtrl utils.ThreadControl
+ lggr logger.Logger
+}
+
+func NewClient(mercuryConfig mercury.MercuryConfigProvider, httpClient mercury.HttpClient, threadCtrl utils.ThreadControl, lggr logger.Logger) *client {
+ return &client{
+ mercuryConfig: mercuryConfig,
+ httpClient: httpClient,
+ threadCtrl: threadCtrl,
+ lggr: lggr,
+ }
+}
+
+func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLookup, pluginRetryKey string) (mercury.MercuryUpkeepState, mercury.MercuryUpkeepFailureReason, [][]byte, bool, time.Duration, error) {
+ resultLen := len(streamsLookup.Feeds)
+ ch := make(chan mercury.MercuryData, resultLen)
+ if len(streamsLookup.Feeds) == 0 {
+ return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", streamsLookup.FeedParamKey, streamsLookup.TimeParamKey, streamsLookup.Feeds)
+ }
+ for i := range streamsLookup.Feeds {
+ // TODO (AUTO-7209): limit the number of concurrent requests
+ i := i
+ c.threadCtrl.Go(func(ctx context.Context) {
+ c.singleFeedRequest(ctx, ch, i, streamsLookup)
+ })
+ }
+
+ var reqErr error
+ var retryInterval time.Duration
+ results := make([][]byte, len(streamsLookup.Feeds))
+ retryable := true
+ allSuccess := true
+ // in v0.2, use the last execution error as the state, if no execution errors, state will be no error
+ state := mercury.NoPipelineError
+ for i := 0; i < resultLen; i++ {
+ m := <-ch
+ if m.Error != nil {
+ reqErr = errors.Join(reqErr, m.Error)
+ retryable = retryable && m.Retryable
+ allSuccess = false
+ if m.State != mercury.NoPipelineError {
+ state = mercury.MercuryUpkeepState(m.State)
+ }
+ continue
+ }
+ results[m.Index] = m.Bytes[0]
+ }
+ if retryable && !allSuccess {
+ retryInterval = mercury.CalculateRetryConfigFn(pluginRetryKey, c.mercuryConfig)
+ }
+ // only retry when not all successful AND none are not retryable
+ return state, mercury.MercuryUpkeepFailureReasonNone, results, retryable && !allSuccess, retryInterval, reqErr
+}
+
+func (c *client) singleFeedRequest(ctx context.Context, ch chan<- mercury.MercuryData, index int, sl *mercury.StreamsLookup) {
+ var httpRequest *http.Request
+ var err error
+
+ q := url.Values{
+ sl.FeedParamKey: {sl.Feeds[index]},
+ sl.TimeParamKey: {sl.Time.String()},
+ }
+ mercuryURL := c.mercuryConfig.Credentials().LegacyURL
+ reqUrl := fmt.Sprintf("%s%s%s", mercuryURL, mercuryPathV02, q.Encode())
+ c.lggr.Debugf("request URL for upkeep %s feed %s: %s", sl.UpkeepId.String(), sl.Feeds[index], reqUrl)
+
+ httpRequest, err = http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil)
+ if err != nil {
+ ch <- mercury.MercuryData{Index: index, Error: err, Retryable: false, State: mercury.InvalidMercuryRequest}
+ return
+ }
+
+ ts := time.Now().UTC().UnixMilli()
+ signature := mercury.GenerateHMACFn(http.MethodGet, mercuryPathV02+q.Encode(), []byte{}, c.mercuryConfig.Credentials().Username, c.mercuryConfig.Credentials().Password, ts)
+ httpRequest.Header.Set(contentTypeHeader, "application/json")
+ httpRequest.Header.Set(authorizationHeader, c.mercuryConfig.Credentials().Username)
+ httpRequest.Header.Set(timestampHeader, strconv.FormatInt(ts, 10))
+ httpRequest.Header.Set(signatureHeader, signature)
+
+ // in the case of multiple retries here, use the last attempt's data
+ state := mercury.NoPipelineError
+ retryable := false
+ sent := false
+ retryErr := retry.Do(
+ func() error {
+ var httpResponse *http.Response
+ var responseBody []byte
+ var blobBytes []byte
+
+ retryable = false
+ if httpResponse, err = c.httpClient.Do(httpRequest); err != nil {
+ c.lggr.Warnf("at block %s upkeep %s GET request fails for feed %s: %v", sl.Time.String(), sl.UpkeepId.String(), sl.Feeds[index], err)
+ retryable = true
+ state = mercury.MercuryFlakyFailure
+ return err
+ }
+ defer httpResponse.Body.Close()
+
+ if responseBody, err = io.ReadAll(httpResponse.Body); err != nil {
+ state = mercury.InvalidMercuryResponse
+ return err
+ }
+
+ switch httpResponse.StatusCode {
+ case http.StatusNotFound, http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
+ c.lggr.Warnf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.UpkeepId.String(), httpResponse.StatusCode, sl.Feeds[index])
+ retryable = true
+ state = mercury.MercuryFlakyFailure
+ return errors.New(strconv.FormatInt(int64(httpResponse.StatusCode), 10))
+ case http.StatusOK:
+ // continue
+ default:
+ state = mercury.InvalidMercuryRequest
+ return fmt.Errorf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.UpkeepId.String(), httpResponse.StatusCode, sl.Feeds[index])
+ }
+
+ c.lggr.Debugf("at block %s upkeep %s received status code %d from mercury v0.2 with BODY=%s", sl.Time.String(), sl.UpkeepId.String(), httpResponse.StatusCode, hexutil.Encode(responseBody))
+
+ var m MercuryV02Response
+ if err = json.Unmarshal(responseBody, &m); err != nil {
+ c.lggr.Warnf("at block %s upkeep %s failed to unmarshal body to MercuryV02Response for feed %s: %v", sl.Time.String(), sl.UpkeepId.String(), sl.Feeds[index], err)
+ state = mercury.MercuryUnmarshalError
+ return err
+ }
+ if blobBytes, err = hexutil.Decode(m.ChainlinkBlob); err != nil {
+ c.lggr.Warnf("at block %s upkeep %s failed to decode chainlinkBlob %s for feed %s: %v", sl.Time.String(), sl.UpkeepId.String(), m.ChainlinkBlob, sl.Feeds[index], err)
+ state = mercury.InvalidMercuryResponse
+ return err
+ }
+ ch <- mercury.MercuryData{
+ Index: index,
+ Bytes: [][]byte{blobBytes},
+ Retryable: false,
+ State: mercury.NoPipelineError,
+ }
+ sent = true
+ return nil
+ },
+ // only retry when the error is 404 Not Found, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
+ retry.RetryIf(func(err error) bool {
+ return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) || err.Error() == fmt.Sprintf("%d", http.StatusBadGateway) || err.Error() == fmt.Sprintf("%d", http.StatusServiceUnavailable) || err.Error() == fmt.Sprintf("%d", http.StatusGatewayTimeout)
+ }),
+ retry.Context(ctx),
+ retry.Delay(retryDelay),
+ retry.Attempts(totalAttempt),
+ )
+
+ if !sent {
+ ch <- mercury.MercuryData{
+ Index: index,
+ Bytes: [][]byte{},
+ Retryable: retryable,
+ Error: fmt.Errorf("failed to request feed for %s: %w", sl.Feeds[index], retryErr),
+ State: state,
+ }
+ }
+}
+
+func (c *client) Close() error {
+ return c.StopOnce("v02_request", func() error {
+ c.threadCtrl.Close()
+ return nil
+ })
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go
new file mode 100644
index 0000000000..17ef8515fd
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go
@@ -0,0 +1,468 @@
+package v02
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "io"
+ "math/big"
+ "net/http"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/patrickmn/go-cache"
+ "github.com/stretchr/testify/mock"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+)
+
+const (
+ defaultPluginRetryExpiration = 30 * time.Minute
+ cleanupInterval = 5 * time.Minute
+)
+
+type MockMercuryConfigProvider struct {
+ cache *cache.Cache
+ mock.Mock
+}
+
+func NewMockMercuryConfigProvider() *MockMercuryConfigProvider {
+ return &MockMercuryConfigProvider{
+ cache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
+ }
+}
+
+func (m *MockMercuryConfigProvider) Credentials() *models.MercuryCredentials {
+ mc := &models.MercuryCredentials{
+ LegacyURL: "https://google.old.com",
+ URL: "https://google.com",
+ Username: "FakeClientID",
+ Password: "FakeClientKey",
+ }
+ return mc
+}
+
+func (m *MockMercuryConfigProvider) IsUpkeepAllowed(s string) (interface{}, bool) {
+ args := m.Called(s)
+ return args.Get(0), args.Bool(1)
+}
+
+func (m *MockMercuryConfigProvider) SetUpkeepAllowed(s string, i interface{}, d time.Duration) {
+ m.Called(s, i, d)
+}
+
+func (m *MockMercuryConfigProvider) GetPluginRetry(s string) (interface{}, bool) {
+ if value, found := m.cache.Get(s); found {
+ return value, true
+ }
+
+ return nil, false
+}
+
+func (m *MockMercuryConfigProvider) SetPluginRetry(s string, i interface{}, d time.Duration) {
+ m.cache.Set(s, i, d)
+}
+
+type MockHttpClient struct {
+ mock.Mock
+}
+
+func (mock *MockHttpClient) Do(req *http.Request) (*http.Response, error) {
+ args := mock.Called(req)
+ return args.Get(0).(*http.Response), args.Error(1)
+}
+
+// setups up a client object for tests.
+func setupClient(t *testing.T) *client {
+ lggr := logger.TestLogger(t)
+ mockHttpClient := new(MockHttpClient)
+ mercuryConfig := NewMockMercuryConfigProvider()
+ threadCtl := utils.NewThreadControl()
+
+ client := NewClient(
+ mercuryConfig,
+ mockHttpClient,
+ threadCtl,
+ lggr,
+ )
+ return client
+}
+
+func TestV02_SingleFeedRequest(t *testing.T) {
+ upkeepId := big.NewInt(123456789)
+ tests := []struct {
+ name string
+ index int
+ lookup *mercury.StreamsLookup
+ blob string
+ statusCode int
+ lastStatusCode int
+ retryNumber int
+ retryable bool
+ errorMessage string
+ }{
+ {
+ name: "success - mercury responds in the first try",
+ index: 0,
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ blob: "0xab2123dc00000012",
+ },
+ {
+ name: "success - retry for 404",
+ index: 0,
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ blob: "0xab2123dcbabbad",
+ retryNumber: 1,
+ statusCode: http.StatusNotFound,
+ lastStatusCode: http.StatusOK,
+ },
+ {
+ name: "success - retry for 500",
+ index: 0,
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ blob: "0xab2123dcbbabad",
+ retryNumber: 2,
+ statusCode: http.StatusInternalServerError,
+ lastStatusCode: http.StatusOK,
+ },
+ {
+ name: "failure - returns retryable",
+ index: 0,
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ blob: "0xab2123dc",
+ retryNumber: totalAttempt,
+ statusCode: http.StatusNotFound,
+ retryable: true,
+ errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 404\n#2: 404\n#3: 404",
+ },
+ {
+ name: "failure - returns retryable and then non-retryable",
+ index: 0,
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ blob: "0xab2123dc",
+ retryNumber: 1,
+ statusCode: http.StatusNotFound,
+ lastStatusCode: http.StatusTooManyRequests,
+ errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 404\n#2: at block 123456 upkeep 123456789 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ },
+ {
+ name: "failure - returns not retryable",
+ index: 0,
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ blob: "0xab2123dc",
+ statusCode: http.StatusConflict,
+ errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 123456 upkeep 123456789 received status code 409 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := setupClient(t)
+ defer c.Close()
+ hc := new(MockHttpClient)
+
+ mr := MercuryV02Response{ChainlinkBlob: tt.blob}
+ b, err := json.Marshal(mr)
+ assert.Nil(t, err)
+
+ if tt.retryNumber == 0 {
+ if tt.errorMessage != "" {
+ resp := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ } else {
+ resp := &http.Response{
+ StatusCode: http.StatusOK,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ }
+ } else if tt.retryNumber > 0 && tt.retryNumber < totalAttempt {
+ retryResp := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(retryResp, nil).Times(tt.retryNumber)
+
+ resp := &http.Response{
+ StatusCode: tt.lastStatusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ } else {
+ resp := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Times(tt.retryNumber)
+ }
+ c.httpClient = hc
+
+ ch := make(chan mercury.MercuryData, 1)
+ c.singleFeedRequest(context.Background(), ch, tt.index, tt.lookup)
+
+ m := <-ch
+ assert.Equal(t, tt.index, m.Index)
+ assert.Equal(t, tt.retryable, m.Retryable)
+ if tt.retryNumber >= totalAttempt || tt.errorMessage != "" {
+ assert.Equal(t, tt.errorMessage, m.Error.Error())
+ assert.Equal(t, [][]byte{}, m.Bytes)
+ } else {
+ blobBytes, err := hexutil.Decode(tt.blob)
+ assert.Nil(t, err)
+ assert.Nil(t, m.Error)
+ assert.Equal(t, [][]byte{blobBytes}, m.Bytes)
+ }
+ })
+ }
+}
+
+func TestV02_DoMercuryRequestV02(t *testing.T) {
+ upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10)
+
+ tests := []struct {
+ name string
+ lookup *mercury.StreamsLookup
+ mockHttpStatusCode int
+ mockChainlinkBlobs []string
+ pluginRetries int
+ pluginRetryKey string
+ expectedValues [][]byte
+ expectedRetryable bool
+ expectedRetryInterval time.Duration
+ expectedError error
+ state mercury.MercuryUpkeepState
+ reason mercury.MercuryUpkeepFailureReason
+ }{
+ {
+ name: "success",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ mockHttpStatusCode: http.StatusOK,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{{0, 6, 109, 252, 209, 237, 45, 149, 177, 140, 148, 141, 188, 91, 214, 76, 104, 122, 254, 147, 228, 202, 125, 102, 61, 222, 193, 76, 32, 9, 10, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 128, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 69, 84, 72, 45, 85, 83, 68, 45, 65, 82, 66, 73, 84, 82, 85, 77, 45, 84, 69, 83, 84, 78, 69, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 216, 211, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 207, 11, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 155, 61, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 206, 116, 217, 250, 37, 42, 137, 131, 151, 110, 171, 96, 13, 199, 89, 12, 119, 141, 4, 129, 52, 48, 132, 27, 198, 231, 101, 195, 76, 216, 26, 22, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 96, 65, 43, 148, 229, 37, 202, 108, 237, 201, 245, 68, 253, 134, 247, 118, 6, 213, 47, 231, 49, 165, 208, 105, 219, 232, 54, 168, 191, 192, 251, 140, 145, 25, 99, 176, 174, 122, 20, 151, 31, 59, 70, 33, 191, 251, 128, 46, 240, 96, 83, 146, 185, 166, 200, 156, 127, 171, 29, 248, 99, 58, 90, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 69, 0, 194, 245, 33, 248, 63, 186, 94, 252, 43, 243, 239, 250, 174, 221, 228, 61, 10, 74, 223, 247, 133, 193, 33, 59, 113, 42, 58, 237, 13, 129, 87, 100, 42, 132, 50, 77, 176, 207, 150, 149, 235, 210, 119, 8, 212, 96, 142, 176, 51, 126, 13, 216, 123, 14, 67, 240, 250, 112, 199, 0, 217, 17}},
+ expectedRetryable: false,
+ expectedError: nil,
+ },
+ {
+ name: "failure - retryable and interval is 1s",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ mockHttpStatusCode: http.StatusInternalServerError,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{nil},
+ expectedRetryable: true,
+ pluginRetries: 0,
+ expectedRetryInterval: 1 * time.Second,
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
+ state: mercury.MercuryFlakyFailure,
+ },
+ {
+ name: "failure - retryable and interval is 5s",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ pluginRetries: 5,
+ mockHttpStatusCode: http.StatusInternalServerError,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{nil},
+ expectedRetryable: true,
+ expectedRetryInterval: 5 * time.Second,
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
+ state: mercury.MercuryFlakyFailure,
+ },
+ {
+ name: "failure - not retryable because there are many plugin retries already",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ pluginRetries: 10,
+ mockHttpStatusCode: http.StatusInternalServerError,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{nil},
+ expectedRetryable: true,
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
+ state: mercury.MercuryFlakyFailure,
+ },
+ {
+ name: "failure - not retryable",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ mockHttpStatusCode: http.StatusTooManyRequests,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{nil},
+ expectedRetryable: false,
+ expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 25880526 upkeep 88786950015966611018675766524283132478093844178961698330929478019253453382042 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"),
+ state: mercury.InvalidMercuryRequest,
+ },
+ {
+ name: "failure - no feeds",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIdHex,
+ Feeds: []string{},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ expectedValues: [][]byte{},
+ reason: mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput,
+ },
+ {
+ name: "failure - invalid revert data",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ expectedValues: [][]byte{},
+ reason: mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := setupClient(t)
+ defer c.Close()
+ if tt.pluginRetries != 0 {
+ c.mercuryConfig.SetPluginRetry(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
+ }
+ hc := new(MockHttpClient)
+
+ for _, blob := range tt.mockChainlinkBlobs {
+ mr := MercuryV02Response{ChainlinkBlob: blob}
+ b, err := json.Marshal(mr)
+ assert.Nil(t, err)
+
+ resp := &http.Response{
+ StatusCode: tt.mockHttpStatusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ if tt.expectedError != nil && tt.expectedRetryable || tt.pluginRetries > 0 {
+ hc.On("Do", mock.Anything).Return(resp, nil).Times(totalAttempt)
+ } else {
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ }
+ }
+ c.httpClient = hc
+
+ state, reason, values, retryable, retryInterval, reqErr := c.DoRequest(context.Background(), tt.lookup, tt.pluginRetryKey)
+ assert.Equal(t, tt.expectedValues, values)
+ assert.Equal(t, tt.expectedRetryable, retryable)
+ if retryable {
+ newRetries, _ := c.mercuryConfig.GetPluginRetry(tt.pluginRetryKey)
+ assert.Equal(t, tt.pluginRetries+1, newRetries.(int))
+ }
+ assert.Equal(t, tt.expectedRetryInterval, retryInterval)
+ assert.Equal(t, tt.state, state)
+ assert.Equal(t, tt.reason, reason)
+ if tt.expectedError != nil {
+ assert.True(t, strings.HasPrefix(reqErr.Error(), "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"))
+ }
+ })
+ }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go
new file mode 100644
index 0000000000..3697dca53c
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go
@@ -0,0 +1,252 @@
+package v03
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/avast/retry-go/v4"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+const (
+ mercuryBatchPathV03 = "/api/v1/reports/bulk?" // only used to access mercury v0.3 server
+ mercuryBatchPathV03BlockNumber = "/api/v1gmx/reports/bulk?" // only used to access mercury v0.3 server with blockNumber
+ retryDelay = 500 * time.Millisecond
+ totalAttempt = 3
+ contentTypeHeader = "Content-Type"
+ authorizationHeader = "Authorization"
+ timestampHeader = "X-Authorization-Timestamp"
+ signatureHeader = "X-Authorization-Signature-SHA256"
+ upkeepIDHeader = "X-Authorization-Upkeep-Id"
+)
+
+type MercuryV03Response struct {
+ Reports []MercuryV03Report `json:"reports"`
+}
+
+type MercuryV03Report struct {
+ FeedID string `json:"feedID"` // feed id in hex encoded
+ ValidFromTimestamp uint32 `json:"validFromTimestamp"`
+ ObservationsTimestamp uint32 `json:"observationsTimestamp"`
+ FullReport string `json:"fullReport"` // the actual hex encoded mercury report of this feed, can be sent to verifier
+}
+
+type client struct {
+ utils.StartStopOnce
+ mercuryConfig mercury.MercuryConfigProvider
+ httpClient mercury.HttpClient
+ threadCtrl utils.ThreadControl
+ lggr logger.Logger
+}
+
+func NewClient(mercuryConfig mercury.MercuryConfigProvider, httpClient mercury.HttpClient, threadCtrl utils.ThreadControl, lggr logger.Logger) *client {
+ return &client{
+ mercuryConfig: mercuryConfig,
+ httpClient: httpClient,
+ threadCtrl: threadCtrl,
+ lggr: lggr,
+ }
+}
+
+func (c *client) DoRequest(ctx context.Context, streamsLookup *mercury.StreamsLookup, pluginRetryKey string) (mercury.MercuryUpkeepState, mercury.MercuryUpkeepFailureReason, [][]byte, bool, time.Duration, error) {
+ resultLen := len(streamsLookup.Feeds)
+ ch := make(chan mercury.MercuryData, resultLen)
+ if len(streamsLookup.Feeds) == 0 {
+ return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", streamsLookup.FeedParamKey, streamsLookup.TimeParamKey, streamsLookup.Feeds)
+ }
+ resultLen = 1
+ c.threadCtrl.Go(func(ctx context.Context) {
+ c.multiFeedsRequest(ctx, ch, streamsLookup)
+ })
+
+ var reqErr error
+ var retryInterval time.Duration
+ results := make([][]byte, len(streamsLookup.Feeds))
+ retryable := true
+ allSuccess := true
+ state := mercury.NoPipelineError
+
+ for i := 0; i < resultLen; i++ {
+ m := <-ch
+ if m.Error != nil {
+ reqErr = errors.Join(reqErr, m.Error)
+ retryable = retryable && m.Retryable
+ allSuccess = false
+ if m.State != mercury.NoPipelineError {
+ state = m.State
+ }
+ continue
+ }
+ results = m.Bytes
+ }
+ // only retry when not all successful AND none are not retryable
+ if retryable && !allSuccess {
+ retryInterval = mercury.CalculateRetryConfigFn(pluginRetryKey, c.mercuryConfig)
+ }
+ // only retry when not all successful AND none are not retryable
+ return state, mercury.MercuryUpkeepFailureReasonNone, results, retryable && !allSuccess, retryInterval, reqErr
+}
+
+func (c *client) multiFeedsRequest(ctx context.Context, ch chan<- mercury.MercuryData, sl *mercury.StreamsLookup) {
+ // this won't work bc q.Encode() will encode commas as '%2C' but the server is strictly expecting a comma separated list
+ //q := url.Values{
+ // feedIDs: {strings.Join(sl.Feeds, ",")},
+ // timestamp: {sl.Time.String()},
+ //}
+
+ params := fmt.Sprintf("%s=%s&%s=%s", mercury.FeedIDs, strings.Join(sl.Feeds, ","), mercury.Timestamp, sl.Time.String())
+ batchPathV03 := mercuryBatchPathV03
+ if sl.IsMercuryUsingBatchPathV03() {
+ batchPathV03 = mercuryBatchPathV03BlockNumber
+ }
+ reqUrl := fmt.Sprintf("%s%s%s", c.mercuryConfig.Credentials().URL, batchPathV03, params)
+
+ c.lggr.Debugf("request URL for upkeep %s userId %s: %s", sl.UpkeepId.String(), c.mercuryConfig.Credentials().Username, reqUrl)
+
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil)
+ if err != nil {
+ ch <- mercury.MercuryData{Index: 0, Error: err, Retryable: false, State: mercury.InvalidMercuryRequest}
+ return
+ }
+
+ ts := time.Now().UTC().UnixMilli()
+ signature := mercury.GenerateHMACFn(http.MethodGet, mercuryBatchPathV03+params, []byte{}, c.mercuryConfig.Credentials().Username, c.mercuryConfig.Credentials().Password, ts)
+
+ req.Header.Set(contentTypeHeader, "application/json")
+ // username here is often referred to as user id
+ req.Header.Set(authorizationHeader, c.mercuryConfig.Credentials().Username)
+ req.Header.Set(timestampHeader, strconv.FormatInt(ts, 10))
+ req.Header.Set(signatureHeader, signature)
+ // mercury will inspect authorization headers above to make sure this user (in automation's context, this node) is eligible to access mercury
+ // and if it has an automation role. it will then look at this upkeep id to check if it has access to all the requested feeds.
+ req.Header.Set(upkeepIDHeader, sl.UpkeepId.String())
+
+ // in the case of multiple retries here, use the last attempt's data
+ state := mercury.NoPipelineError
+ retryable := false
+ sent := false
+ retryErr := retry.Do(
+ func() error {
+ retryable = false
+ resp, err := c.httpClient.Do(req)
+ if err != nil {
+ c.lggr.Warnf("at timestamp %s upkeep %s GET request fails from mercury v0.3: %v", sl.Time.String(), sl.UpkeepId.String(), err)
+ retryable = true
+ state = mercury.MercuryFlakyFailure
+ return err
+ }
+ defer resp.Body.Close()
+
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ retryable = false
+ state = mercury.InvalidMercuryResponse
+ return err
+ }
+
+ c.lggr.Infof("at timestamp %s upkeep %s received status code %d from mercury v0.3", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode)
+ switch resp.StatusCode {
+ case http.StatusUnauthorized:
+ retryable = false
+ state = mercury.UpkeepNotAuthorized
+ return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by unauthorized upkeep", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode)
+ case http.StatusBadRequest:
+ retryable = false
+ state = mercury.InvalidMercuryRequest
+ return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by invalid format of timestamp", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode)
+ case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
+ retryable = true
+ state = mercury.MercuryFlakyFailure
+ return fmt.Errorf("%d", resp.StatusCode)
+ case http.StatusPartialContent:
+ // TODO (AUTO-5044): handle response code 206 entirely with errors field parsing
+ c.lggr.Warnf("at timestamp %s upkeep %s requested [%s] feeds but mercury v0.3 server returned 206 status, treating it as 404 and retrying", sl.Time.String(), sl.UpkeepId.String(), sl.Feeds)
+ retryable = true
+ state = mercury.MercuryFlakyFailure
+ return fmt.Errorf("%d", http.StatusPartialContent)
+ case http.StatusOK:
+ // continue
+ default:
+ retryable = false
+ state = mercury.InvalidMercuryRequest
+ return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode)
+ }
+ c.lggr.Debugf("at block %s upkeep %s received status code %d from mercury v0.3 with BODY=%s", sl.Time.String(), sl.UpkeepId.String(), resp.StatusCode, hexutil.Encode(body))
+
+ var response MercuryV03Response
+ if err := json.Unmarshal(body, &response); err != nil {
+ c.lggr.Warnf("at timestamp %s upkeep %s failed to unmarshal body to MercuryV03Response from mercury v0.3: %v", sl.Time.String(), sl.UpkeepId.String(), err)
+ retryable = false
+ state = mercury.MercuryUnmarshalError
+ return err
+ }
+
+ // in v0.3, if some feeds are not available, the server will only return available feeds, but we need to make sure ALL feeds are retrieved before calling user contract
+ // hence, retry in this case. retry will help when we send a very new timestamp and reports are not yet generated
+ if len(response.Reports) != len(sl.Feeds) {
+ var receivedFeeds []string
+ for _, f := range response.Reports {
+ receivedFeeds = append(receivedFeeds, f.FeedID)
+ }
+ c.lggr.Warnf("at timestamp %s upkeep %s mercury v0.3 server returned 206 status with [%s] reports while we requested [%s] feeds, retrying", sl.Time.String(), sl.UpkeepId.String(), receivedFeeds, sl.Feeds)
+ retryable = true
+ state = mercury.MercuryFlakyFailure
+ return fmt.Errorf("%d", http.StatusNotFound)
+ }
+ var reportBytes [][]byte
+ for _, rsp := range response.Reports {
+ b, err := hexutil.Decode(rsp.FullReport)
+ if err != nil {
+ c.lggr.Warnf("at timestamp %s upkeep %s failed to decode reportBlob %s: %v", sl.Time.String(), sl.UpkeepId.String(), rsp.FullReport, err)
+ retryable = false
+ state = mercury.InvalidMercuryResponse
+ return err
+ }
+ reportBytes = append(reportBytes, b)
+ }
+ ch <- mercury.MercuryData{
+ Index: 0,
+ Bytes: reportBytes,
+ Retryable: false,
+ State: mercury.NoPipelineError,
+ }
+ sent = true
+ return nil
+ },
+ // only retry when the error is 206 Partial Content, 404 Not Found, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
+ retry.RetryIf(func(err error) bool {
+ return err.Error() == fmt.Sprintf("%d", http.StatusPartialContent) || err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) || err.Error() == fmt.Sprintf("%d", http.StatusBadGateway) || err.Error() == fmt.Sprintf("%d", http.StatusServiceUnavailable) || err.Error() == fmt.Sprintf("%d", http.StatusGatewayTimeout)
+ }),
+ retry.Context(ctx),
+ retry.Delay(retryDelay),
+ retry.Attempts(totalAttempt),
+ )
+
+ if !sent {
+ ch <- mercury.MercuryData{
+ Index: 0,
+ Bytes: [][]byte{},
+ Retryable: retryable,
+ Error: retryErr,
+ State: state,
+ }
+ }
+}
+
+func (c *client) Close() error {
+ return c.StopOnce("v03_request", func() error {
+ c.threadCtrl.Close()
+ return nil
+ })
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go
new file mode 100644
index 0000000000..bef2cdac58
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go
@@ -0,0 +1,536 @@
+package v03
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "io"
+ "math/big"
+ "net/http"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/patrickmn/go-cache"
+ "github.com/stretchr/testify/mock"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+)
+
+const (
+ defaultPluginRetryExpiration = 30 * time.Minute
+ cleanupInterval = 5 * time.Minute
+)
+
+type MockMercuryConfigProvider struct {
+ cache *cache.Cache
+ mock.Mock
+}
+
+func NewMockMercuryConfigProvider() *MockMercuryConfigProvider {
+ return &MockMercuryConfigProvider{
+ cache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
+ }
+}
+
+func (m *MockMercuryConfigProvider) Credentials() *models.MercuryCredentials {
+ mc := &models.MercuryCredentials{
+ LegacyURL: "https://google.old.com",
+ URL: "https://google.com",
+ Username: "FakeClientID",
+ Password: "FakeClientKey",
+ }
+ return mc
+}
+
+func (m *MockMercuryConfigProvider) IsUpkeepAllowed(s string) (interface{}, bool) {
+ args := m.Called(s)
+ return args.Get(0), args.Bool(1)
+}
+
+func (m *MockMercuryConfigProvider) SetUpkeepAllowed(s string, i interface{}, d time.Duration) {
+ m.Called(s, i, d)
+}
+
+func (m *MockMercuryConfigProvider) GetPluginRetry(s string) (interface{}, bool) {
+ if value, found := m.cache.Get(s); found {
+ return value, true
+ }
+
+ return nil, false
+}
+
+func (m *MockMercuryConfigProvider) SetPluginRetry(s string, i interface{}, d time.Duration) {
+ m.cache.Set(s, i, d)
+}
+
+type MockHttpClient struct {
+ mock.Mock
+}
+
+func (mock *MockHttpClient) Do(req *http.Request) (*http.Response, error) {
+ args := mock.Called(req)
+ return args.Get(0).(*http.Response), args.Error(1)
+}
+
+// setups up a client object for tests.
+func setupClient(t *testing.T) *client {
+ lggr := logger.TestLogger(t)
+ mockHttpClient := new(MockHttpClient)
+ mercuryConfig := NewMockMercuryConfigProvider()
+ threadCtl := utils.NewThreadControl()
+
+ client := NewClient(
+ mercuryConfig,
+ mockHttpClient,
+ threadCtl,
+ lggr,
+ )
+ return client
+}
+
+func TestV03_DoMercuryRequestV03(t *testing.T) {
+ upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10)
+
+ tests := []struct {
+ name string
+ lookup *mercury.StreamsLookup
+ mockHttpStatusCode int
+ mockChainlinkBlobs []string
+ pluginRetryKey string
+ expectedValues [][]byte
+ expectedRetryable bool
+ expectedRetryInterval time.Duration
+ expectedError error
+ state mercury.MercuryUpkeepState
+ reason mercury.MercuryUpkeepFailureReason
+ }{
+ {
+ name: "success v0.3",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(25880526),
+ ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ UpkeepId: upkeepId,
+ },
+ mockHttpStatusCode: http.StatusOK,
+ mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
+ expectedValues: [][]byte{{0, 6, 109, 252, 209, 237, 45, 149, 177, 140, 148, 141, 188, 91, 214, 76, 104, 122, 254, 147, 228, 202, 125, 102, 61, 222, 193, 76, 32, 9, 10, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 128, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 69, 84, 72, 45, 85, 83, 68, 45, 65, 82, 66, 73, 84, 82, 85, 77, 45, 84, 69, 83, 84, 78, 69, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 216, 211, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 207, 11, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 155, 61, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 206, 116, 217, 250, 37, 42, 137, 131, 151, 110, 171, 96, 13, 199, 89, 12, 119, 141, 4, 129, 52, 48, 132, 27, 198, 231, 101, 195, 76, 216, 26, 22, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 96, 65, 43, 148, 229, 37, 202, 108, 237, 201, 245, 68, 253, 134, 247, 118, 6, 213, 47, 231, 49, 165, 208, 105, 219, 232, 54, 168, 191, 192, 251, 140, 145, 25, 99, 176, 174, 122, 20, 151, 31, 59, 70, 33, 191, 251, 128, 46, 240, 96, 83, 146, 185, 166, 200, 156, 127, 171, 29, 248, 99, 58, 90, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 69, 0, 194, 245, 33, 248, 63, 186, 94, 252, 43, 243, 239, 250, 174, 221, 228, 61, 10, 74, 223, 247, 133, 193, 33, 59, 113, 42, 58, 237, 13, 129, 87, 100, 42, 132, 50, 77, 176, 207, 150, 149, 235, 210, 119, 8, 212, 96, 142, 176, 51, 126, 13, 216, 123, 14, 67, 240, 250, 112, 199, 0, 217, 17}},
+ expectedRetryable: false,
+ expectedError: nil,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := setupClient(t)
+ defer c.Close()
+ hc := mocks.NewHttpClient(t)
+
+ mr := MercuryV03Response{}
+ for i, blob := range tt.mockChainlinkBlobs {
+ r := MercuryV03Report{
+ FeedID: tt.lookup.Feeds[i],
+ ValidFromTimestamp: 0,
+ ObservationsTimestamp: 0,
+ FullReport: blob,
+ }
+ mr.Reports = append(mr.Reports, r)
+ }
+
+ b, err := json.Marshal(mr)
+ assert.Nil(t, err)
+ resp := &http.Response{
+ StatusCode: tt.mockHttpStatusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ if tt.expectedError != nil && tt.expectedRetryable {
+ hc.On("Do", mock.Anything).Return(resp, nil).Times(totalAttempt)
+ } else {
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ }
+ c.httpClient = hc
+
+ state, reason, values, retryable, retryInterval, reqErr := c.DoRequest(context.Background(), tt.lookup, tt.pluginRetryKey)
+
+ assert.Equal(t, tt.expectedValues, values)
+ assert.Equal(t, tt.expectedRetryable, retryable)
+ assert.Equal(t, tt.expectedRetryInterval, retryInterval)
+ assert.Equal(t, tt.state, state)
+ assert.Equal(t, tt.reason, reason)
+ if tt.expectedError != nil {
+ assert.Equal(t, tt.expectedError.Error(), reqErr.Error())
+ }
+ })
+ }
+}
+
+func TestV03_MultiFeedRequest(t *testing.T) {
+ upkeepId := big.NewInt(123456789)
+ tests := []struct {
+ name string
+ lookup *mercury.StreamsLookup
+ statusCode int
+ lastStatusCode int
+ pluginRetries int
+ pluginRetryKey string
+ retryNumber int
+ retryable bool
+ errorMessage string
+ firstResponse *MercuryV03Response
+ response *MercuryV03Response
+ }{
+ {
+ name: "success - mercury responds in the first try",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000016",
+ },
+ },
+ },
+ statusCode: http.StatusOK,
+ },
+ {
+ name: "success - mercury responds in the first try with blocknumber",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.BlockNumber,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000016",
+ },
+ },
+ },
+ statusCode: http.StatusOK,
+ },
+ {
+ name: "success - retry 206",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ firstResponse: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ },
+ },
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000019",
+ },
+ },
+ },
+ retryNumber: 1,
+ statusCode: http.StatusPartialContent,
+ lastStatusCode: http.StatusOK,
+ },
+ {
+ name: "success - retry for 500",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ retryNumber: 2,
+ statusCode: http.StatusInternalServerError,
+ lastStatusCode: http.StatusOK,
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000019",
+ },
+ },
+ },
+ },
+ {
+ name: "failure - fail to decode reportBlob",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "qerwiu", // invalid hex blob
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000016",
+ },
+ },
+ },
+ statusCode: http.StatusOK,
+ retryable: false,
+ errorMessage: "All attempts fail:\n#1: hex string without 0x prefix",
+ },
+ {
+ name: "failure - returns retryable with 1s plugin retry interval",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ retryNumber: totalAttempt,
+ statusCode: http.StatusInternalServerError,
+ retryable: true,
+ errorMessage: "All attempts fail:\n#1: 500\n#2: 500\n#3: 500",
+ },
+ {
+ name: "failure - returns retryable with 5s plugin retry interval",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ pluginRetries: 6,
+ retryNumber: totalAttempt,
+ statusCode: http.StatusInternalServerError,
+ retryable: true,
+ errorMessage: "All attempts fail:\n#1: 500\n#2: 500\n#3: 500",
+ },
+ {
+ name: "failure - returns retryable and then non-retryable",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ retryNumber: 1,
+ statusCode: http.StatusInternalServerError,
+ lastStatusCode: http.StatusUnauthorized,
+ errorMessage: "All attempts fail:\n#1: 500\n#2: at timestamp 123456 upkeep 123456789 received status code 401 from mercury v0.3, most likely this is caused by unauthorized upkeep",
+ },
+ {
+ name: "failure - returns status code 422 not retryable",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ statusCode: http.StatusUnprocessableEntity,
+ errorMessage: "All attempts fail:\n#1: at timestamp 123456 upkeep 123456789 received status code 422 from mercury v0.3",
+ },
+ {
+ name: "success - retry when reports length does not match feeds length",
+ lookup: &mercury.StreamsLookup{
+ StreamsLookupError: &mercury.StreamsLookupError{
+ FeedParamKey: mercury.FeedIDs,
+ Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
+ TimeParamKey: mercury.Timestamp,
+ Time: big.NewInt(123456),
+ },
+ UpkeepId: upkeepId,
+ },
+ firstResponse: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ },
+ },
+ response: &MercuryV03Response{
+ Reports: []MercuryV03Report{
+ {
+ FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123456,
+ ObservationsTimestamp: 123456,
+ FullReport: "0xab2123dc00000012",
+ },
+ {
+ FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
+ ValidFromTimestamp: 123458,
+ ObservationsTimestamp: 123458,
+ FullReport: "0xab2123dc00000019",
+ },
+ },
+ },
+ retryNumber: 1,
+ statusCode: http.StatusOK,
+ lastStatusCode: http.StatusOK,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := setupClient(t)
+ defer c.Close()
+ if tt.pluginRetries != 0 {
+ c.mercuryConfig.SetPluginRetry(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
+ }
+
+ hc := new(MockHttpClient)
+ b, err := json.Marshal(tt.response)
+ assert.Nil(t, err)
+
+ if tt.retryNumber == 0 {
+ resp := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ } else if tt.retryNumber < totalAttempt {
+ if tt.firstResponse != nil && tt.response != nil {
+ b0, err := json.Marshal(tt.firstResponse)
+ assert.Nil(t, err)
+ resp0 := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b0)),
+ }
+ b1, err := json.Marshal(tt.response)
+ assert.Nil(t, err)
+ resp1 := &http.Response{
+ StatusCode: tt.lastStatusCode,
+ Body: io.NopCloser(bytes.NewReader(b1)),
+ }
+ hc.On("Do", mock.Anything).Return(resp0, nil).Once().On("Do", mock.Anything).Return(resp1, nil).Once()
+ } else {
+ retryResp := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(retryResp, nil).Times(tt.retryNumber)
+
+ resp := &http.Response{
+ StatusCode: tt.lastStatusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Once()
+ }
+ } else {
+ resp := &http.Response{
+ StatusCode: tt.statusCode,
+ Body: io.NopCloser(bytes.NewReader(b)),
+ }
+ hc.On("Do", mock.Anything).Return(resp, nil).Times(tt.retryNumber)
+ }
+ c.httpClient = hc
+
+ ch := make(chan mercury.MercuryData, 1)
+ c.multiFeedsRequest(context.Background(), ch, tt.lookup)
+
+ m := <-ch
+ assert.Equal(t, 0, m.Index)
+ assert.Equal(t, tt.retryable, m.Retryable)
+ if tt.retryNumber >= totalAttempt || tt.errorMessage != "" {
+ assert.Equal(t, tt.errorMessage, m.Error.Error())
+ assert.Equal(t, [][]byte{}, m.Bytes)
+ } else {
+ assert.Nil(t, m.Error)
+ var reports [][]byte
+ for _, rsp := range tt.response.Reports {
+ b, _ := hexutil.Decode(rsp.FullReport)
+ reports = append(reports, b)
+ }
+ assert.Equal(t, reports, m.Bytes)
+ }
+ })
+ }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
index 73e2bc0a9c..252d2d91c7 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
@@ -17,9 +17,9 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
@@ -42,8 +42,6 @@ const (
// cleanupInterval decides when the expired items in cache will be deleted.
cleanupInterval = 5 * time.Minute
logTriggerRefreshBatchSize = 32
- totalFastPluginRetries = 5
- totalMediumPluginRetries = 10
)
var (
@@ -89,30 +87,34 @@ func NewEvmRegistry(
blockSub *BlockSubscriber,
finalityDepth uint32,
) *EvmRegistry {
+ mercuryConfig := &MercuryConfig{
+ cred: mc,
+ Abi: core.StreamsCompatibleABI,
+ AllowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
+ pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
+ }
+
+ hc := http.DefaultClient
+
return &EvmRegistry{
- ctx: context.Background(),
- threadCtrl: utils.NewThreadControl(),
- lggr: lggr.Named(RegistryServiceName),
- poller: client.LogPoller(),
- addr: addr,
- client: client.Client(),
- logProcessed: make(map[string]bool),
- registry: registry,
- abi: core.RegistryABI,
- active: al,
- packer: packer,
- headFunc: func(ocr2keepers.BlockKey) {},
- chLog: make(chan logpoller.Log, 1000),
- mercury: &MercuryConfig{
- cred: mc,
- abi: core.StreamsCompatibleABI,
- allowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
- pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
- },
- hc: http.DefaultClient,
+ ctx: context.Background(),
+ threadCtrl: utils.NewThreadControl(),
+ lggr: lggr.Named(RegistryServiceName),
+ poller: client.LogPoller(),
+ addr: addr,
+ client: client.Client(),
+ logProcessed: make(map[string]bool),
+ registry: registry,
+ abi: core.RegistryABI,
+ active: al,
+ packer: packer,
+ headFunc: func(ocr2keepers.BlockKey) {},
+ chLog: make(chan logpoller.Log, 1000),
+ hc: hc,
logEventProvider: logEventProvider,
bs: blockSub,
finalityDepth: finalityDepth,
+ streams: streams.NewStreamsLookup(packer, mercuryConfig, blockSub, client.Client(), registry, lggr),
}
}
@@ -128,15 +130,43 @@ var upkeepStateEvents = []common.Hash{
type MercuryConfig struct {
cred *models.MercuryCredentials
- abi abi.ABI
- // allowListCache stores the upkeeps privileges. In 2.1, this only includes a JSON bytes for allowed to use mercury
- allowListCache *cache.Cache
-
+ Abi abi.ABI
+ // AllowListCache stores the upkeeps privileges. In 2.1, this only includes a JSON bytes for allowed to use mercury
+ AllowListCache *cache.Cache
pluginRetryCache *cache.Cache
}
+func NewMercuryConfig(credentials *models.MercuryCredentials, abi abi.ABI) *MercuryConfig {
+ return &MercuryConfig{
+ cred: credentials,
+ Abi: abi,
+ AllowListCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
+ pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
+ }
+}
+
+func (c *MercuryConfig) Credentials() *models.MercuryCredentials {
+ return c.cred
+}
+
+func (c *MercuryConfig) IsUpkeepAllowed(k string) (interface{}, bool) {
+ return c.AllowListCache.Get(k)
+}
+
+func (c *MercuryConfig) SetUpkeepAllowed(k string, v interface{}, d time.Duration) {
+ c.AllowListCache.Set(k, v, d)
+}
+
+func (c *MercuryConfig) GetPluginRetry(k string) (interface{}, bool) {
+ return c.pluginRetryCache.Get(k)
+}
+
+func (c *MercuryConfig) SetPluginRetry(k string, v interface{}, d time.Duration) {
+ c.pluginRetryCache.Set(k, v, d)
+}
+
type EvmRegistry struct {
- services.StateMachine
+ utils.StartStopOnce
threadCtrl utils.ThreadControl
lggr logger.Logger
poller logpoller.LogPoller
@@ -158,6 +188,7 @@ type EvmRegistry struct {
bs *BlockSubscriber
logEventProvider logprovider.LogEventProvider
finalityDepth uint32
+ streams streams.Lookup
}
func (r *EvmRegistry) Name() string {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
index c9752ea14d..ad31c8feb0 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
@@ -70,7 +70,7 @@ func (r *EvmRegistry) doCheck(ctx context.Context, keys []ocr2keepers.UpkeepPayl
return
}
- upkeepResults = r.streamsLookup(ctx, upkeepResults)
+ upkeepResults = r.streams.Lookup(ctx, upkeepResults)
upkeepResults, err = r.simulatePerformUpkeeps(ctx, upkeepResults)
if err != nil {
@@ -104,7 +104,7 @@ func (r *EvmRegistry) getBlockHash(blockNumber *big.Int) (common.Hash, error) {
}
// verifyCheckBlock checks that the check block and hash are valid, returns the pipeline execution state and retryable
-func (r *EvmRegistry) verifyCheckBlock(_ context.Context, checkBlock, upkeepId *big.Int, checkHash common.Hash) (state encoding.PipelineExecutionState, retryable bool) {
+func (r *EvmRegistry) verifyCheckBlock(_ context.Context, checkBlock, upkeepId *big.Int, checkHash common.Hash) (state uint8, retryable bool) {
// verify check block number and hash are valid
h, ok := r.bs.queryBlocksMap(checkBlock.Int64())
// if this block number/hash combo exists in block subscriber, this check block and hash still exist on chain and are valid
@@ -127,7 +127,7 @@ func (r *EvmRegistry) verifyCheckBlock(_ context.Context, checkBlock, upkeepId *
}
// verifyLogExists checks that the log still exists on chain, returns failure reason, pipeline error, and retryable
-func (r *EvmRegistry) verifyLogExists(upkeepId *big.Int, p ocr2keepers.UpkeepPayload) (encoding.UpkeepFailureReason, encoding.PipelineExecutionState, bool) {
+func (r *EvmRegistry) verifyLogExists(upkeepId *big.Int, p ocr2keepers.UpkeepPayload) (uint8, uint8, bool) {
logBlockNumber := int64(p.Trigger.LogTriggerExtension.BlockNumber)
logBlockHash := common.BytesToHash(p.Trigger.LogTriggerExtension.BlockHash[:])
checkBlockHash := common.BytesToHash(p.Trigger.BlockHash[:])
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
index 5ea2bdc667..2e39892e47 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
@@ -4,12 +4,23 @@ import (
"context"
"fmt"
"math/big"
+ "strings"
"sync/atomic"
"testing"
+ "github.com/stretchr/testify/require"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/patrickmn/go-cache"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
+
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -81,7 +92,7 @@ func TestRegistry_VerifyCheckBlock(t *testing.T) {
payload ocr2keepers.UpkeepPayload
blocks map[int64]string
poller logpoller.LogPoller
- state encoding.PipelineExecutionState
+ state uint8
retryable bool
makeEthCall bool
}{
@@ -239,8 +250,8 @@ func TestRegistry_VerifyLogExists(t *testing.T) {
payload ocr2keepers.UpkeepPayload
blocks map[int64]string
makeEthCall bool
- reason encoding.UpkeepFailureReason
- state encoding.PipelineExecutionState
+ reason uint8
+ state uint8
retryable bool
ethCallErr error
receipt *types.Receipt
@@ -645,5 +656,44 @@ func TestRegistry_SimulatePerformUpkeeps(t *testing.T) {
assert.Equal(t, tc.err, err)
})
}
+}
+// setups up an evm registry for tests.
+func setupEVMRegistry(t *testing.T) *EvmRegistry {
+ lggr := logger.TestLogger(t)
+ addr := common.HexToAddress("0x6cA639822c6C241Fa9A7A6b5032F6F7F1C513CAD")
+ keeperRegistryABI, err := abi.JSON(strings.NewReader(i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMasterABI))
+ require.Nil(t, err, "need registry abi")
+ streamsLookupCompatibleABI, err := abi.JSON(strings.NewReader(streams_lookup_compatible_interface.StreamsLookupCompatibleInterfaceABI))
+ require.Nil(t, err, "need mercury abi")
+ var logPoller logpoller.LogPoller
+ mockReg := mocks.NewRegistry(t)
+ mockHttpClient := mocks.NewHttpClient(t)
+ client := evmClientMocks.NewClient(t)
+
+ r := &EvmRegistry{
+ lggr: lggr,
+ poller: logPoller,
+ addr: addr,
+ client: client,
+ logProcessed: make(map[string]bool),
+ registry: mockReg,
+ abi: keeperRegistryABI,
+ active: NewActiveUpkeepList(),
+ packer: encoding.NewAbiPacker(),
+ headFunc: func(ocr2keepers.BlockKey) {},
+ chLog: make(chan logpoller.Log, 1000),
+ mercury: &MercuryConfig{
+ cred: &models.MercuryCredentials{
+ LegacyURL: "https://google.old.com",
+ URL: "https://google.com",
+ Username: "FakeClientID",
+ Password: "FakeClientKey",
+ },
+ Abi: streamsLookupCompatibleABI,
+ AllowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
+ },
+ hc: mockHttpClient,
+ }
+ return r
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
deleted file mode 100644
index af7ff42b93..0000000000
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup.go
+++ /dev/null
@@ -1,642 +0,0 @@
-package evm
-
-import (
- "context"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "math/big"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/avast/retry-go/v4"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/patrickmn/go-cache"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
-
- "github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
-)
-
-const (
- applicationJson = "application/json"
- blockNumber = "blockNumber" // valid for v0.2
- feedIDs = "feedIDs" // valid for v0.3
- feedIdHex = "feedIdHex" // valid for v0.2
- headerAuthorization = "Authorization"
- headerContentType = "Content-Type"
- headerTimestamp = "X-Authorization-Timestamp"
- headerSignature = "X-Authorization-Signature-SHA256"
- headerUpkeepId = "X-Authorization-Upkeep-Id"
- mercuryPathV02 = "/client?" // only used to access mercury v0.2 server
- mercuryBatchPathV03 = "/api/v1/reports/bulk?" // only used to access mercury v0.3 server
- mercuryBatchPathV03BlockNumber = "/api/v1gmx/reports/bulk?" // only used to access mercury v0.3 server with blockNumber
- retryDelay = 500 * time.Millisecond
- timestamp = "timestamp" // valid for v0.3
- totalAttempt = 3
-)
-
-type StreamsLookup struct {
- *encoding.StreamsLookupError
- upkeepId *big.Int
- block uint64
-}
-
-// MercuryV02Response represents a JSON structure used by Mercury v0.2
-type MercuryV02Response struct {
- ChainlinkBlob string `json:"chainlinkBlob"`
-}
-
-// MercuryV03Response represents a JSON structure used by Mercury v0.3
-type MercuryV03Response struct {
- Reports []MercuryV03Report `json:"reports"`
-}
-
-type MercuryV03Report struct {
- FeedID string `json:"feedID"` // feed id in hex encoded
- ValidFromTimestamp uint32 `json:"validFromTimestamp"`
- ObservationsTimestamp uint32 `json:"observationsTimestamp"`
- FullReport string `json:"fullReport"` // the actual hex encoded mercury report of this feed, can be sent to verifier
-}
-
-type MercuryData struct {
- Index int
- Error error
- Retryable bool
- Bytes [][]byte
- State encoding.PipelineExecutionState
-}
-
-// UpkeepPrivilegeConfig represents the administrative offchain config for each upkeep. It can be set by s_upkeepPrivilegeManager
-// role on the registry. Upkeeps allowed to use Mercury server will have this set to true.
-type UpkeepPrivilegeConfig struct {
- MercuryEnabled bool `json:"mercuryEnabled"`
-}
-
-// streamsLookup looks through check upkeep results looking for any that need off chain lookup
-func (r *EvmRegistry) streamsLookup(ctx context.Context, checkResults []ocr2keepers.CheckResult) []ocr2keepers.CheckResult {
- lggr := r.lggr.With("where", "StreamsLookup")
- lookups := map[int]*StreamsLookup{}
- for i, res := range checkResults {
- if res.IneligibilityReason != uint8(encoding.UpkeepFailureReasonTargetCheckReverted) {
- // Streams Lookup only works when upkeep target check reverts
- continue
- }
-
- block := big.NewInt(int64(res.Trigger.BlockNumber))
- upkeepId := res.UpkeepID
-
- // Try to decode the revert error into streams lookup format. User upkeeps can revert with any reason, see if they
- // tried to call mercury
- lggr.Infof("at block %d upkeep %s trying to DecodeStreamsLookupRequest performData=%s", block, upkeepId, hexutil.Encode(checkResults[i].PerformData))
- streamsLookupErr, err := r.packer.DecodeStreamsLookupRequest(res.PerformData)
- if err != nil {
- lggr.Debugf("at block %d upkeep %s DecodeStreamsLookupRequest failed: %v", block, upkeepId, err)
- // user contract did not revert with StreamsLookup error
- continue
- }
- l := &StreamsLookup{StreamsLookupError: streamsLookupErr}
- if r.mercury.cred == nil {
- lggr.Errorf("at block %d upkeep %s tries to access mercury server but mercury credential is not configured", block, upkeepId)
- continue
- }
-
- if len(l.Feeds) == 0 {
- checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonInvalidRevertDataInput)
- lggr.Debugf("at block %s upkeep %s has empty feeds array", block, upkeepId)
- continue
- }
- // mercury permission checking for v0.3 is done by mercury server
- if l.FeedParamKey == feedIdHex && l.TimeParamKey == blockNumber {
- // check permission on the registry for mercury v0.2
- opts := r.buildCallOpts(ctx, block)
- state, reason, retryable, allowed, err := r.allowedToUseMercury(opts, upkeepId.BigInt())
- if err != nil {
- lggr.Warnf("at block %s upkeep %s failed to query mercury allow list: %s", block, upkeepId, err)
- checkResults[i].PipelineExecutionState = uint8(state)
- checkResults[i].IneligibilityReason = uint8(reason)
- checkResults[i].Retryable = retryable
- continue
- }
-
- if !allowed {
- lggr.Debugf("at block %d upkeep %s NOT allowed to query Mercury server", block, upkeepId)
- checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonMercuryAccessNotAllowed)
- continue
- }
- } else if l.FeedParamKey != feedIDs {
- // if mercury version cannot be determined, set failure reason
- lggr.Debugf("at block %d upkeep %s NOT allowed to query Mercury server", block, upkeepId)
- checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonInvalidRevertDataInput)
- continue
- }
-
- l.upkeepId = upkeepId.BigInt()
- // the block here is exclusively used to call checkCallback at this block, not to be confused with the block number
- // in the revert for mercury v0.2, which is denoted by time in the struct bc starting from v0.3, only timestamp will be supported
- l.block = uint64(block.Int64())
- lggr.Infof("at block %d upkeep %s DecodeStreamsLookupRequest feedKey=%s timeKey=%s feeds=%v time=%s extraData=%s", block, upkeepId, l.FeedParamKey, l.TimeParamKey, l.Feeds, l.Time, hexutil.Encode(l.ExtraData))
- lookups[i] = l
- }
-
- var wg sync.WaitGroup
-
- for i, lookup := range lookups {
- wg.Add(1)
- func(i int, lookup *StreamsLookup) {
- r.threadCtrl.Go(func(ctx context.Context) {
- r.doLookup(ctx, &wg, lookup, i, checkResults, lggr)
- })
- }(i, lookup)
-
- }
-
- wg.Wait()
-
- // don't surface error to plugin bc StreamsLookup process should be self-contained.
- return checkResults
-}
-
-func (r *EvmRegistry) doLookup(ctx context.Context, wg *sync.WaitGroup, lookup *StreamsLookup, i int, checkResults []ocr2keepers.CheckResult, lggr logger.Logger) {
- defer wg.Done()
-
- state, reason, values, retryable, ri, err := r.doMercuryRequest(ctx, lookup, generatePluginRetryKey(checkResults[i].WorkID, lookup.block), lggr)
- if err != nil {
- lggr.Errorf("upkeep %s retryable %v retryInterval %s doMercuryRequest: %s", lookup.upkeepId, retryable, ri, err.Error())
- checkResults[i].Retryable = retryable
- checkResults[i].RetryInterval = ri
- checkResults[i].PipelineExecutionState = uint8(state)
- checkResults[i].IneligibilityReason = uint8(reason)
- return
- }
-
- for j, v := range values {
- lggr.Infof("upkeep %s doMercuryRequest values[%d]: %s", lookup.upkeepId, j, hexutil.Encode(v))
- }
-
- state, retryable, mercuryBytes, err := r.checkCallback(ctx, values, lookup)
- if err != nil {
- lggr.Errorf("at block %d upkeep %s checkCallback err: %s", lookup.block, lookup.upkeepId, err.Error())
- checkResults[i].Retryable = retryable
- checkResults[i].PipelineExecutionState = uint8(state)
- return
- }
- lggr.Infof("checkCallback mercuryBytes=%s", hexutil.Encode(mercuryBytes))
-
- state, needed, performData, failureReason, _, err := r.packer.UnpackCheckCallbackResult(mercuryBytes)
- if err != nil {
- lggr.Errorf("at block %d upkeep %s UnpackCheckCallbackResult err: %s", lookup.block, lookup.upkeepId, err.Error())
- checkResults[i].PipelineExecutionState = uint8(state)
- return
- }
-
- if failureReason == uint8(encoding.UpkeepFailureReasonMercuryCallbackReverted) {
- checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonMercuryCallbackReverted)
- lggr.Debugf("at block %d upkeep %s mercury callback reverts", lookup.block, lookup.upkeepId)
- return
- }
-
- if !needed {
- checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonUpkeepNotNeeded)
- lggr.Debugf("at block %d upkeep %s callback reports upkeep not needed", lookup.block, lookup.upkeepId)
- return
- }
-
- checkResults[i].IneligibilityReason = uint8(encoding.UpkeepFailureReasonNone)
- checkResults[i].Eligible = true
- checkResults[i].PerformData = performData
- lggr.Infof("at block %d upkeep %s successful with perform data: %s", lookup.block, lookup.upkeepId, hexutil.Encode(performData))
-}
-
-// allowedToUseMercury retrieves upkeep's administrative offchain config and decode a mercuryEnabled bool to indicate if
-// this upkeep is allowed to use Mercury service.
-func (r *EvmRegistry) allowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (state encoding.PipelineExecutionState, reason encoding.UpkeepFailureReason, retryable bool, allow bool, err error) {
- allowed, ok := r.mercury.allowListCache.Get(upkeepId.String())
- if ok {
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonNone, false, allowed.(bool), nil
- }
-
- payload, err := r.packer.PackGetUpkeepPrivilegeConfig(upkeepId)
- if err != nil {
- // pack error, no retryable
- r.lggr.Warnf("failed to pack getUpkeepPrivilegeConfig data for upkeepId %s: %s", upkeepId, err)
-
- return encoding.PackUnpackDecodeFailed, encoding.UpkeepFailureReasonNone, false, false, fmt.Errorf("failed to pack upkeepId: %w", err)
- }
-
- var resultBytes hexutil.Bytes
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
-
- // call checkCallback function at the block which OCR3 has agreed upon
- err = r.client.CallContext(opts.Context, &resultBytes, "eth_call", args, hexutil.EncodeBig(opts.BlockNumber))
- if err != nil {
- return encoding.RpcFlakyFailure, encoding.UpkeepFailureReasonNone, true, false, fmt.Errorf("failed to get upkeep privilege config: %v", err)
- }
-
- cfg, err := r.packer.UnpackGetUpkeepPrivilegeConfig(resultBytes)
- if err != nil {
- return encoding.PackUnpackDecodeFailed, encoding.UpkeepFailureReasonNone, false, false, fmt.Errorf("failed to get upkeep privilege config: %v", err)
- }
-
- if len(cfg) == 0 {
- r.mercury.allowListCache.Set(upkeepId.String(), false, cache.DefaultExpiration)
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonMercuryAccessNotAllowed, false, false, fmt.Errorf("upkeep privilege config is empty")
- }
-
- var privilegeConfig UpkeepPrivilegeConfig
- if err := json.Unmarshal(cfg, &privilegeConfig); err != nil {
- return encoding.MercuryUnmarshalError, encoding.UpkeepFailureReasonNone, false, false, fmt.Errorf("failed to unmarshal privilege config: %v", err)
- }
-
- r.mercury.allowListCache.Set(upkeepId.String(), privilegeConfig.MercuryEnabled, cache.DefaultExpiration)
-
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonNone, false, privilegeConfig.MercuryEnabled, nil
-}
-
-func (r *EvmRegistry) checkCallback(ctx context.Context, values [][]byte, lookup *StreamsLookup) (encoding.PipelineExecutionState, bool, hexutil.Bytes, error) {
- payload, err := r.abi.Pack("checkCallback", lookup.upkeepId, values, lookup.ExtraData)
- if err != nil {
- return encoding.PackUnpackDecodeFailed, false, nil, err
- }
-
- var b hexutil.Bytes
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
-
- // call checkCallback function at the block which OCR3 has agreed upon
- err = r.client.CallContext(ctx, &b, "eth_call", args, hexutil.EncodeUint64(lookup.block))
- if err != nil {
- return encoding.RpcFlakyFailure, true, nil, err
- }
- return encoding.NoPipelineError, false, b, nil
-}
-
-// doMercuryRequest sends requests to Mercury API to retrieve mercury data.
-func (r *EvmRegistry) doMercuryRequest(ctx context.Context, sl *StreamsLookup, prk string, lggr logger.Logger) (encoding.PipelineExecutionState, encoding.UpkeepFailureReason, [][]byte, bool, time.Duration, error) {
- var isMercuryV03 bool
- resultLen := len(sl.Feeds)
- ch := make(chan MercuryData, resultLen)
- if len(sl.Feeds) == 0 {
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
- }
- if sl.FeedParamKey == feedIdHex && sl.TimeParamKey == blockNumber {
- // only mercury v0.2
- for i := range sl.Feeds {
- i := i
- r.threadCtrl.Go(func(ctx context.Context) {
- r.singleFeedRequest(ctx, ch, i, sl, lggr)
- })
- }
- } else if sl.FeedParamKey == feedIDs {
- // only mercury v0.3
- resultLen = 1
- isMercuryV03 = true
- ch = make(chan MercuryData, resultLen)
- r.threadCtrl.Go(func(ctx context.Context) {
- r.multiFeedsRequest(ctx, ch, sl, lggr)
- })
- } else {
- return encoding.NoPipelineError, encoding.UpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0 * time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", sl.FeedParamKey, sl.TimeParamKey, sl.Feeds)
- }
-
- var reqErr error
- var ri time.Duration
- results := make([][]byte, len(sl.Feeds))
- retryable := true
- allSuccess := true
- // in v0.2, use the last execution error as the state, if no execution errors, state will be no error
- state := encoding.NoPipelineError
- for i := 0; i < resultLen; i++ {
- m := <-ch
- if m.Error != nil {
- reqErr = errors.Join(reqErr, m.Error)
- retryable = retryable && m.Retryable
- allSuccess = false
- if m.State != encoding.NoPipelineError {
- state = m.State
- }
- continue
- }
- if isMercuryV03 {
- results = m.Bytes
- } else {
- results[m.Index] = m.Bytes[0]
- }
- }
- if retryable && !allSuccess {
- ri = r.calculateRetryConfig(prk)
- }
- // only retry when not all successful AND none are not retryable
- return state, encoding.UpkeepFailureReasonNone, results, retryable && !allSuccess, ri, reqErr
-}
-
-// singleFeedRequest sends a v0.2 Mercury request for a single feed report.
-func (r *EvmRegistry) singleFeedRequest(ctx context.Context, ch chan<- MercuryData, index int, sl *StreamsLookup, lggr logger.Logger) {
- q := url.Values{
- sl.FeedParamKey: {sl.Feeds[index]},
- sl.TimeParamKey: {sl.Time.String()},
- }
- mercuryURL := r.mercury.cred.LegacyURL
- reqUrl := fmt.Sprintf("%s%s%s", mercuryURL, mercuryPathV02, q.Encode())
- lggr.Debugf("request URL for upkeep %s feed %s: %s", sl.upkeepId.String(), sl.Feeds[index], reqUrl)
-
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil)
- if err != nil {
- ch <- MercuryData{Index: index, Error: err, Retryable: false, State: encoding.InvalidMercuryRequest}
- return
- }
-
- ts := time.Now().UTC().UnixMilli()
- signature := r.generateHMAC(http.MethodGet, mercuryPathV02+q.Encode(), []byte{}, r.mercury.cred.Username, r.mercury.cred.Password, ts)
- req.Header.Set(headerContentType, applicationJson)
- req.Header.Set(headerAuthorization, r.mercury.cred.Username)
- req.Header.Set(headerTimestamp, strconv.FormatInt(ts, 10))
- req.Header.Set(headerSignature, signature)
-
- // in the case of multiple retries here, use the last attempt's data
- state := encoding.NoPipelineError
- retryable := false
- sent := false
- retryErr := retry.Do(
- func() error {
- retryable = false
- resp, err1 := r.hc.Do(req)
- if err1 != nil {
- lggr.Warnf("at block %s upkeep %s GET request fails for feed %s: %v", sl.Time.String(), sl.upkeepId.String(), sl.Feeds[index], err1)
- retryable = true
- state = encoding.MercuryFlakyFailure
- return err1
- }
- defer func(Body io.ReadCloser) {
- err = Body.Close()
- if err != nil {
- lggr.Warnf("failed to close mercury response Body: %s", err)
- }
- }(resp.Body)
-
- body, err1 := io.ReadAll(resp.Body)
- if err1 != nil {
- retryable = false
- state = encoding.InvalidMercuryResponse
- return err1
- }
-
- if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusInternalServerError || resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusServiceUnavailable || resp.StatusCode == http.StatusGatewayTimeout {
- lggr.Warnf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, sl.Feeds[index])
- retryable = true
- state = encoding.MercuryFlakyFailure
- return errors.New(strconv.FormatInt(int64(resp.StatusCode), 10))
- } else if resp.StatusCode != http.StatusOK {
- retryable = false
- state = encoding.InvalidMercuryRequest
- return fmt.Errorf("at block %s upkeep %s received status code %d for feed %s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, sl.Feeds[index])
- }
-
- lggr.Debugf("at block %s upkeep %s received status code %d from mercury v0.2 with BODY=%s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, hexutil.Encode(body))
-
- var m MercuryV02Response
- err1 = json.Unmarshal(body, &m)
- if err1 != nil {
- lggr.Warnf("at block %s upkeep %s failed to unmarshal body to MercuryV02Response for feed %s: %v", sl.Time.String(), sl.upkeepId.String(), sl.Feeds[index], err1)
- retryable = false
- state = encoding.MercuryUnmarshalError
- return err1
- }
- blobBytes, err1 := hexutil.Decode(m.ChainlinkBlob)
- if err1 != nil {
- lggr.Warnf("at block %s upkeep %s failed to decode chainlinkBlob %s for feed %s: %v", sl.Time.String(), sl.upkeepId.String(), m.ChainlinkBlob, sl.Feeds[index], err1)
- retryable = false
- state = encoding.InvalidMercuryResponse
- return err1
- }
- ch <- MercuryData{
- Index: index,
- Bytes: [][]byte{blobBytes},
- Retryable: false,
- State: encoding.NoPipelineError,
- }
- sent = true
- return nil
- },
- // only retry when the error is 404 Not Found, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
- retry.RetryIf(func(err error) bool {
- return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) || err.Error() == fmt.Sprintf("%d", http.StatusBadGateway) || err.Error() == fmt.Sprintf("%d", http.StatusServiceUnavailable) || err.Error() == fmt.Sprintf("%d", http.StatusGatewayTimeout)
- }),
- retry.Context(ctx),
- retry.Delay(retryDelay),
- retry.Attempts(totalAttempt))
-
- if !sent {
- md := MercuryData{
- Index: index,
- Bytes: [][]byte{},
- Retryable: retryable,
- Error: fmt.Errorf("failed to request feed for %s: %w", sl.Feeds[index], retryErr),
- State: state,
- }
- ch <- md
- }
-}
-
-// multiFeedsRequest sends a Mercury v0.3 request for a multi-feed report
-func (r *EvmRegistry) multiFeedsRequest(ctx context.Context, ch chan<- MercuryData, sl *StreamsLookup, lggr logger.Logger) {
- // this won't work bc q.Encode() will encode commas as '%2C' but the server is strictly expecting a comma separated list
- //q := url.Values{
- // feedIDs: {strings.Join(sl.Feeds, ",")},
- // timestamp: {sl.Time.String()},
- //}
- params := fmt.Sprintf("%s=%s&%s=%s", feedIDs, strings.Join(sl.Feeds, ","), sl.TimeParamKey, sl.Time.String())
- batchPathV03 := mercuryBatchPathV03
- if sl.TimeParamKey == blockNumber {
- batchPathV03 = mercuryBatchPathV03BlockNumber
- }
- reqUrl := fmt.Sprintf("%s%s%s", r.mercury.cred.URL, batchPathV03, params)
- lggr.Debugf("request URL for upkeep %s userId %s: %s", sl.upkeepId.String(), r.mercury.cred.Username, reqUrl)
-
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil)
- if err != nil {
- ch <- MercuryData{Index: 0, Error: err, Retryable: false, State: encoding.InvalidMercuryRequest}
- return
- }
-
- ts := time.Now().UTC().UnixMilli()
- signature := r.generateHMAC(http.MethodGet, batchPathV03+params, []byte{}, r.mercury.cred.Username, r.mercury.cred.Password, ts)
- req.Header.Set(headerContentType, applicationJson)
- // username here is often referred to as user id
- req.Header.Set(headerAuthorization, r.mercury.cred.Username)
- req.Header.Set(headerTimestamp, strconv.FormatInt(ts, 10))
- req.Header.Set(headerSignature, signature)
- // mercury will inspect authorization headers above to make sure this user (in automation's context, this node) is eligible to access mercury
- // and if it has an automation role. it will then look at this upkeep id to check if it has access to all the requested feeds.
- req.Header.Set(headerUpkeepId, sl.upkeepId.String())
-
- // in the case of multiple retries here, use the last attempt's data
- state := encoding.NoPipelineError
- retryable := false
- sent := false
- retryErr := retry.Do(
- func() error {
- retryable = false
- resp, err1 := r.hc.Do(req)
- if err1 != nil {
- lggr.Warnf("at timestamp %s upkeep %s GET request fails from mercury v0.3: %v", sl.Time.String(), sl.upkeepId.String(), err1)
- retryable = true
- state = encoding.MercuryFlakyFailure
- return err1
- }
- defer func(Body io.ReadCloser) {
- err = Body.Close()
- if err != nil {
- lggr.Warnf("failed to close mercury response Body: %s", err)
- }
- }(resp.Body)
-
- body, err1 := io.ReadAll(resp.Body)
- if err1 != nil {
- retryable = false
- state = encoding.InvalidMercuryResponse
- return err1
- }
-
- lggr.Infof("at timestamp %s upkeep %s received status code %d from mercury v0.3", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode)
- if resp.StatusCode == http.StatusUnauthorized {
- retryable = false
- state = encoding.UpkeepNotAuthorized
- return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by unauthorized upkeep", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode)
- } else if resp.StatusCode == http.StatusBadRequest {
- retryable = false
- state = encoding.InvalidMercuryRequest
- return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3 with message: %s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, string(body))
- } else if resp.StatusCode == http.StatusInternalServerError || resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusServiceUnavailable || resp.StatusCode == http.StatusGatewayTimeout {
- retryable = true
- state = encoding.MercuryFlakyFailure
- return fmt.Errorf("%d", resp.StatusCode)
- } else if resp.StatusCode == http.StatusPartialContent {
- // TODO (AUTO-5044): handle response code 206 entirely with errors field parsing
- lggr.Warnf("at timestamp %s upkeep %s requested [%s] feeds but mercury v0.3 server returned 206 status, treating it as 404 and retrying", sl.Time.String(), sl.upkeepId.String(), sl.Feeds)
- retryable = true
- state = encoding.MercuryFlakyFailure
- return fmt.Errorf("%d", http.StatusPartialContent)
- } else if resp.StatusCode != http.StatusOK {
- retryable = false
- state = encoding.InvalidMercuryRequest
- return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode)
- }
-
- lggr.Debugf("at block %s upkeep %s received status code %d from mercury v0.3 with BODY=%s", sl.Time.String(), sl.upkeepId.String(), resp.StatusCode, hexutil.Encode(body))
-
- var response MercuryV03Response
- err1 = json.Unmarshal(body, &response)
- if err1 != nil {
- lggr.Warnf("at timestamp %s upkeep %s failed to unmarshal body to MercuryV03Response from mercury v0.3: %v", sl.Time.String(), sl.upkeepId.String(), err1)
- retryable = false
- state = encoding.MercuryUnmarshalError
- return err1
- }
- // in v0.3, if some feeds are not available, the server will only return available feeds, but we need to make sure ALL feeds are retrieved before calling user contract
- // hence, retry in this case. retry will help when we send a very new timestamp and reports are not yet generated
- if len(response.Reports) != len(sl.Feeds) {
- var receivedFeeds []string
- for _, f := range response.Reports {
- receivedFeeds = append(receivedFeeds, f.FeedID)
- }
- lggr.Warnf("at timestamp %s upkeep %s mercury v0.3 server returned 206 status with [%s] reports while we requested [%s] feeds, retrying", sl.Time.String(), sl.upkeepId.String(), receivedFeeds, sl.Feeds)
- retryable = true
- state = encoding.MercuryFlakyFailure
- return fmt.Errorf("%d", http.StatusNotFound)
- }
- var reportBytes [][]byte
- for _, rsp := range response.Reports {
- b, err := hexutil.Decode(rsp.FullReport)
- if err != nil {
- lggr.Warnf("at timestamp %s upkeep %s failed to decode reportBlob %s: %v", sl.Time.String(), sl.upkeepId.String(), rsp.FullReport, err)
- retryable = false
- state = encoding.InvalidMercuryResponse
- return err
- }
- reportBytes = append(reportBytes, b)
- }
- ch <- MercuryData{
- Index: 0,
- Bytes: reportBytes,
- Retryable: false,
- State: encoding.NoPipelineError,
- }
- sent = true
- return nil
- },
- // only retry when the error is 206 Partial Content, 404 Not Found, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
- retry.RetryIf(func(err error) bool {
- return err.Error() == fmt.Sprintf("%d", http.StatusPartialContent) || err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) || err.Error() == fmt.Sprintf("%d", http.StatusBadGateway) || err.Error() == fmt.Sprintf("%d", http.StatusServiceUnavailable) || err.Error() == fmt.Sprintf("%d", http.StatusGatewayTimeout)
- }),
- retry.Context(ctx),
- retry.Delay(retryDelay),
- retry.Attempts(totalAttempt))
-
- if !sent {
- md := MercuryData{
- Index: 0,
- Bytes: [][]byte{},
- Retryable: retryable,
- Error: retryErr,
- State: state,
- }
- ch <- md
- }
-}
-
-// generateHMAC calculates a user HMAC for Mercury server authentication.
-func (r *EvmRegistry) generateHMAC(method string, path string, body []byte, clientId string, secret string, ts int64) string {
- bodyHash := sha256.New()
- bodyHash.Write(body)
- hashString := fmt.Sprintf("%s %s %s %s %d",
- method,
- path,
- hex.EncodeToString(bodyHash.Sum(nil)),
- clientId,
- ts)
- signedMessage := hmac.New(sha256.New, []byte(secret))
- signedMessage.Write([]byte(hashString))
- userHmac := hex.EncodeToString(signedMessage.Sum(nil))
- return userHmac
-}
-
-// calculateRetryConfig returns plugin retry interval based on how many times plugin has retried this work
-func (r *EvmRegistry) calculateRetryConfig(prk string) time.Duration {
- var ri time.Duration
- var retries int
- totalAttempts, ok := r.mercury.pluginRetryCache.Get(prk)
- if ok {
- retries = totalAttempts.(int)
- if retries < totalFastPluginRetries {
- ri = 1 * time.Second
- } else if retries < totalMediumPluginRetries {
- ri = 5 * time.Second
- }
- // if the core node has retried totalMediumPluginRetries times, do not set retry interval and plugin will use
- // the default interval
- } else {
- ri = 1 * time.Second
- }
- r.mercury.pluginRetryCache.Set(prk, retries+1, cache.DefaultExpiration)
- return ri
-}
-
-// generatePluginRetryKey returns a plugin retry cache key
-func generatePluginRetryKey(workID string, block uint64) string {
- return workID + "|" + fmt.Sprintf("%d", block)
-}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
deleted file mode 100644
index 145d701454..0000000000
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/streams_lookup_test.go
+++ /dev/null
@@ -1,1354 +0,0 @@
-package evm
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "io"
- "math/big"
- "net/http"
- "strings"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/patrickmn/go-cache"
- "github.com/pkg/errors"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
-
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
-)
-
-// setups up an evm registry for tests.
-func setupEVMRegistry(t *testing.T) *EvmRegistry {
- lggr := logger.TestLogger(t)
- addr := common.HexToAddress("0x6cA639822c6C241Fa9A7A6b5032F6F7F1C513CAD")
- keeperRegistryABI, err := abi.JSON(strings.NewReader(i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMasterABI))
- require.Nil(t, err, "need registry abi")
- streamsLookupCompatibleABI, err := abi.JSON(strings.NewReader(streams_lookup_compatible_interface.StreamsLookupCompatibleInterfaceABI))
- require.Nil(t, err, "need mercury abi")
- var logPoller logpoller.LogPoller
- mockReg := mocks.NewRegistry(t)
- mockHttpClient := mocks.NewHttpClient(t)
- client := evmClientMocks.NewClient(t)
-
- r := &EvmRegistry{
- lggr: lggr,
- poller: logPoller,
- addr: addr,
- client: client,
- logProcessed: make(map[string]bool),
- registry: mockReg,
- abi: keeperRegistryABI,
- active: NewActiveUpkeepList(),
- packer: encoding.NewAbiPacker(),
- headFunc: func(ocr2keepers.BlockKey) {},
- chLog: make(chan logpoller.Log, 1000),
- mercury: &MercuryConfig{
- cred: &models.MercuryCredentials{
- LegacyURL: "https://google.old.com",
- URL: "https://google.com",
- Username: "FakeClientID",
- Password: "FakeClientKey",
- },
- abi: streamsLookupCompatibleABI,
- allowListCache: cache.New(defaultAllowListExpiration, cleanupInterval),
- pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval),
- },
- hc: mockHttpClient,
- threadCtrl: utils.NewThreadControl(),
- }
- return r
-}
-
-func TestEvmRegistry_StreamsLookup(t *testing.T) {
- upkeepId, ok := new(big.Int).SetString("71022726777042968814359024671382968091267501884371696415772139504780367423725", 10)
- var upkeepIdentifier [32]byte
- copy(upkeepIdentifier[:], upkeepId.Bytes())
- assert.True(t, ok, t.Name())
- blockNum := ocr2keepers.BlockNumber(37974374)
- tests := []struct {
- name string
- input []ocr2keepers.CheckResult
- blobs map[string]string
- callbackResp []byte
- expectedResults []ocr2keepers.CheckResult
- callbackNeeded bool
- extraData []byte
- checkCallbackResp []byte
- values [][]byte
- cachedAdminCfg bool
- hasError bool
- hasPermission bool
- v3 bool
- }{
- {
- name: "success - happy path no cache",
- input: []ocr2keepers.CheckResult{
- {
- PerformData: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: blockNum,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
- },
- },
- blobs: map[string]string{
- "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000": "0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3",
- "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000": "0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d",
- },
- cachedAdminCfg: false,
- extraData: hexutil.MustDecode("0x0000000000000000000000000000000000000064"),
- callbackNeeded: true,
- checkCallbackResp: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063a400000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- values: [][]byte{hexutil.MustDecode("0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3"), hexutil.MustDecode("0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d")},
- expectedResults: []ocr2keepers.CheckResult{
- {
- Eligible: true,
- PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: blockNum,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonNone),
- },
- },
- hasPermission: true,
- },
- {
- name: "success - happy path no cache - v0.3",
- input: []ocr2keepers.CheckResult{
- {
- PerformData: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000766656564494473000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: blockNum,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
- },
- },
- blobs: map[string]string{
- "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000": "0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3",
- "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000": "0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d",
- },
- cachedAdminCfg: false,
- extraData: hexutil.MustDecode("0x0000000000000000000000000000000000000064"),
- callbackNeeded: true,
- checkCallbackResp: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063a400000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- values: [][]byte{hexutil.MustDecode("0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3"), hexutil.MustDecode("0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d")},
- expectedResults: []ocr2keepers.CheckResult{
- {
- Eligible: true,
- PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"),
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: blockNum,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonNone),
- },
- },
- hasPermission: true,
- v3: true,
- },
- {
- name: "skip - failure reason is insufficient balance",
- input: []ocr2keepers.CheckResult{
- {
- PerformData: []byte{},
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: 26046145,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance),
- },
- },
- expectedResults: []ocr2keepers.CheckResult{
- {
- Eligible: false,
- PerformData: []byte{},
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: 26046145,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance),
- },
- },
- hasError: true,
- },
- {
- name: "skip - invalid revert data",
- input: []ocr2keepers.CheckResult{
- {
- PerformData: []byte{},
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: 26046145,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
- },
- },
- expectedResults: []ocr2keepers.CheckResult{
- {
- Eligible: false,
- PerformData: []byte{},
- UpkeepID: upkeepIdentifier,
- Trigger: ocr2keepers.Trigger{
- BlockNumber: 26046145,
- },
- IneligibilityReason: uint8(encoding.UpkeepFailureReasonTargetCheckReverted),
- },
- },
- hasError: true,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- r := setupEVMRegistry(t)
- defer r.Close()
- client := new(evmClientMocks.Client)
- r.client = client
-
- if !tt.cachedAdminCfg && !tt.hasError {
- cfg := UpkeepPrivilegeConfig{MercuryEnabled: tt.hasPermission}
- bCfg, err := json.Marshal(cfg)
- require.Nil(t, err)
-
- bContractCfg, err := r.abi.Methods["getUpkeepPrivilegeConfig"].Outputs.PackValues([]interface{}{bCfg})
- require.Nil(t, err)
-
- payload, err := r.abi.Pack("getUpkeepPrivilegeConfig", upkeepId)
- require.Nil(t, err)
-
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
-
- client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, mock.AnythingOfType("string")).Return(nil).
- Run(func(args mock.Arguments) {
- b := args.Get(1).(*hexutil.Bytes)
- *b = bContractCfg
- }).Once()
- }
-
- if len(tt.blobs) > 0 {
- if tt.v3 {
- hc := mocks.NewHttpClient(t)
- mr1 := MercuryV03Response{
- Reports: []MercuryV03Report{{FullReport: tt.blobs["0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"]}, {FullReport: tt.blobs["0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"]}}}
- b1, err := json.Marshal(mr1)
- assert.Nil(t, err)
- resp1 := &http.Response{
- StatusCode: http.StatusOK,
- Body: io.NopCloser(bytes.NewReader(b1)),
- }
- hc.On("Do", mock.Anything).Return(resp1, nil).Once()
- r.hc = hc
- } else {
- hc := mocks.NewHttpClient(t)
- mr1 := MercuryV02Response{ChainlinkBlob: tt.blobs["0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"]}
- b1, err := json.Marshal(mr1)
- assert.Nil(t, err)
- resp1 := &http.Response{
- StatusCode: http.StatusOK,
- Body: io.NopCloser(bytes.NewReader(b1)),
- }
- mr2 := MercuryV02Response{ChainlinkBlob: tt.blobs["0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"]}
- b2, err := json.Marshal(mr2)
- assert.Nil(t, err)
- resp2 := &http.Response{
- StatusCode: http.StatusOK,
- Body: io.NopCloser(bytes.NewReader(b2)),
- }
- hc.On("Do", mock.MatchedBy(func(req *http.Request) bool {
- return strings.Contains(req.URL.String(), "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000")
- })).Return(resp2, nil).Once()
-
- hc.On("Do", mock.MatchedBy(func(req *http.Request) bool {
- return strings.Contains(req.URL.String(), "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000")
- })).Return(resp1, nil).Once()
- r.hc = hc
- }
- }
-
- if tt.callbackNeeded {
- payload, err := r.abi.Pack("checkCallback", upkeepId, tt.values, tt.extraData)
- require.Nil(t, err)
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
- client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, hexutil.EncodeUint64(uint64(blockNum))).Return(nil).
- Run(func(args mock.Arguments) {
- b := args.Get(1).(*hexutil.Bytes)
- *b = tt.checkCallbackResp
- }).Once()
- }
-
- got := r.streamsLookup(context.Background(), tt.input)
- assert.Equal(t, tt.expectedResults, got, tt.name)
- })
- }
-}
-
-func TestEvmRegistry_AllowedToUseMercury(t *testing.T) {
- upkeepId, ok := new(big.Int).SetString("71022726777042968814359024671382968091267501884371696415772139504780367423725", 10)
- assert.True(t, ok, t.Name())
- tests := []struct {
- name string
- cached bool
- allowed bool
- ethCallErr error
- err error
- state encoding.PipelineExecutionState
- reason encoding.UpkeepFailureReason
- retryable bool
- config []byte
- }{
- {
- name: "success - allowed via cache",
- cached: true,
- allowed: true,
- },
- {
- name: "success - allowed via fetching privilege config",
- allowed: true,
- },
- {
- name: "success - not allowed via cache",
- cached: true,
- allowed: false,
- },
- {
- name: "success - not allowed via fetching privilege config",
- allowed: false,
- },
- {
- name: "failure - cannot unmarshal privilege config",
- err: fmt.Errorf("failed to unmarshal privilege config: invalid character '\\x00' looking for beginning of value"),
- state: encoding.MercuryUnmarshalError,
- config: []byte{0, 1},
- },
- {
- name: "failure - flaky RPC",
- retryable: true,
- err: fmt.Errorf("failed to get upkeep privilege config: flaky RPC"),
- state: encoding.RpcFlakyFailure,
- ethCallErr: fmt.Errorf("flaky RPC"),
- },
- {
- name: "failure - empty upkeep privilege config",
- err: fmt.Errorf("upkeep privilege config is empty"),
- reason: encoding.UpkeepFailureReasonMercuryAccessNotAllowed,
- config: []byte{},
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- r := setupEVMRegistry(t)
- defer r.Close()
-
- client := new(evmClientMocks.Client)
- r.client = client
-
- if tt.cached {
- r.mercury.allowListCache.Set(upkeepId.String(), tt.allowed, cache.DefaultExpiration)
- } else {
- if tt.err != nil {
- bContractCfg, err := r.abi.Methods["getUpkeepPrivilegeConfig"].Outputs.PackValues([]interface{}{tt.config})
- require.Nil(t, err)
-
- payload, err := r.abi.Pack("getUpkeepPrivilegeConfig", upkeepId)
- require.Nil(t, err)
-
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
-
- client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, mock.AnythingOfType("string")).
- Return(tt.ethCallErr).
- Run(func(args mock.Arguments) {
- b := args.Get(1).(*hexutil.Bytes)
- *b = bContractCfg
- }).Once()
- } else {
- cfg := UpkeepPrivilegeConfig{MercuryEnabled: tt.allowed}
- bCfg, err := json.Marshal(cfg)
- require.Nil(t, err)
-
- bContractCfg, err := r.abi.Methods["getUpkeepPrivilegeConfig"].Outputs.PackValues([]interface{}{bCfg})
- require.Nil(t, err)
-
- payload, err := r.abi.Pack("getUpkeepPrivilegeConfig", upkeepId)
- require.Nil(t, err)
-
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
-
- client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, mock.AnythingOfType("string")).Return(nil).
- Run(func(args mock.Arguments) {
- b := args.Get(1).(*hexutil.Bytes)
- *b = bContractCfg
- }).Once()
- }
- }
-
- opts := &bind.CallOpts{
- BlockNumber: big.NewInt(10),
- }
-
- state, reason, retryable, allowed, err := r.allowedToUseMercury(opts, upkeepId)
- assert.Equal(t, tt.err, err)
- assert.Equal(t, tt.allowed, allowed)
- assert.Equal(t, tt.state, state)
- assert.Equal(t, tt.reason, reason)
- assert.Equal(t, tt.retryable, retryable)
- })
- }
-}
-
-func TestEvmRegistry_DoMercuryRequestV02(t *testing.T) {
- upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10)
-
- tests := []struct {
- name string
- lookup *StreamsLookup
- mockHttpStatusCode int
- mockChainlinkBlobs []string
- pluginRetries int
- pluginRetryKey string
- expectedValues [][]byte
- expectedRetryable bool
- expectedRetryInterval time.Duration
- expectedError error
- state encoding.PipelineExecutionState
- reason encoding.UpkeepFailureReason
- }{
- {
- name: "success",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- mockHttpStatusCode: http.StatusOK,
- mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
- expectedValues: [][]byte{{0, 6, 109, 252, 209, 237, 45, 149, 177, 140, 148, 141, 188, 91, 214, 76, 104, 122, 254, 147, 228, 202, 125, 102, 61, 222, 193, 76, 32, 9, 10, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 128, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 69, 84, 72, 45, 85, 83, 68, 45, 65, 82, 66, 73, 84, 82, 85, 77, 45, 84, 69, 83, 84, 78, 69, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 216, 211, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 207, 11, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 155, 61, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 206, 116, 217, 250, 37, 42, 137, 131, 151, 110, 171, 96, 13, 199, 89, 12, 119, 141, 4, 129, 52, 48, 132, 27, 198, 231, 101, 195, 76, 216, 26, 22, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 96, 65, 43, 148, 229, 37, 202, 108, 237, 201, 245, 68, 253, 134, 247, 118, 6, 213, 47, 231, 49, 165, 208, 105, 219, 232, 54, 168, 191, 192, 251, 140, 145, 25, 99, 176, 174, 122, 20, 151, 31, 59, 70, 33, 191, 251, 128, 46, 240, 96, 83, 146, 185, 166, 200, 156, 127, 171, 29, 248, 99, 58, 90, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 69, 0, 194, 245, 33, 248, 63, 186, 94, 252, 43, 243, 239, 250, 174, 221, 228, 61, 10, 74, 223, 247, 133, 193, 33, 59, 113, 42, 58, 237, 13, 129, 87, 100, 42, 132, 50, 77, 176, 207, 150, 149, 235, 210, 119, 8, 212, 96, 142, 176, 51, 126, 13, 216, 123, 14, 67, 240, 250, 112, 199, 0, 217, 17}},
- expectedRetryable: false,
- expectedError: nil,
- },
- {
- name: "failure - retryable and interval is 1s",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- mockHttpStatusCode: http.StatusInternalServerError,
- mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
- expectedValues: [][]byte{nil},
- expectedRetryable: true,
- pluginRetries: 0,
- expectedRetryInterval: 1 * time.Second,
- expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
- state: encoding.MercuryFlakyFailure,
- },
- {
- name: "failure - retryable and interval is 5s",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- pluginRetries: 5,
- mockHttpStatusCode: http.StatusInternalServerError,
- mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
- expectedValues: [][]byte{nil},
- expectedRetryable: true,
- expectedRetryInterval: 5 * time.Second,
- expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
- state: encoding.MercuryFlakyFailure,
- },
- {
- name: "failure - not retryable because there are many plugin retries already",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- pluginRetries: 10,
- mockHttpStatusCode: http.StatusInternalServerError,
- mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
- expectedValues: [][]byte{nil},
- expectedRetryable: true,
- expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 500\n#2: 500\n#3: 500"),
- state: encoding.MercuryFlakyFailure,
- },
- {
- name: "failure - not retryable",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- mockHttpStatusCode: http.StatusTooManyRequests,
- mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
- expectedValues: [][]byte{nil},
- expectedRetryable: false,
- expectedError: errors.New("failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 25880526 upkeep 88786950015966611018675766524283132478093844178961698330929478019253453382042 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"),
- state: encoding.InvalidMercuryRequest,
- },
- {
- name: "failure - no feeds",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- expectedValues: [][]byte{},
- reason: encoding.UpkeepFailureReasonInvalidRevertDataInput,
- },
- {
- name: "failure - invalid revert data",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- expectedValues: [][]byte{},
- reason: encoding.UpkeepFailureReasonInvalidRevertDataInput,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- r := setupEVMRegistry(t)
- defer r.Close()
-
- if tt.pluginRetries != 0 {
- r.mercury.pluginRetryCache.Set(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
- }
-
- hc := mocks.NewHttpClient(t)
-
- for _, blob := range tt.mockChainlinkBlobs {
- mr := MercuryV02Response{ChainlinkBlob: blob}
- b, err := json.Marshal(mr)
- assert.Nil(t, err)
-
- resp := &http.Response{
- StatusCode: tt.mockHttpStatusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- if tt.expectedError != nil && tt.expectedRetryable || tt.pluginRetries > 0 {
- hc.On("Do", mock.Anything).Return(resp, nil).Times(totalAttempt)
- } else {
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- }
- }
- r.hc = hc
-
- state, reason, values, retryable, ri, reqErr := r.doMercuryRequest(context.Background(), tt.lookup, tt.pluginRetryKey, r.lggr)
- assert.Equal(t, tt.expectedValues, values)
- assert.Equal(t, tt.expectedRetryable, retryable)
- if retryable {
- newRetries, _ := r.mercury.pluginRetryCache.Get(tt.pluginRetryKey)
- assert.Equal(t, tt.pluginRetries+1, newRetries.(int))
- }
- assert.Equal(t, tt.expectedRetryInterval, ri)
- assert.Equal(t, tt.state, state)
- assert.Equal(t, tt.reason, reason)
- if tt.expectedError != nil {
- assert.True(t, strings.HasPrefix(reqErr.Error(), "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"))
- }
- })
- }
-}
-
-func TestEvmRegistry_DoMercuryRequestV03(t *testing.T) {
- upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10)
-
- tests := []struct {
- name string
- lookup *StreamsLookup
- mockHttpStatusCode int
- mockChainlinkBlobs []string
- pluginRetryKey string
- expectedValues [][]byte
- expectedRetryable bool
- expectedRetryInterval time.Duration
- expectedError error
- state encoding.PipelineExecutionState
- reason encoding.UpkeepFailureReason
- }{
- {
- name: "success v0.3",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(25880526),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- },
- mockHttpStatusCode: http.StatusOK,
- mockChainlinkBlobs: []string{"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"},
- expectedValues: [][]byte{{0, 6, 109, 252, 209, 237, 45, 149, 177, 140, 148, 141, 188, 91, 214, 76, 104, 122, 254, 147, 228, 202, 125, 102, 61, 222, 193, 76, 32, 9, 10, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 128, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 69, 84, 72, 45, 85, 83, 68, 45, 65, 82, 66, 73, 84, 82, 85, 77, 45, 84, 69, 83, 84, 78, 69, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 216, 211, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 154, 207, 11, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 155, 61, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 206, 116, 217, 250, 37, 42, 137, 131, 151, 110, 171, 96, 13, 199, 89, 12, 119, 141, 4, 129, 52, 48, 132, 27, 198, 231, 101, 195, 76, 216, 26, 22, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 138, 231, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137, 28, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 96, 65, 43, 148, 229, 37, 202, 108, 237, 201, 245, 68, 253, 134, 247, 118, 6, 213, 47, 231, 49, 165, 208, 105, 219, 232, 54, 168, 191, 192, 251, 140, 145, 25, 99, 176, 174, 122, 20, 151, 31, 59, 70, 33, 191, 251, 128, 46, 240, 96, 83, 146, 185, 166, 200, 156, 127, 171, 29, 248, 99, 58, 90, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 69, 0, 194, 245, 33, 248, 63, 186, 94, 252, 43, 243, 239, 250, 174, 221, 228, 61, 10, 74, 223, 247, 133, 193, 33, 59, 113, 42, 58, 237, 13, 129, 87, 100, 42, 132, 50, 77, 176, 207, 150, 149, 235, 210, 119, 8, 212, 96, 142, 176, 51, 126, 13, 216, 123, 14, 67, 240, 250, 112, 199, 0, 217, 17}},
- expectedRetryable: false,
- expectedError: nil,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- r := setupEVMRegistry(t)
- hc := mocks.NewHttpClient(t)
-
- mr := MercuryV03Response{}
- for i, blob := range tt.mockChainlinkBlobs {
- r := MercuryV03Report{
- FeedID: tt.lookup.Feeds[i],
- ValidFromTimestamp: 0,
- ObservationsTimestamp: 0,
- FullReport: blob,
- }
- mr.Reports = append(mr.Reports, r)
- }
-
- b, err := json.Marshal(mr)
- assert.Nil(t, err)
- resp := &http.Response{
- StatusCode: tt.mockHttpStatusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- if tt.expectedError != nil && tt.expectedRetryable {
- hc.On("Do", mock.Anything).Return(resp, nil).Times(totalAttempt)
- } else {
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- }
- r.hc = hc
-
- state, reason, values, retryable, ri, reqErr := r.doMercuryRequest(context.Background(), tt.lookup, tt.pluginRetryKey, r.lggr)
- assert.Equal(t, tt.expectedValues, values)
- assert.Equal(t, tt.expectedRetryable, retryable)
- assert.Equal(t, tt.expectedRetryInterval, ri)
- assert.Equal(t, tt.state, state)
- assert.Equal(t, tt.reason, reason)
- if tt.expectedError != nil {
- assert.Equal(t, tt.expectedError.Error(), reqErr.Error())
- }
- })
- }
-}
-
-func TestEvmRegistry_SingleFeedRequest(t *testing.T) {
- upkeepId := big.NewInt(123456789)
- tests := []struct {
- name string
- index int
- lookup *StreamsLookup
- pluginRetryKey string
- blob string
- statusCode int
- lastStatusCode int
- retryNumber int
- retryable bool
- errorMessage string
- }{
- {
- name: "success - mercury responds in the first try",
- index: 0,
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- blob: "0xab2123dc00000012",
- },
- {
- name: "success - retry for 404",
- index: 0,
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- blob: "0xab2123dcbabbad",
- retryNumber: 1,
- statusCode: http.StatusNotFound,
- lastStatusCode: http.StatusOK,
- },
- {
- name: "success - retry for 500",
- index: 0,
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- blob: "0xab2123dcbbabad",
- retryNumber: 2,
- statusCode: http.StatusInternalServerError,
- lastStatusCode: http.StatusOK,
- },
- {
- name: "failure - returns retryable",
- index: 0,
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- blob: "0xab2123dc",
- retryNumber: totalAttempt,
- statusCode: http.StatusNotFound,
- retryable: true,
- errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 404\n#2: 404\n#3: 404",
- },
- {
- name: "failure - returns retryable and then non-retryable",
- index: 0,
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- blob: "0xab2123dc",
- retryNumber: 1,
- statusCode: http.StatusNotFound,
- lastStatusCode: http.StatusTooManyRequests,
- errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: 404\n#2: at block 123456 upkeep 123456789 received status code 429 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- },
- {
- name: "failure - returns not retryable",
- index: 0,
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- blob: "0xab2123dc",
- statusCode: http.StatusConflict,
- errorMessage: "failed to request feed for 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000: All attempts fail:\n#1: at block 123456 upkeep 123456789 received status code 409 for feed 0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- r := setupEVMRegistry(t)
- defer r.Close()
-
- hc := mocks.NewHttpClient(t)
-
- mr := MercuryV02Response{ChainlinkBlob: tt.blob}
- b, err := json.Marshal(mr)
- assert.Nil(t, err)
-
- if tt.retryNumber == 0 {
- if tt.errorMessage != "" {
- resp := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- } else {
- resp := &http.Response{
- StatusCode: http.StatusOK,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- }
- } else if tt.retryNumber > 0 && tt.retryNumber < totalAttempt {
- retryResp := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(retryResp, nil).Times(tt.retryNumber)
-
- resp := &http.Response{
- StatusCode: tt.lastStatusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- } else {
- resp := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Times(tt.retryNumber)
- }
- r.hc = hc
-
- ch := make(chan MercuryData, 1)
- r.singleFeedRequest(context.Background(), ch, tt.index, tt.lookup, r.lggr)
-
- m := <-ch
- assert.Equal(t, tt.index, m.Index)
- assert.Equal(t, tt.retryable, m.Retryable)
- if tt.retryNumber >= totalAttempt || tt.errorMessage != "" {
- assert.Equal(t, tt.errorMessage, m.Error.Error())
- assert.Equal(t, [][]byte{}, m.Bytes)
- } else {
- blobBytes, err := hexutil.Decode(tt.blob)
- assert.Nil(t, err)
- assert.Nil(t, m.Error)
- assert.Equal(t, [][]byte{blobBytes}, m.Bytes)
- }
- })
- }
-}
-
-func TestEvmRegistry_MultiFeedRequest(t *testing.T) {
- upkeepId := big.NewInt(123456789)
- tests := []struct {
- name string
- lookup *StreamsLookup
- statusCode int
- lastStatusCode int
- pluginRetries int
- pluginRetryKey string
- retryNumber int
- retryable bool
- errorMessage string
- firstResponse *MercuryV03Response
- response *MercuryV03Response
- }{
- {
- name: "success - mercury responds in the first try",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- response: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- {
- FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123458,
- ObservationsTimestamp: 123458,
- FullReport: "0xab2123dc00000016",
- },
- },
- },
- statusCode: http.StatusOK,
- },
- {
- name: "success - mercury responds in the first try with blocknumber",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- response: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- {
- FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123458,
- ObservationsTimestamp: 123458,
- FullReport: "0xab2123dc00000016",
- },
- },
- },
- statusCode: http.StatusOK,
- },
- {
- name: "success - retry 206",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- firstResponse: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- },
- },
- response: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- {
- FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123458,
- ObservationsTimestamp: 123458,
- FullReport: "0xab2123dc00000019",
- },
- },
- },
- retryNumber: 1,
- statusCode: http.StatusPartialContent,
- lastStatusCode: http.StatusOK,
- },
- {
- name: "success - retry for 500",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- retryNumber: 2,
- statusCode: http.StatusInternalServerError,
- lastStatusCode: http.StatusOK,
- response: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- {
- FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123458,
- ObservationsTimestamp: 123458,
- FullReport: "0xab2123dc00000019",
- },
- },
- },
- },
- {
- name: "failure - fail to decode reportBlob",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- response: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "qerwiu", // invalid hex blob
- },
- {
- FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123458,
- ObservationsTimestamp: 123458,
- FullReport: "0xab2123dc00000016",
- },
- },
- },
- statusCode: http.StatusOK,
- retryable: false,
- errorMessage: "All attempts fail:\n#1: hex string without 0x prefix",
- },
- {
- name: "failure - returns retryable with 1s plugin retry interval",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- retryNumber: totalAttempt,
- statusCode: http.StatusInternalServerError,
- retryable: true,
- errorMessage: "All attempts fail:\n#1: 500\n#2: 500\n#3: 500",
- },
- {
- name: "failure - returns retryable with 5s plugin retry interval",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- pluginRetries: 6,
- retryNumber: totalAttempt,
- statusCode: http.StatusInternalServerError,
- retryable: true,
- errorMessage: "All attempts fail:\n#1: 500\n#2: 500\n#3: 500",
- },
- {
- name: "failure - returns retryable and then non-retryable",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- retryNumber: 1,
- statusCode: http.StatusInternalServerError,
- lastStatusCode: http.StatusUnauthorized,
- errorMessage: "All attempts fail:\n#1: 500\n#2: at timestamp 123456 upkeep 123456789 received status code 401 from mercury v0.3, most likely this is caused by unauthorized upkeep",
- },
- {
- name: "failure - returns status code 422 not retryable",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- statusCode: http.StatusUnprocessableEntity,
- errorMessage: "All attempts fail:\n#1: at timestamp 123456 upkeep 123456789 received status code 422 from mercury v0.3",
- },
- {
- name: "success - retry when reports length does not match feeds length",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIDs,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: timestamp,
- Time: big.NewInt(123456),
- },
- upkeepId: upkeepId,
- },
- firstResponse: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- },
- },
- response: &MercuryV03Response{
- Reports: []MercuryV03Report{
- {
- FeedID: "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123456,
- ObservationsTimestamp: 123456,
- FullReport: "0xab2123dc00000012",
- },
- {
- FeedID: "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000",
- ValidFromTimestamp: 123458,
- ObservationsTimestamp: 123458,
- FullReport: "0xab2123dc00000019",
- },
- },
- },
- retryNumber: 1,
- statusCode: http.StatusOK,
- lastStatusCode: http.StatusOK,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- r := setupEVMRegistry(t)
- defer r.Close()
-
- if tt.pluginRetries != 0 {
- r.mercury.pluginRetryCache.Set(tt.pluginRetryKey, tt.pluginRetries, cache.DefaultExpiration)
- }
-
- hc := mocks.NewHttpClient(t)
- b, err := json.Marshal(tt.response)
- assert.Nil(t, err)
-
- if tt.retryNumber == 0 {
- resp := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- } else if tt.retryNumber < totalAttempt {
- if tt.firstResponse != nil && tt.response != nil {
- b0, err := json.Marshal(tt.firstResponse)
- assert.Nil(t, err)
- resp0 := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b0)),
- }
- b1, err := json.Marshal(tt.response)
- assert.Nil(t, err)
- resp1 := &http.Response{
- StatusCode: tt.lastStatusCode,
- Body: io.NopCloser(bytes.NewReader(b1)),
- }
- hc.On("Do", mock.Anything).Return(resp0, nil).Once().On("Do", mock.Anything).Return(resp1, nil).Once()
- } else {
- retryResp := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(retryResp, nil).Times(tt.retryNumber)
-
- resp := &http.Response{
- StatusCode: tt.lastStatusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Once()
- }
- } else {
- resp := &http.Response{
- StatusCode: tt.statusCode,
- Body: io.NopCloser(bytes.NewReader(b)),
- }
- hc.On("Do", mock.Anything).Return(resp, nil).Times(tt.retryNumber)
- }
- r.hc = hc
-
- ch := make(chan MercuryData, 1)
- r.multiFeedsRequest(context.Background(), ch, tt.lookup, r.lggr)
-
- m := <-ch
- assert.Equal(t, 0, m.Index)
- assert.Equal(t, tt.retryable, m.Retryable)
- if tt.retryNumber >= totalAttempt || tt.errorMessage != "" {
- assert.Equal(t, tt.errorMessage, m.Error.Error())
- assert.Equal(t, [][]byte{}, m.Bytes)
- } else {
- assert.Nil(t, m.Error)
- var reports [][]byte
- for _, rsp := range tt.response.Reports {
- b, _ := hexutil.Decode(rsp.FullReport)
- reports = append(reports, b)
- }
- assert.Equal(t, reports, m.Bytes)
- }
- })
- }
-}
-
-func TestEvmRegistry_CheckCallback(t *testing.T) {
- upkeepId := big.NewInt(123456789)
- bn := uint64(999)
- bs := []byte{183, 114, 215, 10, 0, 0, 0, 0, 0, 0}
- values := [][]byte{bs}
- tests := []struct {
- name string
- lookup *StreamsLookup
- values [][]byte
- statusCode int
-
- callbackResp []byte
- callbackErr error
-
- upkeepNeeded bool
- performData []byte
- wantErr assert.ErrorAssertionFunc
-
- state encoding.PipelineExecutionState
- retryable bool
- }{
- {
- name: "success - empty extra data",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"ETD-USD", "BTC-ETH"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(100),
- ExtraData: []byte{48, 120, 48, 48},
- },
- upkeepId: upkeepId,
- block: bn,
- },
- values: values,
- statusCode: http.StatusOK,
- callbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48, 120, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- upkeepNeeded: true,
- performData: []byte{48, 120, 48, 48},
- wantErr: assert.NoError,
- },
- {
- name: "success - with extra data",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(18952430),
- // this is the address of precompile contract ArbSys(0x0000000000000000000000000000000000000064)
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- },
- upkeepId: upkeepId,
- block: bn,
- },
- values: values,
- statusCode: http.StatusOK,
- callbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- upkeepNeeded: true,
- performData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
- wantErr: assert.NoError,
- },
- {
- name: "failure - bad response",
- lookup: &StreamsLookup{
- StreamsLookupError: &encoding.StreamsLookupError{
- FeedParamKey: feedIdHex,
- Feeds: []string{"ETD-USD", "BTC-ETH"},
- TimeParamKey: blockNumber,
- Time: big.NewInt(100),
- ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48, 120, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- },
- upkeepId: upkeepId,
- block: bn,
- },
- values: values,
- statusCode: http.StatusOK,
- callbackResp: []byte{},
- callbackErr: errors.New("bad response"),
- wantErr: assert.Error,
- state: encoding.RpcFlakyFailure,
- retryable: true,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- client := new(evmClientMocks.Client)
- r := setupEVMRegistry(t)
- defer r.Close()
-
- payload, err := r.abi.Pack("checkCallback", tt.lookup.upkeepId, values, tt.lookup.ExtraData)
- require.Nil(t, err)
- args := map[string]interface{}{
- "to": r.addr.Hex(),
- "data": hexutil.Bytes(payload),
- }
- client.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", args, hexutil.EncodeUint64(tt.lookup.block)).Return(tt.callbackErr).
- Run(func(args mock.Arguments) {
- by := args.Get(1).(*hexutil.Bytes)
- *by = tt.callbackResp
- }).Once()
- r.client = client
-
- state, retryable, _, err := r.checkCallback(context.Background(), tt.values, tt.lookup)
- tt.wantErr(t, err, fmt.Sprintf("Error asserion failed: %v", tt.name))
- assert.Equal(t, tt.state, state)
- assert.Equal(t, tt.retryable, retryable)
- })
- }
-}
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
index ee8b7cd6e9..f4fbf24f41 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
@@ -26,6 +26,8 @@ import (
"github.com/stretchr/testify/require"
"github.com/umbracle/ethgo/abi"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
+
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
@@ -33,7 +35,9 @@ import (
"github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
automationForwarderLogic "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_forwarder_logic"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/basic_upkeep_contract"
@@ -52,7 +56,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper"
- evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
)
@@ -884,7 +887,7 @@ func (c *feedLookupUpkeepController) EnableMercury(
registry *iregistry21.IKeeperRegistryMaster,
registryOwner *bind.TransactOpts,
) error {
- adminBytes, _ := json.Marshal(evm21.UpkeepPrivilegeConfig{
+ adminBytes, _ := json.Marshal(streams.UpkeepPrivilegeConfig{
MercuryEnabled: true,
})
@@ -908,7 +911,7 @@ func (c *feedLookupUpkeepController) EnableMercury(
return err
}
- var checkBytes evm21.UpkeepPrivilegeConfig
+ var checkBytes streams.UpkeepPrivilegeConfig
if err := json.Unmarshal(bts, &checkBytes); err != nil {
require.NoError(t, err)
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 1a093a8815..87074e786d 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -10,12 +10,16 @@ import (
"testing"
"time"
- "github.com/ethereum/go-ethereum/common"
"github.com/kelseyhightower/envconfig"
+
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
+
+ "github.com/ethereum/go-ethereum/common"
"github.com/onsi/gomega"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
@@ -23,8 +27,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
-
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
@@ -152,7 +154,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
if isMercury {
// Set privilege config to enable mercury
- privilegeConfigBytes, _ := json.Marshal(evm21.UpkeepPrivilegeConfig{
+ privilegeConfigBytes, _ := json.Marshal(streams.UpkeepPrivilegeConfig{
MercuryEnabled: true,
})
if err := registry.SetUpkeepPrivilegeConfig(upkeepIDs[i], privilegeConfigBytes); err != nil {
From 96498b692963bbea6b9b1d1e7d5bcaf6f0786542 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Thu, 16 Nov 2023 15:10:14 -0500
Subject: [PATCH 165/327] [TT-695] Deprecate P2Pv1 in Tests (#11305)
* Deprecating P2Pv1 in Tests
* P2Pv2 Swap
* Lint
* Stupid typose
---
integration-tests/actions/ocr_helpers_local.go | 8 ++++----
integration-tests/client/chainlink.go | 5 ++++-
integration-tests/client/chainlink_models.go | 14 +++++---------
.../docker/test_env/test_env_builder.go | 5 +++--
integration-tests/smoke/keeper_test.go | 2 +-
integration-tests/smoke/ocr_test.go | 7 ++++---
integration-tests/types/config/node/core.go | 2 ++
integration-tests/universal/log_poller/helpers.go | 3 ---
8 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go
index e6dd5ae77f..fb0fd0bd47 100644
--- a/integration-tests/actions/ocr_helpers_local.go
+++ b/integration-tests/actions/ocr_helpers_local.go
@@ -146,7 +146,7 @@ func CreateOCRJobsLocal(
workerNodes []*client.ChainlinkClient,
mockValue int,
mockAdapter *test_env.Killgrave,
- evmChainID string,
+ evmChainID *big.Int,
) error {
for _, ocrInstance := range ocrInstances {
bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys()
@@ -157,7 +157,7 @@ func CreateOCRJobsLocal(
bootstrapSpec := &client.OCRBootstrapJobSpec{
Name: fmt.Sprintf("bootstrap-%s", uuid.New().String()),
ContractAddress: ocrInstance.Address(),
- EVMChainID: evmChainID,
+ EVMChainID: evmChainID.String(),
P2PPeerID: bootstrapP2PId,
IsBootstrapPeer: true,
}
@@ -202,7 +202,7 @@ func CreateOCRJobsLocal(
bootstrapPeers := []*client.ChainlinkClient{bootstrapNode}
ocrSpec := &client.OCRTaskJobSpec{
ContractAddress: ocrInstance.Address(),
- EVMChainID: evmChainID,
+ EVMChainID: evmChainID.String(),
P2PPeerID: nodeP2PId,
P2PBootstrapPeers: bootstrapPeers,
KeyBundleID: nodeOCRKeyId,
@@ -211,7 +211,7 @@ func CreateOCRJobsLocal(
}
_, err = node.MustCreateJob(ocrSpec)
if err != nil {
- return fmt.Errorf("creating OCR task job on OCR node have failed: %w", err)
+ return fmt.Errorf("creating OCR job on OCR node failed: %w", err)
}
}
}
diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go
index 4603679ff8..16299a1ac8 100644
--- a/integration-tests/client/chainlink.go
+++ b/integration-tests/client/chainlink.go
@@ -116,7 +116,7 @@ func (c *ChainlinkClient) MustCreateJob(spec JobSpec) (*Job, error) {
if err != nil {
return nil, err
}
- return job, VerifyStatusCode(resp.RawResponse.StatusCode, http.StatusOK)
+ return job, VerifyStatusCodeWithResponse(resp, http.StatusOK)
}
// CreateJob creates a Chainlink job based on the provided spec struct
@@ -1114,6 +1114,7 @@ func (c *ChainlinkClient) SetPageSize(size int) {
c.pageSize = size
}
+// VerifyStatusCode verifies the status code of the response. Favor VerifyStatusCodeWithResponse over this for better errors
func VerifyStatusCode(actStatusCd, expStatusCd int) error {
if actStatusCd != expStatusCd {
return fmt.Errorf(
@@ -1125,6 +1126,8 @@ func VerifyStatusCode(actStatusCd, expStatusCd int) error {
return nil
}
+// VerifyStatusCodeWithResponse verifies the status code of the response and returns the response as part of the error.
+// Favor this over VerifyStatusCode
func VerifyStatusCodeWithResponse(res *resty.Response, expStatusCd int) error {
actStatusCd := res.RawResponse.StatusCode
if actStatusCd != expStatusCd {
diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go
index 17a0a50845..8ff8494155 100644
--- a/integration-tests/client/chainlink_models.go
+++ b/integration-tests/client/chainlink_models.go
@@ -889,7 +889,7 @@ contractConfigConfirmations ={{if not .ContractConfirmations}} 3 {{el
contractConfigTrackerPollInterval ={{if not .TrackerPollInterval}} "1m" {{else}} {{.TrackerPollInterval}} {{end}}
contractConfigTrackerSubscribeInterval ={{if not .TrackerSubscribeInterval}} "2m" {{else}} {{.TrackerSubscribeInterval}} {{end}}
contractAddress = "{{.ContractAddress}}"
-evmChainID = "{{.EVMChainID}}"
+evmChainID = "{{.EVMChainID}}"
p2pBootstrapPeers = []
isBootstrapPeer = {{.IsBootstrapPeer}}
p2pPeerID = "{{.P2PPeerID}}"`
@@ -988,22 +988,18 @@ contractConfigConfirmations ={{if not .ContractConfirmations}} 3 {{el
contractConfigTrackerPollInterval ={{if not .TrackerPollInterval}} "1m" {{else}} {{.TrackerPollInterval}} {{end}}
contractConfigTrackerSubscribeInterval ={{if not .TrackerSubscribeInterval}} "2m" {{else}} {{.TrackerSubscribeInterval}} {{end}}
contractAddress = "{{.ContractAddress}}"
-evmChainID = "{{.EVMChainID}}"
+evmChainID = "{{.EVMChainID}}"
{{if .P2PBootstrapPeers}}
-p2pBootstrapPeers = [
- {{range $peer := .P2PBootstrapPeers}}
- "/dns4/{{$peer.InternalIP}}/tcp/6690/p2p/{{$peer.PeerID}}",
- {{end}}
-]
+p2pv2Bootstrappers = [{{range $peer := .P2PBootstrapPeers}}"{{$peer.PeerID}}@{{$peer.InternalIP}}:6690",{{end}}]
{{else}}
-p2pBootstrapPeers = []
+p2pv2Bootstrappers = []
{{end}}
isBootstrapPeer = {{.IsBootstrapPeer}}
p2pPeerID = "{{.P2PPeerID}}"
keyBundleID = "{{.KeyBundleID}}"
monitoringEndpoint ={{if not .MonitoringEndpoint}} "chain.link:4321" {{else}} "{{.MonitoringEndpoint}}" {{end}}
transmitterAddress = "{{.TransmitterAddress}}"
-forwardingAllowed = {{.ForwardingAllowed}}
+forwardingAllowed = {{.ForwardingAllowed}}
observationSource = """
{{.ObservationSource}}
"""`
diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go
index 77c5669015..32f84991ee 100644
--- a/integration-tests/docker/test_env/test_env_builder.go
+++ b/integration-tests/docker/test_env/test_env_builder.go
@@ -17,9 +17,10 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
+ evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
+
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
)
type CleanUpType string
@@ -324,7 +325,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
} else {
cfg = node.NewConfig(node.NewBaseConfig(),
node.WithOCR1(),
- node.WithP2Pv1(),
+ node.WithP2Pv2(),
)
}
diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go
index 29a819af13..6f892e60ac 100644
--- a/integration-tests/smoke/keeper_test.go
+++ b/integration-tests/smoke/keeper_test.go
@@ -1098,7 +1098,7 @@ func setupKeeperTest(t *testing.T) (
contracts.LinkToken,
*test_env.CLClusterTestEnv,
) {
- clNodeConfig := node.NewConfig(node.NewBaseConfig(), node.WithP2Pv1())
+ clNodeConfig := node.NewConfig(node.NewBaseConfig(), node.WithP2Pv2())
turnLookBack := int64(0)
syncInterval := models.MustMakeDuration(5 * time.Second)
performGasOverhead := uint32(150000)
diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go
index 8fbc1109e2..a078b8ca41 100644
--- a/integration-tests/smoke/ocr_test.go
+++ b/integration-tests/smoke/ocr_test.go
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/utils"
@@ -39,7 +40,7 @@ func TestOCRBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
- err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String())
+ err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID())
require.NoError(t, err)
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
@@ -86,7 +87,7 @@ func TestOCRJobReplacement(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
- err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String())
+ err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID())
require.NoError(t, err)
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
@@ -112,7 +113,7 @@ func TestOCRJobReplacement(t *testing.T) {
require.NoError(t, err)
//Recreate job
- err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String())
+ err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID())
require.NoError(t, err)
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go
index 7ddddafdd5..e044d1ba32 100644
--- a/integration-tests/types/config/node/core.go
+++ b/integration-tests/types/config/node/core.go
@@ -109,6 +109,8 @@ func WithOCR2() NodeConfigOpt {
}
}
+// Deprecated: P2Pv1 is soon to be fully deprecated
+// WithP2Pv1 enables P2Pv1 and disables P2Pv2
func WithP2Pv1() NodeConfigOpt {
return func(c *chainlink.Config) {
c.P2P.V1 = toml.P2PV1{
diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go
index 08ceb4a7be..505337f032 100644
--- a/integration-tests/universal/log_poller/helpers.go
+++ b/integration-tests/universal/log_poller/helpers.go
@@ -27,7 +27,6 @@ import (
ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
-
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -39,12 +38,10 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
-
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
-
it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
From a9d81ae52ccd4e76ed414768ad7adc4532d3facd Mon Sep 17 00:00:00 2001
From: Tate
Date: Thu, 16 Nov 2023 14:01:31 -0700
Subject: [PATCH 166/327] [TT-653] More integration-test lib migration to
chainlink-testing-framework (#11317)
* [TT-653] Migrate more integration-test libs to chainlink-testing-framework
* testing
* merge conflict fix
* bump ctf version
---
integration-tests/actions/actions.go | 4 +-
.../actions/ocr2vrf_actions/ocr2vrf_steps.go | 6 +-
.../actions/operator_forwarder_helpers.go | 12 +--
.../actions/vrfv2plus/vrfv2plus_steps.go | 6 +-
integration-tests/benchmark/keeper_test.go | 3 +-
.../chaos/automation_chaos_test.go | 26 ++---
integration-tests/chaos/ocr2vrf_chaos_test.go | 26 ++---
integration-tests/chaos/ocr_chaos_test.go | 24 ++---
.../client/chainlink_config_builder.go | 52 ----------
integration-tests/docker/test_env/cl_node.go | 19 ++--
integration-tests/docker/test_env/test_env.go | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
.../load/vrfv2/onchain_monitoring.go | 5 +-
.../load/vrfv2plus/vrfv2plus_test.go | 6 +-
.../migration/upgrade_version_test.go | 6 +-
integration-tests/performance/cron_test.go | 2 +-
.../performance/directrequest_test.go | 6 +-
integration-tests/performance/flux_test.go | 12 +--
integration-tests/performance/keeper_test.go | 10 +-
integration-tests/performance/ocr_test.go | 9 +-
integration-tests/performance/vrf_test.go | 8 +-
.../reorg/automation_reorg_test.go | 10 +-
integration-tests/reorg/reorg_confirmer.go | 7 +-
integration-tests/reorg/reorg_test.go | 12 +--
integration-tests/smoke/automation_test.go | 87 ++++++++---------
integration-tests/smoke/flux_test.go | 10 +-
integration-tests/smoke/forwarder_ocr_test.go | 6 +-
.../smoke/forwarders_ocr2_test.go | 6 +-
integration-tests/smoke/keeper_test.go | 96 +++++++++----------
integration-tests/smoke/ocr2_test.go | 12 +--
integration-tests/smoke/ocr2vrf_test.go | 8 +-
integration-tests/smoke/ocr_test.go | 13 ++-
integration-tests/smoke/runlog_test.go | 4 +-
integration-tests/smoke/vrf_test.go | 12 +--
integration-tests/smoke/vrfv2_test.go | 6 +-
integration-tests/smoke/vrfv2plus_test.go | 96 +++++++++----------
integration-tests/soak/forwarder_ocr_test.go | 2 +-
integration-tests/soak/ocr_test.go | 2 +-
.../testsetups/keeper_benchmark.go | 10 +-
integration-tests/testsetups/ocr.go | 14 +--
integration-tests/testsetups/vrfv2.go | 4 +-
integration-tests/types/config/node/core.go | 91 +++++++++---------
.../universal/log_poller/helpers.go | 16 ++--
.../universal/log_poller/scenarios.go | 14 +--
integration-tests/utils/common.go | 25 -----
46 files changed, 368 insertions(+), 447 deletions(-)
delete mode 100644 integration-tests/client/chainlink_config_builder.go
diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go
index 02a2523477..438c36a9f0 100644
--- a/integration-tests/actions/actions.go
+++ b/integration-tests/actions/actions.go
@@ -23,7 +23,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/testreporters"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
@@ -48,7 +48,7 @@ func FundChainlinkNodes(
msg := ethereum.CallMsg{
From: common.HexToAddress(client.GetDefaultWallet().Address()),
To: &recipient,
- Value: utils.EtherToWei(amount),
+ Value: conversions.EtherToWei(amount),
}
gasEstimates, err := client.EstimateGas(msg)
if err != nil {
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
index 72d668076e..2904162f49 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
@@ -14,6 +14,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -22,7 +23,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func SetAndWaitForVRFBeaconProcessToFinish(t *testing.T, ocr2VRFPluginConfig *OCR2VRFPluginConfig, vrfBeacon contracts.VRFBeacon) {
@@ -273,14 +273,14 @@ func RequestRandomnessFulfillmentAndWaitForFulfilment(
}
func getRequestId(t *testing.T, consumer contracts.VRFBeaconConsumer, receipt *types.Receipt, confirmationDelay *big.Int) *big.Int {
- periodBlocks, err := consumer.IBeaconPeriodBlocks(utils.TestContext(t))
+ periodBlocks, err := consumer.IBeaconPeriodBlocks(testcontext.Get(t))
require.NoError(t, err, "Error getting Beacon Period block count")
blockNumber := receipt.BlockNumber
periodOffset := new(big.Int).Mod(blockNumber, periodBlocks)
nextBeaconOutputHeight := new(big.Int).Sub(new(big.Int).Add(blockNumber, periodBlocks), periodOffset)
- requestID, err := consumer.GetRequestIdsBy(utils.TestContext(t), nextBeaconOutputHeight, confirmationDelay)
+ requestID, err := consumer.GetRequestIdsBy(testcontext.Get(t), nextBeaconOutputHeight, confirmationDelay)
require.NoError(t, err, "Error getting requestID from consumer contract")
return requestID
diff --git a/integration-tests/actions/operator_forwarder_helpers.go b/integration-tests/actions/operator_forwarder_helpers.go
index a1d7135416..e308cd8fd5 100644
--- a/integration-tests/actions/operator_forwarder_helpers.go
+++ b/integration-tests/actions/operator_forwarder_helpers.go
@@ -12,11 +12,11 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func DeployForwarderContracts(
@@ -67,7 +67,7 @@ func AcceptAuthorizedReceiversOperator(
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for events in nodes shouldn't fail")
- senders, err := forwarderInstance.GetAuthorizedSenders(utils.TestContext(t))
+ senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t))
require.NoError(t, err, "Getting authorized senders shouldn't fail")
var nodesAddrs []string
for _, o := range nodeAddresses {
@@ -75,7 +75,7 @@ func AcceptAuthorizedReceiversOperator(
}
require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses")
- owner, err := forwarderInstance.Owner(utils.TestContext(t))
+ owner, err := forwarderInstance.Owner(testcontext.Get(t))
require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail")
require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator")
}
@@ -139,7 +139,7 @@ func SubscribeOperatorFactoryEvents(
l := logging.GetTestLogger(t)
contractABI, err := operator_factory.OperatorFactoryMetaData.GetAbi()
require.NoError(t, err, "Getting contract abi for OperatorFactory shouldn't fail")
- latestBlockNum, err := chainClient.LatestBlockNumber(utils.TestContext(t))
+ latestBlockNum, err := chainClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail")
query := geth.FilterQuery{
FromBlock: big.NewInt(0).SetUint64(latestBlockNum),
@@ -147,7 +147,7 @@ func SubscribeOperatorFactoryEvents(
}
eventLogs := make(chan types.Log)
- sub, err := chainClient.SubscribeFilterLogs(utils.TestContext(t), query, eventLogs)
+ sub, err := chainClient.SubscribeFilterLogs(testcontext.Get(t), query, eventLogs)
require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail")
go func() {
defer sub.Unsubscribe()
@@ -158,7 +158,7 @@ func SubscribeOperatorFactoryEvents(
l.Error().Err(err).Msg("Error while watching for new contract events. Retrying Subscription")
sub.Unsubscribe()
- sub, err = chainClient.SubscribeFilterLogs(utils.TestContext(t), query, eventLogs)
+ sub, err = chainClient.SubscribeFilterLogs(testcontext.Get(t), query, eventLogs)
require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail")
case vLog := <-eventLogs:
eventDetails, err := contractABI.EventByID(vLog.Topics[0])
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index 254f2ca6ce..f48d415792 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -7,7 +7,7 @@ import (
"sync"
"time"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions"
relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
@@ -599,7 +599,7 @@ func FundSubscriptions(
) error {
for _, subID := range subIDs {
//Native Billing
- amountWei := utils.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountNative))
+ amountWei := conversions.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountNative))
err := coordinator.FundSubscriptionWithNative(
subID,
amountWei,
@@ -608,7 +608,7 @@ func FundSubscriptions(
return fmt.Errorf("%s, err %w", ErrFundSubWithNativeToken, err)
}
//Link Billing
- amountJuels := utils.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountLink))
+ amountJuels := conversions.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountLink))
err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, amountJuels)
if err != nil {
return fmt.Errorf("%s, err %w", ErrFundSubWithLinkToken, err)
diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go
index 9342f3629b..6d398c685e 100644
--- a/integration-tests/benchmark/keeper_test.go
+++ b/integration-tests/benchmark/keeper_test.go
@@ -22,7 +22,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
- "github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
@@ -434,7 +433,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockc
testNetwork.HTTPURLs = []string{internalHttpURLs[i]}
testNetwork.URLs = []string{internalWsURLs[i]}
testEnvironment.AddHelm(chainlink.New(i, map[string]any{
- "toml": client.AddNetworkDetailedConfig(keeperBenchmarkBaseTOML, networkDetailTOML, testNetwork),
+ "toml": networks.AddNetworkDetailedConfig(keeperBenchmarkBaseTOML, networkDetailTOML, testNetwork),
"chainlink": chainlinkResources,
"db": dbResources,
}))
diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go
index 6ebf14d806..06352a93d7 100644
--- a/integration-tests/chaos/automation_chaos_test.go
+++ b/integration-tests/chaos/automation_chaos_test.go
@@ -18,13 +18,13 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -41,7 +41,7 @@ ListenAddresses = ["0.0.0.0:6690"]`
defaultAutomationSettings = map[string]interface{}{
"replicas": 6,
- "toml": client.AddNetworksConfig(baseTOML, networks.MustGetSelectedNetworksFromEnv()[0]),
+ "toml": networks.AddNetworksConfig(baseTOML, networks.MustGetSelectedNetworksFromEnv()[0]),
"db": map[string]interface{}{
"stateful": true,
"capacity": "1Gi",
@@ -132,7 +132,7 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -141,7 +141,7 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -150,9 +150,9 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
DurationStr: "1m",
- ContainerNames: &[]*string{utils.Ptr("chainlink-db")},
+ ContainerNames: &[]*string{ptr.Ptr("chainlink-db")},
},
},
NetworkChaosFailMajorityNetwork: {
@@ -160,8 +160,8 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
- ToLabels: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
+ FromLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
+ ToLabels: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -170,8 +170,8 @@ func TestAutomationChaos(t *testing.T) {
chainlink.New(0, defaultAutomationSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{"app": utils.Ptr("geth")},
- ToLabels: &map[string]*string{ChaosGroupMajorityPlus: utils.Ptr("1")},
+ FromLabels: &map[string]*string{"app": ptr.Ptr("geth")},
+ ToLabels: &map[string]*string{ChaosGroupMajorityPlus: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -269,7 +269,7 @@ func TestAutomationChaos(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(it_utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
@@ -284,7 +284,7 @@ func TestAutomationChaos(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(it_utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 10
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go
index 8739a5960a..200114ddaf 100644
--- a/integration-tests/chaos/ocr2vrf_chaos_test.go
+++ b/integration-tests/chaos/ocr2vrf_chaos_test.go
@@ -17,7 +17,8 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions"
@@ -25,7 +26,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCR2VRFChaos(t *testing.T) {
@@ -35,7 +35,7 @@ func TestOCR2VRFChaos(t *testing.T) {
defaultOCR2VRFSettings := map[string]interface{}{
"replicas": 6,
- "toml": client.AddNetworkDetailedConfig(
+ "toml": networks.AddNetworkDetailedConfig(
config.BaseOCR2Config,
config.DefaultOCR2VRFNetworkDetailTomlConfig,
loadedNetwork,
@@ -68,7 +68,7 @@ func TestOCR2VRFChaos(t *testing.T) {
chainlink.New(0, defaultOCR2VRFSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -78,7 +78,7 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewFailPods,
// &chaos.Props{
- // LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ // LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
// DurationStr: "1m",
// },
//},
@@ -88,9 +88,9 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewFailPods,
// &chaos.Props{
- // LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ // LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
// DurationStr: "1m",
- // ContainerNames: &[]*string{utils.Ptr("chainlink-db")},
+ // ContainerNames: &[]*string{ptr.Ptr("chainlink-db")},
// },
//},
//NetworkChaosFailMajorityNetwork: {
@@ -98,8 +98,8 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewNetworkPartition,
// &chaos.Props{
- // FromLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
- // ToLabels: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
+ // FromLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
+ // ToLabels: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")},
// DurationStr: "1m",
// },
//},
@@ -108,8 +108,8 @@ func TestOCR2VRFChaos(t *testing.T) {
// chainlink.New(0, defaultOCR2VRFSettings),
// chaos.NewNetworkPartition,
// &chaos.Props{
- // FromLabels: &map[string]*string{"app": utils.Ptr("geth")},
- // ToLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ // FromLabels: &map[string]*string{"app": ptr.Ptr("geth")},
+ // ToLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
// DurationStr: "1m",
// },
//},
@@ -186,7 +186,7 @@ func TestOCR2VRFChaos(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(testcontext.Get(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err)
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
@@ -213,7 +213,7 @@ func TestOCR2VRFChaos(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(testcontext.Get(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err, "Error getting Randomness result from Consumer Contract")
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go
index 76e25d9200..5368997daa 100644
--- a/integration-tests/chaos/ocr_chaos_test.go
+++ b/integration-tests/chaos/ocr_chaos_test.go
@@ -20,13 +20,13 @@ import (
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -52,7 +52,7 @@ var (
)
func TestMain(m *testing.M) {
- defaultOCRSettings["toml"] = client.AddNetworksConfig(config.BaseOCRP2PV1Config, networks.MustGetSelectedNetworksFromEnv()[0])
+ defaultOCRSettings["toml"] = networks.AddNetworksConfig(config.BaseOCRP2PV1Config, networks.MustGetSelectedNetworksFromEnv()[0])
os.Exit(m.Run())
}
@@ -80,8 +80,8 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
- ToLabels: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
+ FromLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
+ ToLabels: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -90,8 +90,8 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewNetworkPartition,
&chaos.Props{
- FromLabels: &map[string]*string{"app": utils.Ptr("geth")},
- ToLabels: &map[string]*string{ChaosGroupMajorityPlus: utils.Ptr("1")},
+ FromLabels: &map[string]*string{"app": ptr.Ptr("geth")},
+ ToLabels: &map[string]*string{ChaosGroupMajorityPlus: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -100,7 +100,7 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMinority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -109,7 +109,7 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
DurationStr: "1m",
},
},
@@ -118,9 +118,9 @@ func TestOCRChaos(t *testing.T) {
chainlink.New(0, defaultOCRSettings),
chaos.NewFailPods,
&chaos.Props{
- LabelsSelector: &map[string]*string{ChaosGroupMajority: utils.Ptr("1")},
+ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")},
DurationStr: "1m",
- ContainerNames: &[]*string{utils.Ptr("chainlink-db")},
+ ContainerNames: &[]*string{ptr.Ptr("chainlink-db")},
},
},
}
@@ -195,7 +195,7 @@ func TestOCRChaos(t *testing.T) {
err := ocr.RequestNewRound()
require.NoError(t, err, "Error requesting new round")
}
- round, err := ocrInstances[0].GetLatestRound(it_utils.TestContext(t))
+ round, err := ocrInstances[0].GetLatestRound(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred())
l.Info().Int64("RoundID", round.RoundId.Int64()).Msg("Latest OCR Round")
if round.RoundId.Int64() == chaosStartRound && !chaosApplied {
diff --git a/integration-tests/client/chainlink_config_builder.go b/integration-tests/client/chainlink_config_builder.go
deleted file mode 100644
index 13cc1e7fe9..0000000000
--- a/integration-tests/client/chainlink_config_builder.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package client
-
-import (
- "fmt"
- "os"
-
- "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
- "github.com/smartcontractkit/chainlink-testing-framework/k8s/config"
-)
-
-const (
- pyroscopeTOML = `[Pyroscope]
-ServerAddress = '%s'
-Environment = '%s'`
-
- secretTOML = `
-[Mercury.Credentials.cred1]
-URL = '%s'
-Username = '%s'
-Password = '%s'
-`
-)
-
-// AddNetworksConfig adds EVM network configurations to a base config TOML. Useful for adding networks with default
-// settings. See AddNetworkDetailedConfig for adding more detailed network configuration.
-func AddNetworksConfig(baseTOML string, networks ...blockchain.EVMNetwork) string {
- networksToml := ""
- for _, network := range networks {
- networksToml = fmt.Sprintf("%s\n\n%s", networksToml, network.MustChainlinkTOML(""))
- }
- return fmt.Sprintf("%s\n\n%s\n\n%s", baseTOML, pyroscopeSettings(), networksToml)
-}
-
-func AddSecretTomlConfig(url, username, password string) string {
- return fmt.Sprintf(secretTOML, url, username, password)
-}
-
-// AddNetworkDetailedConfig adds EVM config to a base TOML. Also takes a detailed network config TOML where values like
-// using transaction forwarders can be included.
-// See https://github.com/smartcontractkit/chainlink/blob/develop/docs/CONFIG.md#EVM
-func AddNetworkDetailedConfig(baseTOML, detailedNetworkConfig string, network blockchain.EVMNetwork) string {
- return fmt.Sprintf("%s\n\n%s\n\n%s", baseTOML, pyroscopeSettings(), network.MustChainlinkTOML(detailedNetworkConfig))
-}
-
-func pyroscopeSettings() string {
- pyroscopeServer := os.Getenv(config.EnvVarPyroscopeServer)
- pyroscopeEnv := os.Getenv(config.EnvVarPyroscopeEnvironment)
- if pyroscopeServer == "" {
- return ""
- }
- return fmt.Sprintf(pyroscopeTOML, pyroscopeServer, pyroscopeEnv)
-}
diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go
index 3c0a6d3af7..c781ddfc1b 100644
--- a/integration-tests/docker/test_env/cl_node.go
+++ b/integration-tests/docker/test_env/cl_node.go
@@ -23,11 +23,12 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/logwatch"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
"github.com/smartcontractkit/chainlink/integration-tests/client"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
"github.com/smartcontractkit/chainlink/integration-tests/utils/templates"
)
@@ -112,7 +113,7 @@ func (n *ClNode) SetTestLogger(t *testing.T) {
// Restart restarts only CL node, DB container is reused
func (n *ClNode) Restart(cfg *chainlink.Config) error {
- if err := n.Container.Terminate(utils.TestContext(n.t)); err != nil {
+ if err := n.Container.Terminate(testcontext.Get(n.t)); err != nil {
return err
}
n.NodeConfig = cfg
@@ -138,7 +139,7 @@ func (n *ClNode) PrimaryETHAddress() (string, error) {
func (n *ClNode) AddBootstrapJob(verifierAddr common.Address, chainId int64,
feedId [32]byte) (*client.Job, error) {
- spec := utils.BuildBootstrapSpec(verifierAddr, chainId, feedId)
+ spec := it_utils.BuildBootstrapSpec(verifierAddr, chainId, feedId)
return n.API.MustCreateJob(spec)
}
@@ -166,7 +167,7 @@ func (n *ClNode) AddMercuryOCRJob(verifierAddr common.Address, fromBlock uint64,
}
}
- bridges := utils.BuildBridges(eaUrls)
+ bridges := it_utils.BuildBridges(eaUrls)
for index := range bridges {
err = n.API.MustCreateBridge(&bridges[index])
if err != nil {
@@ -181,7 +182,7 @@ func (n *ClNode) AddMercuryOCRJob(verifierAddr common.Address, fromBlock uint64,
allowedFaults = 2
}
- spec := utils.BuildOCRSpec(
+ spec := it_utils.BuildOCRSpec(
verifierAddr, chainId, fromBlock, feedId, bridges,
csaPubKey, mercuryServerUrl, mercuryServerPubKey, nodeOCRKeyId[0],
bootstrapUrl, allowedFaults)
@@ -190,7 +191,7 @@ func (n *ClNode) AddMercuryOCRJob(verifierAddr common.Address, fromBlock uint64,
}
func (n *ClNode) GetContainerName() string {
- name, err := n.Container.Name(utils.TestContext(n.t))
+ name, err := n.Container.Name(testcontext.Get(n.t))
if err != nil {
return ""
}
@@ -282,15 +283,15 @@ func (n *ClNode) StartContainer() error {
return fmt.Errorf("%s err: %w", ErrStartCLNodeContainer, err)
}
if n.lw != nil {
- if err := n.lw.ConnectContainer(utils.TestContext(n.t), container, "cl-node", true); err != nil {
+ if err := n.lw.ConnectContainer(testcontext.Get(n.t), container, "cl-node", true); err != nil {
return err
}
}
- clEndpoint, err := test_env.GetEndpoint(utils.TestContext(n.t), container, "http")
+ clEndpoint, err := test_env.GetEndpoint(testcontext.Get(n.t), container, "http")
if err != nil {
return err
}
- ip, err := container.ContainerIP(utils.TestContext(n.t))
+ ip, err := container.ContainerIP(testcontext.Get(n.t))
if err != nil {
return err
}
diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go
index 9987bab2fe..6278ec1398 100644
--- a/integration-tests/docker/test_env/test_env.go
+++ b/integration-tests/docker/test_env/test_env.go
@@ -22,11 +22,11 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/logwatch"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -266,7 +266,7 @@ func (te *CLClusterTestEnv) collectTestLogs() error {
return err
}
defer logFile.Close()
- logReader, err := node.Container.Logs(utils.TestContext(te.t))
+ logReader, err := node.Container.Logs(testcontext.Get(te.t))
if err != nil {
return err
}
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index a450dd235a..99dd990bec 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -23,7 +23,7 @@ require (
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd
- github.com/smartcontractkit/chainlink-testing-framework v1.18.6
+ github.com/smartcontractkit/chainlink-testing-framework v1.19.0
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index f882a7bb57..0402b12f3f 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2375,8 +2375,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.6 h1:UL3DxsPflSRALP62rsg5v3NdOsa8RHGhHMUImoWDD6k=
-github.com/smartcontractkit/chainlink-testing-framework v1.18.6/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.19.0 h1:ungyY1gYcXCtmdX2yCon8pkx9HgPPLg4aNAhKNZFP5c=
+github.com/smartcontractkit/chainlink-testing-framework v1.19.0/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/load/vrfv2/onchain_monitoring.go b/integration-tests/load/vrfv2/onchain_monitoring.go
index 879c7089e1..66af1807ac 100644
--- a/integration-tests/load/vrfv2/onchain_monitoring.go
+++ b/integration-tests/load/vrfv2/onchain_monitoring.go
@@ -7,8 +7,9 @@ import (
"github.com/rs/zerolog/log"
"github.com/smartcontractkit/wasp"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
/* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */
@@ -36,7 +37,7 @@ func MonitorLoadStats(t *testing.T, vrfv2Contracts *vrfv2_actions.VRFV2Contracts
}
for {
time.Sleep(1 * time.Second)
- metrics, err := vrfv2Contracts.LoadTestConsumer.GetLoadTestMetrics(utils.TestContext(t))
+ metrics, err := vrfv2Contracts.LoadTestConsumer.GetLoadTestMetrics(testcontext.Get(t))
if err != nil {
log.Error().Err(err).Msg(ErrMetrics)
}
diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
index e7734fee0d..11e160297f 100644
--- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go
+++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go
@@ -14,8 +14,8 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus"
@@ -99,7 +99,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
Str("Returning funds from SubID", subID.String()).
Str("Returning funds to", eoaWalletAddress).
Msg("Canceling subscription and returning funds to subscription owner")
- pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(utils.TestContext(t), subID)
+ pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(testcontext.Get(t), subID)
if err != nil {
l.Error().Err(err).Msg("Error checking if pending requests exist")
}
@@ -230,7 +230,7 @@ func TestVRFV2PlusPerformance(t *testing.T) {
l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test")
for _, subID := range subIDs {
- subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err, "error getting subscription information for subscription %s", subID.String())
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
}
diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go
index c851f36ec6..d1f07a52b7 100644
--- a/integration-tests/migration/upgrade_version_test.go
+++ b/integration-tests/migration/upgrade_version_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-testing-framework/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
)
@@ -19,9 +19,9 @@ func TestVersionUpgrade(t *testing.T) {
Build()
require.NoError(t, err)
- upgradeImage, err := utils.GetEnv("UPGRADE_IMAGE")
+ upgradeImage, err := osutil.GetEnv("UPGRADE_IMAGE")
require.NoError(t, err, "Error getting upgrade image")
- upgradeVersion, err := utils.GetEnv("UPGRADE_VERSION")
+ upgradeVersion, err := osutil.GetEnv("UPGRADE_VERSION")
require.NoError(t, err, "Error getting upgrade version")
_ = os.Setenv("CHAINLINK_IMAGE", upgradeImage)
diff --git a/integration-tests/performance/cron_test.go b/integration-tests/performance/cron_test.go
index 7e90d29221..38d861cee0 100644
--- a/integration-tests/performance/cron_test.go
+++ b/integration-tests/performance/cron_test.go
@@ -121,7 +121,7 @@ func setupCronTest(t *testing.T) (testEnvironment *environment.Environment) {
HTTPWriteTimout = '300s'`
cd := chainlink.New(0, map[string]interface{}{
"replicas": 1,
- "toml": client.AddNetworksConfig(baseTOML, network),
+ "toml": networks.AddNetworksConfig(baseTOML, network),
})
testEnvironment = environment.New(&environment.Config{
diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go
index 1a3f1d2a01..0fe1ca37e1 100644
--- a/integration-tests/performance/directrequest_test.go
+++ b/integration-tests/performance/directrequest_test.go
@@ -19,12 +19,12 @@ import (
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
"github.com/google/uuid"
)
@@ -108,7 +108,7 @@ func TestDirectRequestPerformance(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
gom.Eventually(func(g gomega.Gomega) {
- d, err := consumer.Data(utils.TestContext(t))
+ d, err := consumer.Data(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail")
g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil")
l.Debug().Int64("Data", d.Int64()).Msg("Found on chain")
@@ -142,7 +142,7 @@ func setupDirectRequestTest(t *testing.T) (testEnvironment *environment.Environm
HTTPWriteTimout = '300s'`
cd := chainlink.New(0, map[string]interface{}{
"replicas": 1,
- "toml": client.AddNetworksConfig(baseTOML, network),
+ "toml": networks.AddNetworksConfig(baseTOML, network),
})
testEnvironment = environment.New(&environment.Config{
diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go
index 18b13ab907..5fa31b626a 100644
--- a/integration-tests/performance/flux_test.go
+++ b/integration-tests/performance/flux_test.go
@@ -20,12 +20,12 @@ import (
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestFluxPerformance(t *testing.T) {
@@ -83,7 +83,7 @@ func TestFluxPerformance(t *testing.T) {
require.NoError(t, err, "Setting oracle options in the Flux Aggregator contract shouldn't fail")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- oracles, err := fluxInstance.GetOracles(utils.TestContext(t))
+ oracles, err := fluxInstance.GetOracles(testcontext.Get(t))
require.NoError(t, err, "Getting oracle details from the Flux aggregator contract shouldn't fail")
l.Info().Str("Oracles", strings.Join(oracles, ",")).Msg("Oracles set")
@@ -120,7 +120,7 @@ func TestFluxPerformance(t *testing.T) {
chainClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound)
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err := fluxInstance.GetContractData(utils.TestContext(t))
+ data, err := fluxInstance.GetContractData(testcontext.Get(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
l.Info().Interface("Data", data).Msg("Round data")
require.Equal(t, int64(1e5), data.LatestRoundData.Answer.Int64(),
@@ -140,7 +140,7 @@ func TestFluxPerformance(t *testing.T) {
require.NoError(t, err, "Setting value path in mock server shouldn't fail")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err = fluxInstance.GetContractData(utils.TestContext(t))
+ data, err = fluxInstance.GetContractData(testcontext.Get(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
require.Equal(t, int64(1e10), data.LatestRoundData.Answer.Int64(),
"Expected latest round answer to be %d, but found %d", int64(1e10), data.LatestRoundData.Answer.Int64())
@@ -153,7 +153,7 @@ func TestFluxPerformance(t *testing.T) {
l.Info().Interface("data", data).Msg("Round data")
for _, oracleAddr := range nodeAddresses {
- payment, _ := fluxInstance.WithdrawablePayment(utils.TestContext(t), oracleAddr)
+ payment, _ := fluxInstance.WithdrawablePayment(testcontext.Get(t), oracleAddr)
require.Equal(t, int64(2), payment.Int64(),
"Expected flux aggregator contract's withdrawable payment to be %d, but found %d", int64(2), payment.Int64())
}
@@ -189,7 +189,7 @@ HTTPWriteTimout = '300s'
Enabled = true`
cd := chainlink.New(0, map[string]interface{}{
"replicas": 3,
- "toml": client.AddNetworksConfig(baseTOML, testNetwork),
+ "toml": networks.AddNetworksConfig(baseTOML, testNetwork),
})
testEnvironment = environment.New(&environment.Config{
diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go
index 8e273a96f6..ac6e9e6a57 100644
--- a/integration-tests/performance/keeper_test.go
+++ b/integration-tests/performance/keeper_test.go
@@ -19,13 +19,13 @@ import (
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var keeperDefaultRegistryConfig = contracts.KeeperRegistrySettings{
@@ -74,7 +74,7 @@ func TestKeeperPerformance(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
"Expected consumer counter to be greater than 10, but got %d", counter.Int64())
@@ -95,7 +95,7 @@ func TestKeeperPerformance(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterCancellation[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterCancellation[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Index", i).Int64("Upkeeps Performed", countersAfterCancellation[i].Int64()).Msg("Cancelled Upkeep")
}
@@ -103,7 +103,7 @@ func TestKeeperPerformance(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant because the upkeep was cancelled, so it shouldn't increase anymore
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterCancellation[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -155,7 +155,7 @@ PerformGasOverhead = 150_000`
networkName := strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")
cd := chainlink.New(0, map[string]interface{}{
"replicas": 5,
- "toml": client.AddNetworksConfig(baseTOML, network),
+ "toml": networks.AddNetworksConfig(baseTOML, network),
})
testEnvironment := environment.New(
diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go
index 47879cebb8..7f91f4321a 100644
--- a/integration-tests/performance/ocr_test.go
+++ b/integration-tests/performance/ocr_test.go
@@ -17,14 +17,13 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
-
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCRBasic(t *testing.T) {
@@ -64,7 +63,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(1, ocrInstances, chainClient, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -73,7 +72,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(2, ocrInstances, chainClient, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
@@ -113,7 +112,7 @@ ListenIP = '0.0.0.0'
ListenPort = 6690`
cd := chainlink.New(0, map[string]interface{}{
"replicas": 6,
- "toml": client.AddNetworksConfig(baseTOML, testNetwork),
+ "toml": networks.AddNetworksConfig(baseTOML, testNetwork),
})
testEnvironment = environment.New(&environment.Config{
diff --git a/integration-tests/performance/vrf_test.go b/integration-tests/performance/vrf_test.go
index 7a38a45495..cad4ea5eeb 100644
--- a/integration-tests/performance/vrf_test.go
+++ b/integration-tests/performance/vrf_test.go
@@ -17,12 +17,12 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFBasic(t *testing.T) {
@@ -97,7 +97,7 @@ func TestVRFBasic(t *testing.T) {
encodedProvingKeys := make([][2]*big.Int, 0)
encodedProvingKeys = append(encodedProvingKeys, provingKey)
- requestHash, err := coordinator.HashOfKey(utils.TestContext(t), encodedProvingKeys[0])
+ requestHash, err := coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0])
require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail")
err = consumer.RequestRandomness(requestHash, big.NewInt(1))
require.NoError(t, err, "Requesting randomness shouldn't fail")
@@ -108,7 +108,7 @@ func TestVRFBasic(t *testing.T) {
jobRuns, err := chainlinkNodes[0].MustReadRunsByJob(job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
- out, err := consumer.RandomnessOutput(utils.TestContext(t))
+ out, err := consumer.RandomnessOutput(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
// Checks that the job has actually run
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
@@ -147,7 +147,7 @@ func setupVRFTest(t *testing.T) (testEnvironment *environment.Environment, testN
baseTOML := `[WebServer]
HTTPWriteTimout = '300s'`
cd := chainlink.New(0, map[string]interface{}{
- "toml": client.AddNetworksConfig(baseTOML, testNetwork),
+ "toml": networks.AddNetworksConfig(baseTOML, testNetwork),
})
testEnvironment = environment.New(&environment.Config{
diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go
index 58cd147201..dae977d3ee 100644
--- a/integration-tests/reorg/automation_reorg_test.go
+++ b/integration-tests/reorg/automation_reorg_test.go
@@ -18,12 +18,12 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -49,7 +49,7 @@ Mode = 'FixedPrice'
LimitDefault = 5_000_000`
activeEVMNetwork = networks.MustGetSelectedNetworksFromEnv()[0]
defaultAutomationSettings = map[string]interface{}{
- "toml": client.AddNetworkDetailedConfig(baseTOML, networkTOML, activeEVMNetwork),
+ "toml": networks.AddNetworkDetailedConfig(baseTOML, networkTOML, activeEVMNetwork),
"db": map[string]interface{}{
"stateful": false,
"capacity": "1Gi",
@@ -210,7 +210,7 @@ func TestAutomationReorg(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(it_utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
@@ -241,7 +241,7 @@ func TestAutomationReorg(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(it_utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 10
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
@@ -258,7 +258,7 @@ func TestAutomationReorg(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 20
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(it_utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 20
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
diff --git a/integration-tests/reorg/reorg_confirmer.go b/integration-tests/reorg/reorg_confirmer.go
index 2193131680..a5659e6678 100644
--- a/integration-tests/reorg/reorg_confirmer.go
+++ b/integration-tests/reorg/reorg_confirmer.go
@@ -15,8 +15,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
-
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
)
// The steps are:
@@ -232,8 +231,8 @@ func (rc *ReorgController) forkNetwork(header blockchain.NodeHeader) error {
rc.cfg.Env.Cfg.Namespace,
&chaos.Props{
DurationStr: "999h",
- FromLabels: &map[string]*string{"app": utils.Ptr(reorg.TXNodesAppLabel)},
- ToLabels: &map[string]*string{"app": utils.Ptr(reorg.MinerNodesAppLabel)},
+ FromLabels: &map[string]*string{"app": ptr.Ptr(reorg.TXNodesAppLabel)},
+ ToLabels: &map[string]*string{"app": ptr.Ptr(reorg.MinerNodesAppLabel)},
},
))
rc.chaosExperimentName = expName
diff --git a/integration-tests/reorg/reorg_test.go b/integration-tests/reorg/reorg_test.go
index d5fefdbc56..fc35047d0e 100644
--- a/integration-tests/reorg/reorg_test.go
+++ b/integration-tests/reorg/reorg_test.go
@@ -9,6 +9,8 @@ import (
"time"
"github.com/google/uuid"
+ "github.com/onsi/gomega"
+ "github.com/rs/zerolog/log"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
@@ -21,16 +23,12 @@ import (
mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
-
- "github.com/onsi/gomega"
- "github.com/rs/zerolog/log"
-
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
const (
@@ -127,7 +125,7 @@ func TestDirectRequestReorg(t *testing.T) {
netCfg := fmt.Sprintf(networkDRTOML, EVMFinalityDepth, EVMTrackerHistoryDepth)
chainlinkDeployment := chainlink.New(0, map[string]interface{}{
"replicas": 1,
- "toml": client.AddNetworkDetailedConfig(baseDRTOML, netCfg, activeEVMNetwork),
+ "toml": networks.AddNetworkDetailedConfig(baseDRTOML, netCfg, activeEVMNetwork),
})
err = testEnvironment.AddHelm(chainlinkDeployment).Run()
@@ -221,7 +219,7 @@ func TestDirectRequestReorg(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
gom.Eventually(func(g gomega.Gomega) {
- d, err := consumer.Data(it_utils.TestContext(t))
+ d, err := consumer.Data(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail")
g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil")
log.Debug().Int64("Data", d.Int64()).Msg("Found on chain")
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 87074e786d..05d19d5ccd 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -22,6 +22,8 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
@@ -33,7 +35,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var utilsABI = cltypes.MustGetABI(automation_utils_2_1.AutomationUtilsABI)
@@ -171,7 +172,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Number of upkeeps performed")
@@ -193,7 +194,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are increasing by 5 in each step within 5 minutes
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)),
@@ -216,7 +217,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterCancellation[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterCancellation[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeep Count", countersAfterCancellation[i].Int64()).Int("Upkeep Index", i).Msg("Cancelled upkeep")
}
@@ -225,7 +226,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) {
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant (At most increase by 1 to account for stale performs) because the upkeep was cancelled
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterCancellation[i].Int64()+1),
"Expected consumer counter to remain less than or equal to %d, but got %d",
@@ -271,7 +272,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := 5
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Number of upkeeps performed")
@@ -328,7 +329,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
time.Sleep(10 * time.Second)
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterSetNoMatch[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterSetNoMatch[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeep Count", countersAfterSetNoMatch[i].Int64()).Int("Upkeep Index", i).Msg("Upkeep")
}
@@ -338,7 +339,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant (At most increase by 2 to account for stale performs) because the upkeep trigger config is not met
bufferCount := int64(2)
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterSetNoMatch[i].Int64()+bufferCount),
"Expected consumer counter to remain less than or equal to %d, but got %d",
@@ -374,7 +375,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterSetMatch[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterSetMatch[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int64("Upkeep Count", countersAfterSetMatch[i].Int64()).Int("Upkeep Index", i).Msg("Upkeep")
}
@@ -393,7 +394,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
expect := int64(5)
l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Number of upkeeps performed")
@@ -424,7 +425,7 @@ func TestAutomationAddFunds(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
// Since the upkeep is currently underfunded, check that it doesn't get executed
gom.Consistently(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(utils.TestContext(t))
+ counter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
"Expected consumer counter to remain zero, but got %d", counter.Int64())
@@ -444,7 +445,7 @@ func TestAutomationAddFunds(t *testing.T) {
// Now the new upkeep should be performing because we added enough funds
gom.Eventually(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(utils.TestContext(t))
+ counter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -476,7 +477,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)),
"Expected consumer counter to be greater than 5, but got %d", counter.Int64())
@@ -496,7 +497,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterPause[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Upkeep Index", i).Int64("Upkeeps Performed", countersAfterPause[i].Int64()).Msg("Paused Upkeep")
}
@@ -505,7 +506,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// In most cases counters should remain constant, but there might be a straggling perform tx which
// gets committed later and increases counter by 1
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterPause[i].Int64()+1),
"Expected consumer counter not have increased more than %d, but got %d",
@@ -525,7 +526,7 @@ func TestAutomationPauseUnPause(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5 + numbers of performing before pause
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", countersAfterPause[i].Int64()+1),
"Expected consumer counter to be greater than %d, but got %d", countersAfterPause[i].Int64()+1, counter.Int64())
@@ -561,7 +562,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
// store the value of their initial counters in order to compare later on that the value increased.
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -581,7 +582,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
// Test that the newly registered upkeep is also performing.
gom.Eventually(func(g gomega.Gomega) {
- counter, err := newUpkeep.Counter(utils.TestContext(t))
+ counter, err := newUpkeep.Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling newly deployed upkeep's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -590,7 +591,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(utils.TestContext(t))
+ currentCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().
@@ -630,7 +631,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
// Observe that the upkeeps which are initially registered are performing
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d")
@@ -646,7 +647,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
// Store how many times each upkeep performed once the registry was successfully paused
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterPause[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
}
@@ -654,7 +655,7 @@ func TestAutomationPauseRegistry(t *testing.T) {
// because they are no longer getting serviced
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterPause[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -691,7 +692,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// Watch upkeeps being performed and store their counters in order to compare them later in the test
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -710,7 +711,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// Assert that upkeeps are still performed and their counters have increased
gom.Eventually(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(utils.TestContext(t))
+ currentCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", initialCounters[i].Int64()),
"Expected counter to have increased from initial value of %s, but got %s",
@@ -731,7 +732,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// See how many times each upkeep was executed
var countersAfterNoMoreNodes = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterNoMoreNodes[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterNoMoreNodes[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Upkeep Index", i).Int64("Performed", countersAfterNoMoreNodes[i].Int64()).Msg("Upkeeps Performed")
}
@@ -740,7 +741,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) {
// all the nodes were taken down
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterNoMoreNodes[i].Int64()+1),
"Expected consumer counter to not have increased more than %d, but got %d",
@@ -789,7 +790,7 @@ func TestAutomationPerformSimulation(t *testing.T) {
// Initially performGas is set high, so performUpkeep reverts and no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
// Consumer count should remain at 0
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.Equal(int64(0)),
"Expected consumer counter to remain constant at %d, but got %d", 0, cnt.Int64(),
@@ -797,14 +798,14 @@ func TestAutomationPerformSimulation(t *testing.T) {
}, "2m", "1s").Should(gomega.Succeed()) // ~1m for setup, 1m assertion
// Set performGas on consumer to be low, so that performUpkeep starts becoming successful
- err := consumerPerformance.SetPerformGasToBurn(utils.TestContext(t), big.NewInt(100000))
+ err := consumerPerformance.SetPerformGasToBurn(testcontext.Get(t), big.NewInt(100000))
require.NoError(t, err, "Perform gas should be set successfully on consumer")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for set perform gas tx")
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -854,7 +855,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
// Initially performGas is set higher than defaultUpkeepGasLimit, so no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.Equal(int64(0)),
@@ -870,7 +871,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -878,19 +879,19 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
}, "2m", "1s").Should(gomega.Succeed()) // ~1m to perform once, 1m buffer
// Now increase the checkGasBurn on consumer, upkeep should stop performing
- err = consumerPerformance.SetCheckGasToBurn(utils.TestContext(t), big.NewInt(3000000))
+ err = consumerPerformance.SetCheckGasToBurn(testcontext.Get(t), big.NewInt(3000000))
require.NoError(t, err, "Check gas burn should be set successfully on consumer")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for SetCheckGasToBurn tx")
// Get existing performed count
- existingCnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ existingCnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
require.NoError(t, err, "Calling consumer's counter shouldn't fail")
l.Info().Int64("Upkeep counter", existingCnt.Int64()).Msg("Upkeep counter when check gas increased")
// In most cases count should remain constant, but it might increase by upto 1 due to pending perform
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.BeNumerically("<=", existingCnt.Int64()+1),
@@ -898,7 +899,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
)
}, "1m", "1s").Should(gomega.Succeed())
- existingCnt, err = consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ existingCnt, err = consumerPerformance.GetUpkeepCount(testcontext.Get(t))
require.NoError(t, err, "Calling consumer's counter shouldn't fail")
existingCntInt := existingCnt.Int64()
l.Info().Int64("Upkeep counter", existingCntInt).Msg("Upkeep counter when consistently block finished")
@@ -918,7 +919,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) {
// Upkeep should start performing again, and it should get regularly performed
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", existingCntInt),
"Expected consumer counter to be greater than %d, but got %d", existingCntInt, cnt.Int64(),
@@ -962,7 +963,7 @@ func TestUpdateCheckData(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
// expect the counter to remain 0 because perform data does not match
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(utils.TestContext(t))
+ counter, err := performDataChecker[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker"+
" for upkeep at index "+strconv.Itoa(i))
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
@@ -981,7 +982,7 @@ func TestUpdateCheckData(t *testing.T) {
// retrieve new check data for all upkeeps
for i := 0; i < len(upkeepIDs); i++ {
- upkeep, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepIDs[i])
+ upkeep, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepIDs[i])
require.NoError(t, err, "Failed to get upkeep info at index %d", i)
require.Equal(t, []byte(automationExpectedData), upkeep.CheckData, "Upkeep data not as expected")
}
@@ -989,7 +990,7 @@ func TestUpdateCheckData(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(utils.TestContext(t))
+ counter, err := performDataChecker[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker counter"+
" for upkeep at index "+strconv.Itoa(i))
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -1030,11 +1031,11 @@ func setupAutomationTestDocker(
// build the node config
clNodeConfig := node.NewConfig(node.NewBaseConfig())
syncInterval := models.MustMakeDuration(5 * time.Minute)
- clNodeConfig.Feature.LogPoller = utils.Ptr[bool](true)
- clNodeConfig.OCR2.Enabled = utils.Ptr[bool](true)
- clNodeConfig.Keeper.TurnLookBack = utils.Ptr[int64](int64(0))
+ clNodeConfig.Feature.LogPoller = ptr.Ptr[bool](true)
+ clNodeConfig.OCR2.Enabled = ptr.Ptr[bool](true)
+ clNodeConfig.Keeper.TurnLookBack = ptr.Ptr[int64](int64(0))
clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval
- clNodeConfig.Keeper.Registry.PerformGasOverhead = utils.Ptr[uint32](uint32(150000))
+ clNodeConfig.Keeper.Registry.PerformGasOverhead = ptr.Ptr[uint32](uint32(150000))
clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"}
clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"}
diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go
index 2997ff1c74..72dc15e7b1 100644
--- a/integration-tests/smoke/flux_test.go
+++ b/integration-tests/smoke/flux_test.go
@@ -13,12 +13,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestFluxBasic(t *testing.T) {
@@ -74,7 +74,7 @@ func TestFluxBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- oracles, err := fluxInstance.GetOracles(utils.TestContext(t))
+ oracles, err := fluxInstance.GetOracles(testcontext.Get(t))
require.NoError(t, err, "Getting oracle details from the Flux aggregator contract shouldn't fail")
l.Info().Str("Oracles", strings.Join(oracles, ",")).Msg("Oracles set")
@@ -108,7 +108,7 @@ func TestFluxBasic(t *testing.T) {
env.EVMClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound)
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err := fluxInstance.GetContractData(utils.TestContext(t))
+ data, err := fluxInstance.GetContractData(testcontext.Get(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
require.Equal(t, int64(1e5), data.LatestRoundData.Answer.Int64(),
"Expected latest round answer to be %d, but found %d", int64(1e5), data.LatestRoundData.Answer.Int64())
@@ -127,7 +127,7 @@ func TestFluxBasic(t *testing.T) {
require.NoError(t, err, "Setting value path in mock server shouldn't fail")
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail")
- data, err = fluxInstance.GetContractData(utils.TestContext(t))
+ data, err = fluxInstance.GetContractData(testcontext.Get(t))
require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail")
require.Equal(t, int64(1e10), data.LatestRoundData.Answer.Int64(),
"Expected latest round answer to be %d, but found %d", int64(1e10), data.LatestRoundData.Answer.Int64())
@@ -140,7 +140,7 @@ func TestFluxBasic(t *testing.T) {
l.Info().Interface("data", data).Msg("Round data")
for _, oracleAddr := range nodeAddresses {
- payment, _ := fluxInstance.WithdrawablePayment(utils.TestContext(t), oracleAddr)
+ payment, _ := fluxInstance.WithdrawablePayment(testcontext.Get(t), oracleAddr)
require.Equal(t, int64(2), payment.Int64(),
"Expected flux aggregator contract's withdrawable payment to be %d, but found %d", int64(2), payment.Int64())
}
diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go
index 7203e03178..d4f9b5884a 100644
--- a/integration-tests/smoke/forwarder_ocr_test.go
+++ b/integration-tests/smoke/forwarder_ocr_test.go
@@ -8,10 +8,10 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestForwarderOCRBasic(t *testing.T) {
@@ -72,7 +72,7 @@ func TestForwarderOCRBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
- answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -83,7 +83,7 @@ func TestForwarderOCRBasic(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")
- answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go
index be87eb5629..c9fe3cb11d 100644
--- a/integration-tests/smoke/forwarders_ocr2_test.go
+++ b/integration-tests/smoke/forwarders_ocr2_test.go
@@ -11,12 +11,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestForwarderOCR2Basic(t *testing.T) {
@@ -92,7 +92,7 @@ func TestForwarderOCR2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(1, ocrInstances, env.EVMClient, time.Minute*10, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Getting latest answer from OCRv2 contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCRw contract to be 5 but got %d", answer.Int64())
@@ -103,7 +103,7 @@ func TestForwarderOCR2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(int64(i), ocrInstances, env.EVMClient, time.Minute*10, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Error getting latest OCRv2 answer")
require.Equal(t, int64(ocrRoundVal), answer.Int64(), fmt.Sprintf("Expected latest answer from OCRv2 contract to be %d but got %d", ocrRoundVal, answer.Int64()))
}
diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go
index 6f892e60ac..bcf64a5feb 100644
--- a/integration-tests/smoke/keeper_test.go
+++ b/integration-tests/smoke/keeper_test.go
@@ -13,6 +13,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
@@ -22,7 +23,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
const (
@@ -109,7 +109,7 @@ func TestKeeperBasicSmoke(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
"Expected consumer counter to be greater than 10, but got %d", counter.Int64())
@@ -131,7 +131,7 @@ func TestKeeperBasicSmoke(t *testing.T) {
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterCancellation[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterCancellation[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i)
l.Info().Int("Index", i).Int64("Upkeeps Performed", countersAfterCancellation[i].Int64()).Msg("Cancelled Upkeep")
}
@@ -139,7 +139,7 @@ func TestKeeperBasicSmoke(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
// Expect the counter to remain constant because the upkeep was cancelled, so it shouldn't increase anymore
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterCancellation[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -187,11 +187,11 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
// Wait for upkeep to be performed twice by different keepers (buddies)
gom.Eventually(func(g gomega.Gomega) error {
- counter, err := consumers[0].Counter(utils.TestContext(t))
+ counter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed")
- upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -205,7 +205,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
}, "1m", "1s").Should(gomega.Succeed())
gom.Eventually(func(g gomega.Gomega) error {
- upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -219,7 +219,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
// Expect no new keepers to perform for a while
gom.Consistently(func(g gomega.Gomega) {
- upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -235,11 +235,11 @@ func TestKeeperBlockCountPerTurn(t *testing.T) {
// Expect a new keeper to perform
gom.Eventually(func(g gomega.Gomega) error {
- counter, err := consumers[0].Counter(utils.TestContext(t))
+ counter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Num upkeeps performed")
- upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
latestKeeper := upkeepInfo.LastKeeper
@@ -296,7 +296,7 @@ func TestKeeperSimulation(t *testing.T) {
// Initially performGas is set high, so performUpkeep reverts and no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
// Consumer count should remain at 0
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.Equal(int64(0)),
@@ -304,20 +304,20 @@ func TestKeeperSimulation(t *testing.T) {
)
// Not even reverted upkeeps should be performed. Last keeper for the upkeep should be 0 address
- upkeepInfo, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepID)
+ upkeepInfo, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail")
g.Expect(upkeepInfo.LastKeeper).Should(gomega.Equal(actions.ZeroAddress.String()), "Last keeper should be zero address")
}, "1m", "1s").Should(gomega.Succeed())
// Set performGas on consumer to be low, so that performUpkeep starts becoming successful
- err = consumerPerformance.SetPerformGasToBurn(utils.TestContext(t), big.NewInt(100000))
+ err = consumerPerformance.SetPerformGasToBurn(testcontext.Get(t), big.NewInt(100000))
require.NoError(t, err, "Error setting PerformGasToBurn")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting to set PerformGasToBurn")
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) error {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -368,7 +368,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// Initially performGas is set higher than defaultUpkeepGasLimit, so no upkeep should be performed
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.Equal(int64(0)),
@@ -384,7 +384,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// Upkeep should now start performing
gom.Eventually(func(g gomega.Gomega) error {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d", cnt.Int64(),
@@ -393,13 +393,13 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
}, "1m", "1s").Should(gomega.Succeed())
// Now increase the checkGasBurn on consumer, upkeep should stop performing
- err = consumerPerformance.SetCheckGasToBurn(utils.TestContext(t), big.NewInt(3000000))
+ err = consumerPerformance.SetCheckGasToBurn(testcontext.Get(t), big.NewInt(3000000))
require.NoError(t, err, "Error setting CheckGasToBurn")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for SetCheckGasToBurn tx")
// Get existing performed count
- existingCnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ existingCnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
require.NoError(t, err, "Error calling consumer's counter")
l.Info().Int64("Upkeep counter", existingCnt.Int64()).Msg("Check Gas Increased")
@@ -407,7 +407,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// gets committed later. Since every keeper node cannot have more than 1 straggling tx, it
// is sufficient to check that the upkeep count does not increase by more than 6.
gom.Consistently(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(cnt.Int64()).Should(
gomega.BeNumerically("<=", existingCnt.Int64()+numUpkeepsAllowedForStragglingTxs),
@@ -415,7 +415,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
)
}, "3m", "1s").Should(gomega.Succeed())
- existingCnt, err = consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ existingCnt, err = consumerPerformance.GetUpkeepCount(testcontext.Get(t))
require.NoError(t, err, "Error calling consumer's counter")
existingCntInt := existingCnt.Int64()
l.Info().Int64("Upkeep counter", existingCntInt).Msg("Upkeep counter when consistently block finished")
@@ -430,7 +430,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) {
// Upkeep should start performing again, and it should get regularly performed
gom.Eventually(func(g gomega.Gomega) {
- cnt, err := consumerPerformance.GetUpkeepCount(utils.TestContext(t))
+ cnt, err := consumerPerformance.GetUpkeepCount(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail")
g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", existingCntInt),
"Expected consumer counter to be greater than %d, but got %d", existingCntInt, cnt.Int64(),
@@ -478,7 +478,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) {
// store the value of their initial counters in order to compare later on that the value increased.
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+
" for upkeep at index "+strconv.Itoa(i))
@@ -500,7 +500,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) {
// Test that the newly registered upkeep is also performing.
gom.Eventually(func(g gomega.Gomega) error {
- counter, err := newUpkeep.Counter(utils.TestContext(t))
+ counter, err := newUpkeep.Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling newly deployed upkeep's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -510,7 +510,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(utils.TestContext(t))
+ currentCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
l.Info().
@@ -563,7 +563,7 @@ func TestKeeperAddFunds(t *testing.T) {
// Since the upkeep is currently underfunded, check that it doesn't get executed
gom.Consistently(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(utils.TestContext(t))
+ counter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
"Expected consumer counter to remain zero, but got %d", counter.Int64())
@@ -583,7 +583,7 @@ func TestKeeperAddFunds(t *testing.T) {
// Now the new upkeep should be performing because we added enough funds
gom.Eventually(func(g gomega.Gomega) {
- counter, err := consumers[0].Counter(utils.TestContext(t))
+ counter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64())
@@ -628,7 +628,7 @@ func TestKeeperRemove(t *testing.T) {
// Make sure the upkeeps are running before we remove a keeper
gom.Eventually(func(g gomega.Gomega) error {
for upkeepID := 0; upkeepID < len(upkeepIDs); upkeepID++ {
- counter, err := consumers[upkeepID].Counter(utils.TestContext(t))
+ counter, err := consumers[upkeepID].Counter(testcontext.Get(t))
initialCounters[upkeepID] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+
" for upkeep with ID "+strconv.Itoa(upkeepID))
@@ -637,7 +637,7 @@ func TestKeeperRemove(t *testing.T) {
return nil
}, "1m", "1s").Should(gomega.Succeed())
- keepers, err := registry.GetKeeperList(utils.TestContext(t))
+ keepers, err := registry.GetKeeperList(testcontext.Get(t))
require.NoError(t, err, "Error getting list of Keepers")
// Remove the first keeper from the list
@@ -660,7 +660,7 @@ func TestKeeperRemove(t *testing.T) {
// The upkeeps should still perform and their counters should have increased compared to the first check
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Cmp(initialCounters[i]) == 1, "Expected consumer counter to be greater "+
"than initial counter which was %s, but got %s", initialCounters[i], counter)
@@ -705,7 +705,7 @@ func TestKeeperPauseRegistry(t *testing.T) {
// Observe that the upkeeps which are initially registered are performing
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %d")
@@ -722,7 +722,7 @@ func TestKeeperPauseRegistry(t *testing.T) {
// Store how many times each upkeep performed once the registry was successfully paused
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterPause[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Error retrieving consumer at index %d", i)
}
@@ -730,7 +730,7 @@ func TestKeeperPauseRegistry(t *testing.T) {
// because they are no longer getting serviced
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Error retrieving consumer contract at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterPause[i].Int64()),
"Expected consumer counter to remain constant at %d, but got %d",
@@ -791,7 +791,7 @@ func TestKeeperMigrateRegistry(t *testing.T) {
// Check that the first upkeep from the first registry is performing (before being migrated)
gom.Eventually(func(g gomega.Gomega) error {
- counterBeforeMigration, err := consumers[0].Counter(utils.TestContext(t))
+ counterBeforeMigration, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(counterBeforeMigration.Int64()).Should(gomega.BeNumerically(">", int64(0)),
"Expected consumer counter to be greater than 0, but got %s", counterBeforeMigration)
@@ -810,12 +810,12 @@ func TestKeeperMigrateRegistry(t *testing.T) {
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting to pause first registry")
- counterAfterMigration, err := consumers[0].Counter(utils.TestContext(t))
+ counterAfterMigration, err := consumers[0].Counter(testcontext.Get(t))
require.NoError(t, err, "Error calling consumer's counter")
// Check that once we migrated the upkeep, the counter has increased
gom.Eventually(func(g gomega.Gomega) error {
- currentCounter, err := consumers[0].Counter(utils.TestContext(t))
+ currentCounter, err := consumers[0].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail")
g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", counterAfterMigration.Int64()),
"Expected counter to have increased, but stayed constant at %s", counterAfterMigration)
@@ -860,7 +860,7 @@ func TestKeeperNodeDown(t *testing.T) {
// Watch upkeeps being performed and store their counters in order to compare them later in the test
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
initialCounters[i] = counter
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)),
@@ -882,7 +882,7 @@ func TestKeeperNodeDown(t *testing.T) {
// Assert that upkeeps are still performed and their counters have increased
gom.Eventually(func(g gomega.Gomega) error {
for i := 0; i < len(upkeepIDs); i++ {
- currentCounter, err := consumers[i].Counter(utils.TestContext(t))
+ currentCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", initialCounters[i].Int64()),
"Expected counter to have increased from initial value of %s, but got %s",
@@ -908,7 +908,7 @@ func TestKeeperNodeDown(t *testing.T) {
// See how many times each upkeep was executed
var countersAfterNoMoreNodes = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
- countersAfterNoMoreNodes[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterNoMoreNodes[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Error retrieving consumer counter %d", i)
l.Info().
Int("Index", i).
@@ -921,7 +921,7 @@ func TestKeeperNodeDown(t *testing.T) {
// so a +6 on the upper limit side should be sufficient.
gom.Consistently(func(g gomega.Gomega) {
for i := 0; i < len(upkeepIDs); i++ {
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=",
countersAfterNoMoreNodes[i].Int64()+numUpkeepsAllowedForStragglingTxs,
@@ -964,7 +964,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)),
"Expected consumer counter to be greater than 5, but got %d", counter.Int64())
@@ -985,7 +985,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
var countersAfterPause = make([]*big.Int, len(upkeepIDs))
for i := 0; i < len(upkeepIDs); i++ {
// Obtain the amount of times the upkeep has been executed so far
- countersAfterPause[i], err = consumers[i].Counter(utils.TestContext(t))
+ countersAfterPause[i], err = consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Error retrieving upkeep count at index %d", i)
l.Info().
Int("Index", i).
@@ -998,7 +998,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
// In most cases counters should remain constant, but there might be a straggling perform tx which
// gets committed later. Since every keeper node cannot have more than 1 straggling tx, it
// is sufficient to check that the upkeep count does not increase by more than 6.
- latestCounter, err := consumers[i].Counter(utils.TestContext(t))
+ latestCounter, err := consumers[i].Counter(testcontext.Get(t))
require.NoError(t, err, "Error retrieving counter at index %d", i)
g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterPause[i].Int64()+numUpkeepsAllowedForStragglingTxs),
"Expected consumer counter not have increased more than %d, but got %d",
@@ -1018,7 +1018,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5 + numbers of performing before pause
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+
" for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)+countersAfterPause[i].Int64()),
@@ -1055,7 +1055,7 @@ func TestKeeperUpdateCheckData(t *testing.T) {
gom.Consistently(func(g gomega.Gomega) {
// expect the counter to remain 0 because perform data does not match
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(utils.TestContext(t))
+ counter, err := performDataChecker[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)),
"Expected perform data checker counter to be 0, but got %d", counter.Int64())
@@ -1073,7 +1073,7 @@ func TestKeeperUpdateCheckData(t *testing.T) {
// retrieve new check data for all upkeeps
for i := 0; i < len(upkeepIDs); i++ {
- upkeep, err := registry.GetUpkeepInfo(utils.TestContext(t), upkeepIDs[i])
+ upkeep, err := registry.GetUpkeepInfo(testcontext.Get(t), upkeepIDs[i])
require.NoError(t, err, "Error getting upkeep info from index %d", i)
require.Equal(t, []byte(keeperExpectedData), upkeep.CheckData, "Check data not as expected")
}
@@ -1081,7 +1081,7 @@ func TestKeeperUpdateCheckData(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := performDataChecker[i].Counter(utils.TestContext(t))
+ counter, err := performDataChecker[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(5)),
"Expected perform data checker counter to be greater than 5, but got %d", counter.Int64())
@@ -1154,7 +1154,7 @@ func TestKeeperJobReplacement(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
"Expected consumer counter to be greater than 10, but got %d", counter.Int64())
@@ -1183,7 +1183,7 @@ func TestKeeperJobReplacement(t *testing.T) {
gom.Eventually(func(g gomega.Gomega) error {
// Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10
for i := 0; i < len(upkeepIDs); i++ {
- counter, err := consumers[i].Counter(utils.TestContext(t))
+ counter, err := consumers[i].Counter(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i)
g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)),
"Expected consumer counter to be greater than 10, but got %d", counter.Int64())
diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go
index bec82e633f..0676ed0300 100644
--- a/integration-tests/smoke/ocr2_test.go
+++ b/integration-tests/smoke/ocr2_test.go
@@ -10,11 +10,11 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// Tests a basic OCRv2 median feed
@@ -72,7 +72,7 @@ func TestOCRv2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l)
require.NoError(t, err, "Error starting new OCR2 round")
- roundData, err := aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(1))
+ roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 5 but got %d",
@@ -84,7 +84,7 @@ func TestOCRv2Basic(t *testing.T) {
err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l)
require.NoError(t, err)
- roundData, err = aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(2))
+ roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 10 but got %d",
@@ -146,7 +146,7 @@ func TestOCRv2JobReplacement(t *testing.T) {
err = actions.StartNewOCR2Round(1, aggregatorContracts, env.EVMClient, time.Minute*5, l)
require.NoError(t, err, "Error starting new OCR2 round")
- roundData, err := aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(1))
+ roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 5 but got %d",
@@ -158,7 +158,7 @@ func TestOCRv2JobReplacement(t *testing.T) {
err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l)
require.NoError(t, err)
- roundData, err = aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(2))
+ roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 10 but got %d",
@@ -176,7 +176,7 @@ func TestOCRv2JobReplacement(t *testing.T) {
err = actions.StartNewOCR2Round(3, aggregatorContracts, env.EVMClient, time.Minute*3, l)
require.NoError(t, err, "Error starting new OCR2 round")
- roundData, err = aggregatorContracts[0].GetRound(utils.TestContext(t), big.NewInt(3))
+ roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(3))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(15), roundData.Answer.Int64(),
"Expected latest answer from OCR contract to be 15 but got %d",
diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go
index 57bd5412b1..773476826c 100644
--- a/integration-tests/smoke/ocr2vrf_test.go
+++ b/integration-tests/smoke/ocr2vrf_test.go
@@ -15,6 +15,7 @@ import (
eth "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions"
@@ -22,7 +23,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCR2VRFRedeemModel(t *testing.T) {
@@ -80,7 +80,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(testcontext.Get(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err)
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness retrieved from Consumer contract give an answer other than 0")
@@ -141,7 +141,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) {
)
for i := uint16(0); i < ocr2vrf_constants.NumberOfRandomWordsToRequest; i++ {
- randomness, err := consumerContract.GetRandomnessByRequestId(it_utils.TestContext(t), requestID, big.NewInt(int64(i)))
+ randomness, err := consumerContract.GetRandomnessByRequestId(testcontext.Get(t), requestID, big.NewInt(int64(i)))
require.NoError(t, err, "Error getting Randomness result from Consumer Contract")
l.Info().Interface("Random Number", randomness).Interface("Randomness Number Index", i).Msg("Randomness Fulfillment retrieved from Consumer contract")
require.NotEqual(t, 0, randomness.Uint64(), "Randomness Fulfillment retrieved from Consumer contract give an answer other than 0")
@@ -161,7 +161,7 @@ func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environ
cd := chainlink.New(0, map[string]interface{}{
"replicas": 6,
- "toml": client.AddNetworkDetailedConfig(
+ "toml": networks.AddNetworkDetailedConfig(
config.BaseOCR2Config,
config.DefaultOCR2VRFNetworkDetailTomlConfig,
testNetwork,
diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go
index a078b8ca41..9ed692700a 100644
--- a/integration-tests/smoke/ocr_test.go
+++ b/integration-tests/smoke/ocr_test.go
@@ -7,10 +7,9 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
-
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestOCRBasic(t *testing.T) {
@@ -46,7 +45,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -55,7 +54,7 @@ func TestOCRBasic(t *testing.T) {
err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
}
@@ -93,7 +92,7 @@ func TestOCRJobReplacement(t *testing.T) {
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err := ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64())
@@ -102,7 +101,7 @@ func TestOCRJobReplacement(t *testing.T) {
err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Error getting latest OCR answer")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
@@ -119,7 +118,7 @@ func TestOCRJobReplacement(t *testing.T) {
err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l)
require.NoError(t, err)
- answer, err = ocrInstances[0].GetLatestAnswer(utils.TestContext(t))
+ answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t))
require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail")
require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64())
diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go
index 20389da378..e2cd28b332 100644
--- a/integration-tests/smoke/runlog_test.go
+++ b/integration-tests/smoke/runlog_test.go
@@ -12,10 +12,10 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestRunLogBasic(t *testing.T) {
@@ -87,7 +87,7 @@ func TestRunLogBasic(t *testing.T) {
gom := gomega.NewGomegaWithT(t)
gom.Eventually(func(g gomega.Gomega) {
- d, err := consumer.Data(utils.TestContext(t))
+ d, err := consumer.Data(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail")
g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil")
l.Debug().Int64("Data", d.Int64()).Msg("Found on chain")
diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go
index e477d45926..9c24d97b13 100644
--- a/integration-tests/smoke/vrf_test.go
+++ b/integration-tests/smoke/vrf_test.go
@@ -11,12 +11,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv1"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFBasic(t *testing.T) {
@@ -81,7 +81,7 @@ func TestVRFBasic(t *testing.T) {
encodedProvingKeys := make([][2]*big.Int, 0)
encodedProvingKeys = append(encodedProvingKeys, provingKey)
- requestHash, err := contracts.Coordinator.HashOfKey(utils.TestContext(t), encodedProvingKeys[0])
+ requestHash, err := contracts.Coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0])
require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail")
err = contracts.Consumer.RequestRandomness(requestHash, big.NewInt(1))
require.NoError(t, err, "Requesting randomness shouldn't fail")
@@ -92,7 +92,7 @@ func TestVRFBasic(t *testing.T) {
jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
- out, err := contracts.Consumer.RandomnessOutput(utils.TestContext(t))
+ out, err := contracts.Consumer.RandomnessOutput(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
// Checks that the job has actually run
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
@@ -170,7 +170,7 @@ func TestVRFJobReplacement(t *testing.T) {
encodedProvingKeys := make([][2]*big.Int, 0)
encodedProvingKeys = append(encodedProvingKeys, provingKey)
- requestHash, err := contracts.Coordinator.HashOfKey(utils.TestContext(t), encodedProvingKeys[0])
+ requestHash, err := contracts.Coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0])
require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail")
err = contracts.Consumer.RequestRandomness(requestHash, big.NewInt(1))
require.NoError(t, err, "Requesting randomness shouldn't fail")
@@ -181,7 +181,7 @@ func TestVRFJobReplacement(t *testing.T) {
jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
- out, err := contracts.Consumer.RandomnessOutput(utils.TestContext(t))
+ out, err := contracts.Consumer.RandomnessOutput(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
// Checks that the job has actually run
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
@@ -208,7 +208,7 @@ func TestVRFJobReplacement(t *testing.T) {
jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail")
- out, err := contracts.Consumer.RandomnessOutput(utils.TestContext(t))
+ out, err := contracts.Consumer.RandomnessOutput(testcontext.Get(t))
g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail")
// Checks that the job has actually run
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1),
diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go
index 714ed752a3..09024b28ba 100644
--- a/integration-tests/smoke/vrfv2_test.go
+++ b/integration-tests/smoke/vrfv2_test.go
@@ -9,13 +9,13 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions"
vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFv2Basic(t *testing.T) {
@@ -97,11 +97,11 @@ func TestVRFv2Basic(t *testing.T) {
jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfV2jobs[0].Job.Data.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically("==", 1))
- lastRequestID, err = vrfv2Contracts.LoadTestConsumer.GetLastRequestId(utils.TestContext(t))
+ lastRequestID, err = vrfv2Contracts.LoadTestConsumer.GetLastRequestId(testcontext.Get(t))
l.Debug().Interface("Last Request ID", lastRequestID).Msg("Last Request ID Received")
g.Expect(err).ShouldNot(gomega.HaveOccurred())
- status, err := vrfv2Contracts.LoadTestConsumer.GetRequestStatus(utils.TestContext(t), lastRequestID)
+ status, err := vrfv2Contracts.LoadTestConsumer.GetRequestStatus(testcontext.Get(t), lastRequestID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(status.Fulfilled).Should(gomega.BeTrue())
l.Debug().Interface("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go
index cfeca0a66a..b171ea65f9 100644
--- a/integration-tests/smoke/vrfv2plus_test.go
+++ b/integration-tests/smoke/vrfv2plus_test.go
@@ -6,19 +6,19 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
-
"github.com/ethereum/go-ethereum/common"
"github.com/kelseyhightower/envconfig"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func TestVRFv2Plus(t *testing.T) {
@@ -54,7 +54,7 @@ func TestVRFv2Plus(t *testing.T) {
subID := subIDs[0]
- subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
@@ -82,7 +82,7 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err, "error getting subscription information")
subBalanceAfterRequest := subscription.Balance
require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest)
@@ -91,7 +91,7 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error reading job runs")
require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data))
- status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
+ status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, status.Fulfilled)
l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
@@ -124,7 +124,7 @@ func TestVRFv2Plus(t *testing.T) {
)
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceWei := new(big.Int).Sub(subNativeTokenBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ subscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err)
subBalanceAfterRequest := subscription.NativeBalance
require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest)
@@ -133,7 +133,7 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error reading job runs")
require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data))
- status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
+ status, err := vrfv2PlusContracts.LoadTestConsumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, status.Fulfilled)
l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status")
@@ -161,10 +161,10 @@ func TestVRFv2Plus(t *testing.T) {
testConfig := vrfv2PlusConfig
var isNativeBilling = false
- wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(utils.TestContext(t), wrapperContracts.LoadTestConsumers[0].Address())
+ wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(testcontext.Get(t), wrapperContracts.LoadTestConsumers[0].Address())
require.NoError(t, err, "error getting wrapper consumer balance")
- wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
+ wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceBeforeRequest := wrapperSubscription.Balance
@@ -181,18 +181,18 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
+ wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceAfterRequest := wrapperSubscription.Balance
require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest)
- consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
+ consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, consumerStatus.Fulfilled)
expectedWrapperConsumerJuelsBalance := new(big.Int).Sub(wrapperConsumerJuelsBalanceBeforeRequest, consumerStatus.Paid)
- wrapperConsumerJuelsBalanceAfterRequest, err := linkToken.BalanceOf(utils.TestContext(t), wrapperContracts.LoadTestConsumers[0].Address())
+ wrapperConsumerJuelsBalanceAfterRequest, err := linkToken.BalanceOf(testcontext.Get(t), wrapperContracts.LoadTestConsumers[0].Address())
require.NoError(t, err, "error getting wrapper consumer balance")
require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest)
@@ -210,10 +210,10 @@ func TestVRFv2Plus(t *testing.T) {
testConfig := vrfv2PlusConfig
var isNativeBilling = true
- wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
+ wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
require.NoError(t, err, "error getting wrapper consumer balance")
- wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
+ wrapperSubscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceBeforeRequest := wrapperSubscription.NativeBalance
@@ -230,18 +230,18 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err, "error requesting randomness and waiting for fulfilment")
expectedSubBalanceWei := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment)
- wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), wrapperSubID)
+ wrapperSubscription, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), wrapperSubID)
require.NoError(t, err, "error getting subscription information")
subBalanceAfterRequest := wrapperSubscription.NativeBalance
require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest)
- consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(utils.TestContext(t), randomWordsFulfilledEvent.RequestId)
+ consumerStatus, err := wrapperContracts.LoadTestConsumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId)
require.NoError(t, err, "error getting rand request status")
require.True(t, consumerStatus.Fulfilled)
expectedWrapperConsumerWeiBalance := new(big.Int).Sub(wrapperConsumerBalanceBeforeRequestWei, consumerStatus.Paid)
- wrapperConsumerBalanceAfterRequestWei, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
+ wrapperConsumerBalanceAfterRequestWei, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()))
require.NoError(t, err, "error getting wrapper consumer balance")
require.Equal(t, expectedWrapperConsumerWeiBalance, wrapperConsumerBalanceAfterRequestWei)
@@ -272,13 +272,13 @@ func TestVRFv2Plus(t *testing.T) {
testWalletAddress, err := actions.GenerateWallet()
require.NoError(t, err)
- testWalletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), testWalletAddress)
+ testWalletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(testcontext.Get(t), testWalletAddress)
require.NoError(t, err)
- testWalletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), testWalletAddress.String())
+ testWalletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), testWalletAddress.String())
require.NoError(t, err)
- subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
+ subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
subBalanceLink := subscriptionForCancelling.Balance
@@ -317,14 +317,14 @@ func TestVRFv2Plus(t *testing.T) {
require.Equal(t, subBalanceNative, subscriptionCanceledEvent.AmountNative, "SubscriptionCanceled event native amount is not equal to sub amount while canceling subscription")
require.Equal(t, subBalanceLink, subscriptionCanceledEvent.AmountLink, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription")
- testWalletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), testWalletAddress)
+ testWalletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(testcontext.Get(t), testWalletAddress)
require.NoError(t, err)
- testWalletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), testWalletAddress.String())
+ testWalletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), testWalletAddress.String())
require.NoError(t, err)
//Verify that sub was deleted from Coordinator
- _, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling)
require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
subFundsReturnedNativeActual := new(big.Int).Sub(testWalletBalanceNativeAfterSubCancelling, testWalletBalanceNativeBeforeSubCancelling)
@@ -366,17 +366,17 @@ func TestVRFv2Plus(t *testing.T) {
subIDForCancelling := subIDsForCancelling[0]
- subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
+ subscriptionForCancelling, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetails(l, subscriptionForCancelling, subIDForCancelling, vrfv2PlusContracts.Coordinator)
- activeSubscriptionIdsBeforeSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
+ activeSubscriptionIdsBeforeSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err)
- require.True(t, utils.BigIntSliceContains(activeSubscriptionIdsBeforeSubCancellation, subIDForCancelling))
+ require.True(t, it_utils.BigIntSliceContains(activeSubscriptionIdsBeforeSubCancellation, subIDForCancelling))
- pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(utils.TestContext(t), subIDForCancelling)
+ pendingRequestsExist, err := vrfv2PlusContracts.Coordinator.PendingRequestsExist(testcontext.Get(t), subIDForCancelling)
require.NoError(t, err)
require.False(t, pendingRequestsExist, "Pending requests should not exist")
@@ -408,17 +408,17 @@ func TestVRFv2Plus(t *testing.T) {
require.Error(t, err, "error should occur for waiting for fulfilment due to low sub balance")
- pendingRequestsExist, err = vrfv2PlusContracts.Coordinator.PendingRequestsExist(utils.TestContext(t), subIDForCancelling)
+ pendingRequestsExist, err = vrfv2PlusContracts.Coordinator.PendingRequestsExist(testcontext.Get(t), subIDForCancelling)
require.NoError(t, err)
require.True(t, pendingRequestsExist, "Pending requests should exist after unfulfilled rand requests due to low sub balance")
- walletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
+ walletBalanceNativeBeforeSubCancelling, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- walletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
+ walletBalanceLinkBeforeSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress)
require.NoError(t, err)
- subscriptionForCancelling, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
+ subscriptionForCancelling, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling)
require.NoError(t, err, "error getting subscription information")
subBalanceLink := subscriptionForCancelling.Balance
@@ -457,14 +457,14 @@ func TestVRFv2Plus(t *testing.T) {
require.Equal(t, subBalanceNative, subscriptionCanceledEvent.AmountNative, "SubscriptionCanceled event native amount is not equal to sub amount while canceling subscription")
require.Equal(t, subBalanceLink, subscriptionCanceledEvent.AmountLink, "SubscriptionCanceled event LINK amount is not equal to sub amount while canceling subscription")
- walletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
+ walletBalanceNativeAfterSubCancelling, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- walletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
+ walletBalanceLinkAfterSubCancelling, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress)
require.NoError(t, err)
//Verify that sub was deleted from Coordinator
- _, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subIDForCancelling)
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subIDForCancelling)
fmt.Println("err", err)
require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
@@ -493,12 +493,12 @@ func TestVRFv2Plus(t *testing.T) {
//require.Equal(t, subFundsReturnedNativeExpected, subFundsReturnedNativeActual, "Returned funds are not equal to sub balance that was cancelled")
require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled")
- activeSubscriptionIdsAfterSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
+ activeSubscriptionIdsAfterSubCancellation, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err, "error getting active subscription ids")
require.False(
t,
- utils.BigIntSliceContains(activeSubscriptionIdsAfterSubCancellation, subIDForCancelling),
+ it_utils.BigIntSliceContains(activeSubscriptionIdsAfterSubCancellation, subIDForCancelling),
"Active subscription ids should not contain sub id after sub cancellation",
)
})
@@ -542,10 +542,10 @@ func TestVRFv2Plus(t *testing.T) {
require.NoError(t, err)
amountToWithdrawLink := fulfilledEventLink.Payment
- defaultWalletBalanceNativeBeforeOracleWithdraw, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
+ defaultWalletBalanceNativeBeforeOracleWithdraw, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
+ defaultWalletBalanceLinkBeforeOracleWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress)
require.NoError(t, err)
l.Info().
@@ -574,10 +574,10 @@ func TestVRFv2Plus(t *testing.T) {
err = env.EVMClient.WaitForEvents()
require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete)
- defaultWalletBalanceNativeAfterOracleWithdraw, err := env.EVMClient.BalanceAt(utils.TestContext(t), common.HexToAddress(defaultWalletAddress))
+ defaultWalletBalanceNativeAfterOracleWithdraw, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(defaultWalletAddress))
require.NoError(t, err)
- defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(utils.TestContext(t), defaultWalletAddress)
+ defaultWalletBalanceLinkAfterOracleWithdraw, err := linkToken.BalanceOf(testcontext.Get(t), defaultWalletAddress)
require.NoError(t, err)
//not possible to verify exact amount of Native/LINK returned as defaultWallet is used in other tests in parallel which might affect the balance
@@ -617,17 +617,17 @@ func TestVRFv2PlusMigration(t *testing.T) {
subID := subIDs[0]
- subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator)
- activeSubIdsOldCoordinatorBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
+ activeSubIdsOldCoordinatorBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err, "error occurred getting active sub ids")
require.Len(t, activeSubIdsOldCoordinatorBeforeMigration, 1, "Active Sub Ids length is not equal to 1")
require.Equal(t, subID, activeSubIdsOldCoordinatorBeforeMigration[0])
- oldSubscriptionBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ oldSubscriptionBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err, "error getting subscription information")
//Migration Process
@@ -698,14 +698,14 @@ func TestVRFv2PlusMigration(t *testing.T) {
migratedCoordinatorLinkTotalBalanceAfterMigration, migratedCoordinatorEthTotalBalanceAfterMigration, err := vrfv2plus.GetUpgradedCoordinatorTotalBalance(newCoordinator)
require.NoError(t, err)
- migratedSubscription, err := newCoordinator.GetSubscription(utils.TestContext(t), subID)
+ migratedSubscription, err := newCoordinator.GetSubscription(testcontext.Get(t), subID)
require.NoError(t, err, "error getting subscription information")
vrfv2plus.LogSubDetailsAfterMigration(l, newCoordinator, subID, migratedSubscription)
//Verify that Coordinators were updated in Consumers
for _, consumer := range vrfv2PlusContracts.LoadTestConsumers {
- coordinatorAddressInConsumerAfterMigration, err := consumer.GetCoordinator(utils.TestContext(t))
+ coordinatorAddressInConsumerAfterMigration, err := consumer.GetCoordinator(testcontext.Get(t))
require.NoError(t, err, "error getting Coordinator from Consumer contract")
require.Equal(t, newCoordinator.Address(), coordinatorAddressInConsumerAfterMigration.String())
l.Debug().
@@ -721,13 +721,13 @@ func TestVRFv2PlusMigration(t *testing.T) {
require.Equal(t, oldSubscriptionBeforeMigration.Consumers, migratedSubscription.Consumers)
//Verify that old sub was deleted from old Coordinator
- _, err = vrfv2PlusContracts.Coordinator.GetSubscription(utils.TestContext(t), subID)
+ _, err = vrfv2PlusContracts.Coordinator.GetSubscription(testcontext.Get(t), subID)
require.Error(t, err, "error not occurred when trying to get deleted subscription from old Coordinator after sub migration")
- _, err = vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
+ _, err = vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0))
require.Error(t, err, "error not occurred getting active sub ids. Should occur since it should revert when sub id array is empty")
- activeSubIdsMigratedCoordinator, err := newCoordinator.GetActiveSubscriptionIds(utils.TestContext(t), big.NewInt(0), big.NewInt(0))
+ activeSubIdsMigratedCoordinator, err := newCoordinator.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0))
require.NoError(t, err, "error occurred getting active sub ids")
require.Len(t, activeSubIdsMigratedCoordinator, 1, "Active Sub Ids length is not equal to 1 for Migrated Coordinator after migration")
require.Equal(t, subID, activeSubIdsMigratedCoordinator[0])
diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go
index bc02f36789..538f5ff156 100644
--- a/integration-tests/soak/forwarder_ocr_test.go
+++ b/integration-tests/soak/forwarder_ocr_test.go
@@ -18,7 +18,7 @@ func TestForwarderOCRSoak(t *testing.T) {
ForwardersEnabled = true`
// Uncomment below for debugging TOML issues on the node
// fmt.Println("Using Chainlink TOML\n---------------------")
- // fmt.Println(client.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network))
+ // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network))
// fmt.Println("---------------------")
ocrSoakTest, err := testsetups.NewOCRSoakTest(t, true)
diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go
index 9973c23808..c7d4bc80f6 100644
--- a/integration-tests/soak/ocr_test.go
+++ b/integration-tests/soak/ocr_test.go
@@ -18,7 +18,7 @@ func TestOCRSoak(t *testing.T) {
// Uncomment below for debugging TOML issues on the node
// network := networks.MustGetSelectedNetworksFromEnv()[0]
// fmt.Println("Using Chainlink TOML\n---------------------")
- // fmt.Println(client.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network))
+ // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network))
// fmt.Println("---------------------")
ocrSoakTest, err := testsetups.NewOCRSoakTest(t, false)
diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go
index d9b389a965..575ed3e7de 100644
--- a/integration-tests/testsetups/keeper_benchmark.go
+++ b/integration-tests/testsetups/keeper_benchmark.go
@@ -25,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1"
@@ -37,7 +38,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// KeeperBenchmarkTest builds a test to check that chainlink nodes are able to upkeep a specified amount of Upkeep
@@ -230,7 +230,7 @@ func (k *KeeperBenchmarkTest) Run() {
"NumberOfRegistries": len(k.keeperRegistries),
}
inputs := k.Inputs
- startingBlock, err := k.chainClient.LatestBlockNumber(utils.TestContext(k.t))
+ startingBlock, err := k.chainClient.LatestBlockNumber(testcontext.Get(k.t))
require.NoError(k.t, err, "Error getting latest block number")
k.startingBlock = big.NewInt(0).SetUint64(startingBlock)
startTime := time.Now()
@@ -319,7 +319,7 @@ func (k *KeeperBenchmarkTest) Run() {
// This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats.
err = fmt.Errorf("initial error") // to ensure our for loop runs at least once
for err != nil {
- ctx, cancel := context.WithTimeout(utils.TestContext(k.t), timeout)
+ ctx, cancel := context.WithTimeout(testcontext.Get(k.t), timeout)
logs, err = k.chainClient.FilterLogs(ctx, filterQuery)
cancel()
if err != nil {
@@ -430,7 +430,7 @@ func (k *KeeperBenchmarkTest) observeUpkeepEvents() {
FromBlock: k.startingBlock,
}
- ctx, cancel := context.WithTimeout(utils.TestContext(k.t), 5*time.Second)
+ ctx, cancel := context.WithTimeout(testcontext.Get(k.t), 5*time.Second)
sub, err := k.chainClient.SubscribeFilterLogs(ctx, filterQuery, eventLogs)
cancel()
require.NoError(k.t, err, "Subscribing to upkeep performed events log shouldn't fail")
@@ -453,7 +453,7 @@ func (k *KeeperBenchmarkTest) observeUpkeepEvents() {
Str("Backoff", backoff.String()).
Msg("Error while subscribing to Keeper Event Logs. Resubscribing...")
- ctx, cancel := context.WithTimeout(utils.TestContext(k.t), backoff)
+ ctx, cancel := context.WithTimeout(testcontext.Get(k.t), backoff)
sub, err = k.chainClient.SubscribeFilterLogs(ctx, filterQuery, eventLogs)
cancel()
if err != nil {
diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go
index 3fb9dd9844..dfeb4bb916 100644
--- a/integration-tests/testsetups/ocr.go
+++ b/integration-tests/testsetups/ocr.go
@@ -36,13 +36,13 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
const (
@@ -142,7 +142,7 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) {
cd := chainlink.New(0, map[string]any{
"replicas": 6,
- "toml": client.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customChainlinkNetworkTOML, network),
+ "toml": networks.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customChainlinkNetworkTOML, network),
"db": map[string]any{
"stateful": true, // stateful DB by default for soak tests
},
@@ -258,7 +258,7 @@ func (o *OCRSoakTest) Setup() {
// Run starts the OCR soak test
func (o *OCRSoakTest) Run() {
- ctx, cancel := context.WithTimeout(utils.TestContext(o.t), time.Second*5)
+ ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5)
latestBlockNum, err := o.chainClient.LatestBlockNumber(ctx)
cancel()
require.NoError(o.t, err, "Error getting current block number")
@@ -559,7 +559,7 @@ func (o *OCRSoakTest) setFilterQuery() {
// WARNING: Should only be used for observation and logging. This is not a reliable way to collect events.
func (o *OCRSoakTest) observeOCREvents() error {
eventLogs := make(chan types.Log)
- ctx, cancel := context.WithTimeout(utils.TestContext(o.t), 5*time.Second)
+ ctx, cancel := context.WithTimeout(testcontext.Get(o.t), 5*time.Second)
eventSub, err := o.chainClient.SubscribeFilterLogs(ctx, o.filterQuery, eventLogs)
cancel()
if err != nil {
@@ -593,7 +593,7 @@ func (o *OCRSoakTest) observeOCREvents() error {
Str("Backoff", backoff.String()).
Interface("Query", o.filterQuery).
Msg("Error while subscribed to OCR Logs. Resubscribing")
- ctx, cancel = context.WithTimeout(utils.TestContext(o.t), backoff)
+ ctx, cancel = context.WithTimeout(testcontext.Get(o.t), backoff)
eventSub, err = o.chainClient.SubscribeFilterLogs(ctx, o.filterQuery, eventLogs)
cancel()
if err != nil {
@@ -646,12 +646,12 @@ func (o *OCRSoakTest) collectEvents() error {
timeout := time.Second * 15
o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events")
- ctx, cancel := context.WithTimeout(utils.TestContext(o.t), timeout)
+ ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout)
contractEvents, err := o.chainClient.FilterLogs(ctx, o.filterQuery)
cancel()
for err != nil {
o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events")
- ctx, cancel := context.WithTimeout(utils.TestContext(o.t), timeout)
+ ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout)
contractEvents, err = o.chainClient.FilterLogs(ctx, o.filterQuery)
cancel()
if err != nil {
diff --git a/integration-tests/testsetups/vrfv2.go b/integration-tests/testsetups/vrfv2.go
index 8c5fde7216..ef18bd267d 100644
--- a/integration-tests/testsetups/vrfv2.go
+++ b/integration-tests/testsetups/vrfv2.go
@@ -18,11 +18,11 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
+ "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/testreporters"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
// VRFV2SoakTest defines a typical VRFV2 soak test
@@ -88,7 +88,7 @@ func (v *VRFV2SoakTest) Run(t *testing.T) {
Msg("Starting VRFV2 Soak Test")
// set the requests to only run for a certain amount of time
- ctx := utils.TestContext(t)
+ ctx := testcontext.Get(t)
testContext, testCancel := context.WithTimeout(ctx, v.Inputs.TestDuration)
defer testCancel()
diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go
index e044d1ba32..6da1d94371 100644
--- a/integration-tests/types/config/node/core.go
+++ b/integration-tests/types/config/node/core.go
@@ -13,6 +13,7 @@ import (
relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
@@ -23,42 +24,42 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/utils/config"
"github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants"
- utils2 "github.com/smartcontractkit/chainlink/integration-tests/utils"
+ it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
func NewBaseConfig() *chainlink.Config {
return &chainlink.Config{
Core: toml.Core{
- RootDir: utils2.Ptr("/home/chainlink"),
+ RootDir: ptr.Ptr("/home/chainlink"),
Database: toml.Database{
- MaxIdleConns: utils2.Ptr(int64(20)),
- MaxOpenConns: utils2.Ptr(int64(40)),
- MigrateOnStartup: utils2.Ptr(true),
+ MaxIdleConns: ptr.Ptr(int64(20)),
+ MaxOpenConns: ptr.Ptr(int64(40)),
+ MigrateOnStartup: ptr.Ptr(true),
},
Log: toml.Log{
- Level: utils2.Ptr(toml.LogLevel(zapcore.DebugLevel)),
- JSONConsole: utils2.Ptr(true),
+ Level: ptr.Ptr(toml.LogLevel(zapcore.DebugLevel)),
+ JSONConsole: ptr.Ptr(true),
File: toml.LogFile{
- MaxSize: utils2.Ptr(utils.FileSize(0)),
+ MaxSize: ptr.Ptr(utils.FileSize(0)),
},
},
WebServer: toml.WebServer{
- AllowOrigins: utils2.Ptr("*"),
- HTTPPort: utils2.Ptr[uint16](6688),
- SecureCookies: utils2.Ptr(false),
+ AllowOrigins: ptr.Ptr("*"),
+ HTTPPort: ptr.Ptr[uint16](6688),
+ SecureCookies: ptr.Ptr(false),
SessionTimeout: models.MustNewDuration(time.Hour * 999),
TLS: toml.WebServerTLS{
- HTTPSPort: utils2.Ptr[uint16](0),
+ HTTPSPort: ptr.Ptr[uint16](0),
},
RateLimit: toml.WebServerRateLimit{
- Authenticated: utils2.Ptr(int64(2000)),
- Unauthenticated: utils2.Ptr(int64(100)),
+ Authenticated: ptr.Ptr(int64(2000)),
+ Unauthenticated: ptr.Ptr(int64(100)),
},
},
Feature: toml.Feature{
- LogPoller: utils2.Ptr(true),
- FeedsManager: utils2.Ptr(true),
- UICSAKeys: utils2.Ptr(true),
+ LogPoller: ptr.Ptr(true),
+ FeedsManager: ptr.Ptr(true),
+ UICSAKeys: ptr.Ptr(true),
},
P2P: toml.P2P{},
},
@@ -96,7 +97,7 @@ func NewConfigFromToml(tomlFile string, opts ...NodeConfigOpt) (*chainlink.Confi
func WithOCR1() NodeConfigOpt {
return func(c *chainlink.Config) {
c.OCR = toml.OCR{
- Enabled: utils2.Ptr(true),
+ Enabled: ptr.Ptr(true),
}
}
}
@@ -104,7 +105,7 @@ func WithOCR1() NodeConfigOpt {
func WithOCR2() NodeConfigOpt {
return func(c *chainlink.Config) {
c.OCR2 = toml.OCR2{
- Enabled: utils2.Ptr(true),
+ Enabled: ptr.Ptr(true),
}
}
}
@@ -114,12 +115,12 @@ func WithOCR2() NodeConfigOpt {
func WithP2Pv1() NodeConfigOpt {
return func(c *chainlink.Config) {
c.P2P.V1 = toml.P2PV1{
- Enabled: utils2.Ptr(true),
- ListenIP: utils2.MustIP("0.0.0.0"),
- ListenPort: utils2.Ptr[uint16](6690),
+ Enabled: ptr.Ptr(true),
+ ListenIP: it_utils.MustIP("0.0.0.0"),
+ ListenPort: ptr.Ptr[uint16](6690),
}
// disabled default
- c.P2P.V2 = toml.P2PV2{Enabled: utils2.Ptr(false)}
+ c.P2P.V2 = toml.P2PV2{Enabled: ptr.Ptr(false)}
}
}
@@ -134,14 +135,14 @@ func WithP2Pv2() NodeConfigOpt {
func WithTracing() NodeConfigOpt {
return func(c *chainlink.Config) {
c.Tracing = toml.Tracing{
- Enabled: utils2.Ptr(true),
- CollectorTarget: utils2.Ptr("otel-collector:4317"),
+ Enabled: ptr.Ptr(true),
+ CollectorTarget: ptr.Ptr("otel-collector:4317"),
// ksortable unique id
- NodeID: utils2.Ptr(ksuid.New().String()),
+ NodeID: ptr.Ptr(ksuid.New().String()),
Attributes: map[string]string{
"env": "smoke",
},
- SamplingRatio: utils2.Ptr(1.0),
+ SamplingRatio: ptr.Ptr(1.0),
}
}
}
@@ -157,10 +158,10 @@ func SetChainConfig(
var nodes []*evmcfg.Node
for i := range wsUrls {
node := evmcfg.Node{
- Name: utils2.Ptr(fmt.Sprintf("node_%d_%s", i, chain.Name)),
- WSURL: utils2.MustURL(wsUrls[i]),
- HTTPURL: utils2.MustURL(httpUrls[i]),
- SendOnly: utils2.Ptr(false),
+ Name: ptr.Ptr(fmt.Sprintf("node_%d_%s", i, chain.Name)),
+ WSURL: it_utils.MustURL(wsUrls[i]),
+ HTTPURL: it_utils.MustURL(httpUrls[i]),
+ SendOnly: ptr.Ptr(false),
}
nodes = append(nodes, &node)
@@ -168,8 +169,8 @@ func SetChainConfig(
var chainConfig evmcfg.Chain
if chain.Simulated {
chainConfig = evmcfg.Chain{
- AutoCreateKey: utils2.Ptr(true),
- FinalityDepth: utils2.Ptr[uint32](1),
+ AutoCreateKey: ptr.Ptr(true),
+ FinalityDepth: ptr.Ptr[uint32](1),
MinContractPayment: relayassets.NewLinkFromJuels(0),
}
}
@@ -182,7 +183,7 @@ func SetChainConfig(
}
if forwarders {
cfg.EVM[0].Transactions = evmcfg.Transactions{
- ForwardersEnabled: utils2.Ptr(true),
+ ForwardersEnabled: ptr.Ptr(true),
}
}
}
@@ -194,25 +195,25 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork) NodeConfigOpt {
evmConfigs = append(evmConfigs, &evmcfg.EVMConfig{
ChainID: utils.NewBig(big.NewInt(network.ChainID)),
Chain: evmcfg.Chain{
- AutoCreateKey: utils2.Ptr(true),
- FinalityDepth: utils2.Ptr[uint32](50),
+ AutoCreateKey: ptr.Ptr(true),
+ FinalityDepth: ptr.Ptr[uint32](50),
MinContractPayment: relayassets.NewLinkFromJuels(0),
LogPollInterval: models.MustNewDuration(1 * time.Second),
HeadTracker: evmcfg.HeadTracker{
- HistoryDepth: utils2.Ptr(uint32(100)),
+ HistoryDepth: ptr.Ptr(uint32(100)),
},
GasEstimator: evmcfg.GasEstimator{
- LimitDefault: utils2.Ptr(uint32(6000000)),
+ LimitDefault: ptr.Ptr(uint32(6000000)),
PriceMax: assets.GWei(200),
FeeCapDefault: assets.GWei(200),
},
},
Nodes: []*evmcfg.Node{
{
- Name: utils2.Ptr(network.Name),
- WSURL: utils2.MustURL(network.URLs[0]),
- HTTPURL: utils2.MustURL(network.HTTPURLs[0]),
- SendOnly: utils2.Ptr(false),
+ Name: ptr.Ptr(network.Name),
+ WSURL: it_utils.MustURL(network.URLs[0]),
+ HTTPURL: it_utils.MustURL(network.HTTPURLs[0]),
+ SendOnly: ptr.Ptr(false),
},
},
})
@@ -227,17 +228,17 @@ func WithVRFv2EVMEstimator(addr string) NodeConfigOpt {
return func(c *chainlink.Config) {
c.EVM[0].KeySpecific = evmcfg.KeySpecificConfig{
{
- Key: utils2.Ptr(ethkey.EIP55Address(addr)),
+ Key: ptr.Ptr(ethkey.EIP55Address(addr)),
GasEstimator: evmcfg.KeySpecificGasEstimator{
PriceMax: est,
},
},
}
c.EVM[0].Chain.GasEstimator = evmcfg.GasEstimator{
- LimitDefault: utils2.Ptr[uint32](3500000),
+ LimitDefault: ptr.Ptr[uint32](3500000),
}
c.EVM[0].Chain.Transactions = evmcfg.Transactions{
- MaxQueued: utils2.Ptr[uint32](10000),
+ MaxQueued: ptr.Ptr[uint32](10000),
}
}
}
diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go
index 505337f032..7bf1657316 100644
--- a/integration-tests/universal/log_poller/helpers.go
+++ b/integration-tests/universal/log_poller/helpers.go
@@ -27,6 +27,7 @@ import (
ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -42,7 +43,6 @@ import (
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
"github.com/smartcontractkit/chainlink/integration-tests/types/config/node"
- it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils"
)
var (
@@ -1010,12 +1010,12 @@ func setupLogPollerTestDocker(
// build the node config
clNodeConfig := node.NewConfig(node.NewBaseConfig())
syncInterval := models.MustMakeDuration(5 * time.Minute)
- clNodeConfig.Feature.LogPoller = it_utils.Ptr[bool](true)
- clNodeConfig.OCR2.Enabled = it_utils.Ptr[bool](true)
- clNodeConfig.Keeper.TurnLookBack = it_utils.Ptr[int64](int64(0))
+ clNodeConfig.Feature.LogPoller = ptr.Ptr[bool](true)
+ clNodeConfig.OCR2.Enabled = ptr.Ptr[bool](true)
+ clNodeConfig.Keeper.TurnLookBack = ptr.Ptr[int64](int64(0))
clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval
- clNodeConfig.Keeper.Registry.PerformGasOverhead = it_utils.Ptr[uint32](uint32(150000))
- clNodeConfig.P2P.V2.Enabled = it_utils.Ptr[bool](true)
+ clNodeConfig.Keeper.Registry.PerformGasOverhead = ptr.Ptr[uint32](uint32(150000))
+ clNodeConfig.P2P.V2.Enabled = ptr.Ptr[bool](true)
clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"}
clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"}
@@ -1027,8 +1027,8 @@ func setupLogPollerTestDocker(
var logPolllerSettingsFn = func(chain *evmcfg.Chain) *evmcfg.Chain {
chain.LogPollInterval = models.MustNewDuration(lpPollingInterval)
- chain.FinalityDepth = it_utils.Ptr[uint32](uint32(finalityDepth))
- chain.FinalityTagEnabled = it_utils.Ptr[bool](finalityTagEnabled)
+ chain.FinalityDepth = ptr.Ptr[uint32](uint32(finalityDepth))
+ chain.FinalityTagEnabled = ptr.Ptr[bool](finalityTagEnabled)
return chain
}
diff --git a/integration-tests/universal/log_poller/scenarios.go b/integration-tests/universal/log_poller/scenarios.go
index 886547d46e..5331c63f75 100644
--- a/integration-tests/universal/log_poller/scenarios.go
+++ b/integration-tests/universal/log_poller/scenarios.go
@@ -10,10 +10,10 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
- "github.com/smartcontractkit/chainlink/integration-tests/utils"
core_logger "github.com/smartcontractkit/chainlink/v2/core/logger"
)
@@ -100,7 +100,7 @@ func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
// Save block number before starting to emit events, so that we can later use it when querying logs
- sb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
+ sb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Error getting latest block number")
startBlock := int64(sb)
@@ -122,7 +122,7 @@ func ExecuteBasicLogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
// Save block number after finishing to emit events, so that we can later use it when querying logs
- eb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
+ eb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Error getting latest block number")
endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
@@ -229,7 +229,7 @@ func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string
time.Sleep(5 * time.Second)
// Save block number before starting to emit events, so that we can later use it when querying logs
- sb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
+ sb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Error getting latest block number")
startBlock := int64(sb)
@@ -243,7 +243,7 @@ func ExecuteLogPollerReplay(t *testing.T, cfg *Config, consistencyTimeout string
l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
// Save block number after finishing to emit events, so that we can later use it when querying logs
- eb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
+ eb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Error getting latest block number")
endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
@@ -419,7 +419,7 @@ func ExecuteCILogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Count", len(expectedFilters)).Msg("Expected filters count")
// Save block number before starting to emit events, so that we can later use it when querying logs
- sb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
+ sb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Error getting latest block number")
startBlock := int64(sb)
@@ -441,7 +441,7 @@ func ExecuteCILogPollerTest(t *testing.T, cfg *Config) {
l.Info().Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION")
// Save block number after finishing to emit events, so that we can later use it when querying logs
- eb, err := testEnv.EVMClient.LatestBlockNumber(utils.TestContext(t))
+ eb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t))
require.NoError(t, err, "Error getting latest block number")
endBlock, err := GetEndBlockToWaitFor(int64(eb), testEnv.EVMClient.GetChainID().Int64(), cfg)
diff --git a/integration-tests/utils/common.go b/integration-tests/utils/common.go
index f13c71cfd9..34a40e396d 100644
--- a/integration-tests/utils/common.go
+++ b/integration-tests/utils/common.go
@@ -1,16 +1,12 @@
package utils
import (
- "context"
"math/big"
"net"
- "testing"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
-func Ptr[T any](t T) *T { return &t }
-
func MustURL(s string) *models.URL {
var u models.URL
if err := u.UnmarshalText([]byte(s)); err != nil {
@@ -35,24 +31,3 @@ func BigIntSliceContains(slice []*big.Int, b *big.Int) bool {
}
return false
}
-
-// TestContext returns a context with the test's deadline, if available.
-func TestContext(tb testing.TB) context.Context {
- ctx := context.Background()
- var cancel func()
- switch t := tb.(type) {
- case *testing.T:
- // Return background context if testing.T not set
- if t == nil {
- return ctx
- }
- if d, ok := t.Deadline(); ok {
- ctx, cancel = context.WithDeadline(ctx, d)
- }
- }
- if cancel == nil {
- ctx, cancel = context.WithCancel(ctx)
- }
- tb.Cleanup(cancel)
- return ctx
-}
From 4eb170b51d67be85b950efa0aa8e5daad3bed00d Mon Sep 17 00:00:00 2001
From: Sergey Kudasov
Date: Fri, 17 Nov 2023 02:54:02 +0300
Subject: [PATCH 167/327] Devspace update + Cluster dashboard (#11222)
* fix chainlink config
* init dashboard
* bump CTF
* move dashboard rows
* dashboard
* comments
* exclude dashboard from SonarQube
* common dashboard
* extend opts
* rg filter
---
charts/chainlink-cluster/README.md | 21 +-
.../dashboard/cmd/dashboard_deploy.go | 42 ++
.../chainlink-cluster/dashboard/dashboard.go | 392 ++++++++++++++++++
charts/chainlink-cluster/devspace.yaml | 2 +
charts/chainlink-cluster/go.mod | 15 +
charts/chainlink-cluster/go.sum | 20 +
.../templates/chainlink-cm.yaml | 5 +-
.../templates/chainlink-deployment.yaml | 2 +
.../templates/chainlink-pod-monitor.yaml | 16 +-
sonar-project.properties | 2 +-
10 files changed, 505 insertions(+), 12 deletions(-)
create mode 100644 charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go
create mode 100644 charts/chainlink-cluster/dashboard/dashboard.go
create mode 100644 charts/chainlink-cluster/go.mod
create mode 100644 charts/chainlink-cluster/go.sum
diff --git a/charts/chainlink-cluster/README.md b/charts/chainlink-cluster/README.md
index f7d4c45fa5..46c337dc72 100644
--- a/charts/chainlink-cluster/README.md
+++ b/charts/chainlink-cluster/README.md
@@ -34,7 +34,7 @@ If you don't need a build use
devspace deploy --skip-build
```
-Connect to your environment
+Connect to your environment, by replacing container with label `node-1` with your local repository files
```
devspace dev -p node
make chainlink
@@ -117,4 +117,23 @@ helm test cl-cluster
## Uninstall
```
helm uninstall cl-cluster
+```
+
+# Grafana dashboard
+We are using [Grabana]() lib to create dashboards programmatically
+```
+export GRAFANA_URL=...
+export GRAFANA_TOKEN=...
+export LOKI_DATA_SOURCE_NAME=Loki
+export PROMETHEUS_DATA_SOURCE_NAME=Thanos
+export DASHBOARD_FOLDER=CLClusterEphemeralDevspace
+export DASHBOARD_NAME=ChainlinkCluster
+
+cd dashboard/cmd && go run dashboard_deploy.go
+```
+Open Grafana folder `CLClusterEphemeralDevspace` and find dashboard `ChainlinkCluster`
+
+If you'd like to add more metrics or verify that all of them are added you can have the full list using IDE search or `ripgrep`:
+```
+rg -U ".*promauto.*\n.*Name: \"(.*)\"" ../.. > metrics.txt
```
\ No newline at end of file
diff --git a/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go b/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go
new file mode 100644
index 0000000000..c752794f53
--- /dev/null
+++ b/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "os"
+
+ "github.com/smartcontractkit/chainlink/v2/dashboard/dashboard"
+)
+
+func main() {
+ name := os.Getenv("DASHBOARD_NAME")
+ if name == "" {
+ panic("DASHBOARD_NAME must be provided")
+ }
+ ldsn := os.Getenv("LOKI_DATA_SOURCE_NAME")
+ if ldsn == "" {
+ panic("DATA_SOURCE_NAME must be provided")
+ }
+ pdsn := os.Getenv("PROMETHEUS_DATA_SOURCE_NAME")
+ if ldsn == "" {
+ panic("DATA_SOURCE_NAME must be provided")
+ }
+ dbf := os.Getenv("DASHBOARD_FOLDER")
+ if dbf == "" {
+ panic("DASHBOARD_FOLDER must be provided")
+ }
+ grafanaURL := os.Getenv("GRAFANA_URL")
+ if grafanaURL == "" {
+ panic("GRAFANA_URL must be provided")
+ }
+ grafanaToken := os.Getenv("GRAFANA_TOKEN")
+ if grafanaToken == "" {
+ panic("GRAFANA_TOKEN must be provided")
+ }
+ // if you'll use this dashboard base in other projects, you can add your own opts here to extend it
+ db, err := dashboard.NewCLClusterDashboard(name, ldsn, pdsn, dbf, grafanaURL, grafanaToken, nil)
+ if err != nil {
+ panic(err)
+ }
+ if err := db.Deploy(); err != nil {
+ panic(err)
+ }
+}
diff --git a/charts/chainlink-cluster/dashboard/dashboard.go b/charts/chainlink-cluster/dashboard/dashboard.go
new file mode 100644
index 0000000000..7918b996dd
--- /dev/null
+++ b/charts/chainlink-cluster/dashboard/dashboard.go
@@ -0,0 +1,392 @@
+package dashboard
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+
+ "github.com/K-Phoen/grabana"
+ "github.com/K-Phoen/grabana/dashboard"
+ "github.com/K-Phoen/grabana/logs"
+ "github.com/K-Phoen/grabana/row"
+ "github.com/K-Phoen/grabana/stat"
+ "github.com/K-Phoen/grabana/target/prometheus"
+ "github.com/K-Phoen/grabana/timeseries"
+ "github.com/K-Phoen/grabana/timeseries/axis"
+ "github.com/K-Phoen/grabana/variable/interval"
+ "github.com/K-Phoen/grabana/variable/query"
+ "github.com/pkg/errors"
+)
+
+const (
+ ErrFailedToCreateDashboard = "failed to create dashboard"
+ ErrFailedToCreateFolder = "failed to create folder"
+)
+
+// CLClusterDashboard is a dashboard for a Chainlink cluster
+type CLClusterDashboard struct {
+ Name string
+ LokiDataSourceName string
+ PrometheusDataSourceName string
+ Folder string
+ GrafanaURL string
+ GrafanaToken string
+ opts []dashboard.Option
+ extendedOpts []dashboard.Option
+ builder dashboard.Builder
+}
+
+// NewCLClusterDashboard returns a new dashboard for a Chainlink cluster, can be used as a base for more complex plugin based dashboards
+func NewCLClusterDashboard(name, ldsn, pdsn, dbf, grafanaURL, grafanaToken string, opts []dashboard.Option) (*CLClusterDashboard, error) {
+ db := &CLClusterDashboard{
+ Name: name,
+ Folder: dbf,
+ LokiDataSourceName: ldsn,
+ PrometheusDataSourceName: pdsn,
+ GrafanaURL: grafanaURL,
+ GrafanaToken: grafanaToken,
+ extendedOpts: opts,
+ }
+ if err := db.generate(); err != nil {
+ return db, err
+ }
+ return db, nil
+}
+
+func (m *CLClusterDashboard) Opts() []dashboard.Option {
+ return m.opts
+}
+
+// logsRowOption returns a row option for a node's logs with name and instance selector
+func (m *CLClusterDashboard) logsRowOption(name, instanceSelector string) row.Option {
+ return row.WithLogs(
+ name,
+ logs.DataSource(m.LokiDataSourceName),
+ logs.Span(12),
+ logs.Height("300px"),
+ logs.Transparent(),
+ logs.WithLokiTarget(fmt.Sprintf(`
+ {namespace="${namespace}", app="app", instance="%s", container="node"}
+ `, instanceSelector)),
+ )
+}
+
+// timeseriesRowOption returns a row option for a timeseries with name, axis unit, query and legend template
+func (m *CLClusterDashboard) timeseriesRowOption(name, axisUnit, query, legendTemplate string) row.Option {
+ var tsq timeseries.Option
+ if legendTemplate != "" {
+ tsq = timeseries.WithPrometheusTarget(
+ query,
+ prometheus.Legend(legendTemplate),
+ )
+ } else {
+ tsq = timeseries.WithPrometheusTarget(query)
+ }
+ var au timeseries.Option
+ if axisUnit != "" {
+ au = timeseries.Axis(
+ axis.Unit(axisUnit),
+ )
+ } else {
+ au = timeseries.Axis()
+ }
+ return row.WithTimeSeries(
+ name,
+ timeseries.Span(6),
+ timeseries.Height("300px"),
+ timeseries.DataSource(m.PrometheusDataSourceName),
+ au,
+ tsq,
+ )
+}
+
+// statRowOption returns a row option for a stat with name, prometheus target and legend template
+func (m *CLClusterDashboard) statRowOption(name, target, legend string) row.Option {
+ return row.WithStat(
+ name,
+ stat.Transparent(),
+ stat.DataSource(m.PrometheusDataSourceName),
+ stat.Text(stat.TextValueAndName),
+ stat.Orientation(stat.OrientationVertical),
+ stat.TitleFontSize(12),
+ stat.ValueFontSize(20),
+ stat.Span(12),
+ stat.Height("100px"),
+ stat.WithPrometheusTarget(target, prometheus.Legend(legend)),
+ )
+}
+
+// generate generates the dashboard, adding extendedOpts to the default options
+func (m *CLClusterDashboard) generate() error {
+ opts := []dashboard.Option{
+ dashboard.AutoRefresh("10s"),
+ dashboard.Tags([]string{"generated"}),
+ dashboard.VariableAsQuery(
+ "namespace",
+ query.DataSource(m.LokiDataSourceName),
+ query.Multiple(),
+ query.IncludeAll(),
+ query.Request(fmt.Sprintf("label_values(%s)", "namespace")),
+ query.Sort(query.NumericalAsc),
+ ),
+ dashboard.VariableAsInterval(
+ "interval",
+ interval.Values([]string{"30s", "1m", "5m", "10m", "30m", "1h", "6h", "12h"}),
+ ),
+ dashboard.Row(
+ "Cluster health",
+ m.statRowOption(
+ "App Version",
+ `version{namespace="${namespace}"}`,
+ "{{pod}} - {{version}}",
+ ),
+ row.WithTimeSeries(
+ "Restarts",
+ timeseries.Span(12),
+ timeseries.Height("200px"),
+ timeseries.DataSource(m.PrometheusDataSourceName),
+ timeseries.WithPrometheusTarget(
+ `sum(increase(kube_pod_container_status_restarts_total{namespace=~"${namespace}"}[5m])) by (pod)`,
+ prometheus.Legend("{{pod}}"),
+ ),
+ ),
+ row.WithTimeSeries(
+ "Service Components Health",
+ timeseries.Span(12),
+ timeseries.Height("200px"),
+ timeseries.DataSource(m.PrometheusDataSourceName),
+ timeseries.WithPrometheusTarget(
+ `health{namespace="${namespace}"}`,
+ prometheus.Legend("{{pod}} - {{service_id}}"),
+ ),
+ ),
+ row.WithTimeSeries(
+ "Log Counters",
+ timeseries.Span(12),
+ timeseries.Height("200px"),
+ timeseries.DataSource(m.PrometheusDataSourceName),
+ timeseries.WithPrometheusTarget(
+ `log_panic_count{namespace="${namespace}"}`,
+ prometheus.Legend("{{pod}} - panic"),
+ ),
+ timeseries.WithPrometheusTarget(
+ `log_fatal_count{namespace="${namespace}"}`,
+ prometheus.Legend("{{pod}} - fatal"),
+ ),
+ timeseries.WithPrometheusTarget(
+ `log_critical_count{namespace="${namespace}"}`,
+ prometheus.Legend("{{pod}} - critical"),
+ ),
+ timeseries.WithPrometheusTarget(
+ `log_error_count{namespace="${namespace}"}`,
+ prometheus.Legend("{{pod}} - error"),
+ ),
+ ),
+ row.WithTimeSeries(
+ "ETH Balance",
+ timeseries.Span(12),
+ timeseries.Height("200px"),
+ timeseries.DataSource(m.PrometheusDataSourceName),
+ timeseries.WithPrometheusTarget(
+ `eth_balance{namespace="${namespace}"}`,
+ prometheus.Legend("{{pod}} - {{account}}"),
+ ),
+ ),
+ ),
+ // logs
+ dashboard.Row(
+ "Logs",
+ row.Collapse(),
+ m.logsRowOption("Node 1", "node-1"),
+ m.logsRowOption("Node 2", "node-2"),
+ m.logsRowOption("Node 3", "node-3"),
+ m.logsRowOption("Node 4", "node-4"),
+ ),
+ // DON report metrics
+ dashboard.Row("DON Report metrics",
+ row.Collapse(),
+ m.timeseriesRowOption(
+ "Plugin Query() count",
+ "Count",
+ `sum(rate(ocr2_reporting_plugin_query_count{namespace="${namespace}", app="app"}[$__rate_interval])) by (service)`,
+ "",
+ ),
+ m.timeseriesRowOption(
+ "Plugin Observation() time (95th)",
+ "Sec",
+ `histogram_quantile(0.95, sum(rate(ocr2_reporting_plugin_observation_time_bucket{namespace="${namespace}", app="app"}[$__rate_interval])) by (le, service)) / 1e9`,
+ "",
+ ),
+ m.timeseriesRowOption(
+ "Plugin ShouldAcceptReport() time (95th)",
+ "Sec",
+ `histogram_quantile(0.95, sum(rate(ocr2_reporting_plugin_should_accept_report_time_bucket{namespace="${namespace}", app="app"}[$__rate_interval])) by (le, service)) / 1e9`,
+ "",
+ ),
+ m.timeseriesRowOption(
+ "Plugin Report() time (95th)",
+ "Sec",
+ `histogram_quantile(0.95, sum(rate(ocr2_reporting_plugin_report_time_bucket{namespace="${namespace}", app="app"}[$__rate_interval])) by (le, service)) / 1e9`,
+ "",
+ ),
+ m.timeseriesRowOption(
+ "Plugin ShouldTransmitReport() time (95th)",
+ "Sec",
+ `histogram_quantile(0.95, sum(rate(ocr2_reporting_plugin_should_transmit_report_time_bucket{namespace="${namespace}", app="app"}[$__rate_interval])) by (le, service)) / 1e9`,
+ "",
+ ),
+ ),
+ dashboard.Row(
+ "DB Connection Metrics (App)",
+ row.Collapse(),
+ m.timeseriesRowOption(
+ "DB Connections MAX",
+ "Conn",
+ `db_conns_max{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "DB Connections Open",
+ "Conn",
+ `db_conns_open{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "DB Connections Used",
+ "Conn",
+ `db_conns_used{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "DB Connections Wait",
+ "Conn",
+ `db_conns_wait{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "DB Wait time",
+ "Sec",
+ `db_wait_time_seconds{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ ),
+ dashboard.Row(
+ "EVM Pool RPC Node Metrics (App)",
+ row.Collapse(),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Calls Success",
+ "",
+ `evm_pool_rpc_node_calls_success{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Calls Total",
+ "",
+ `evm_pool_rpc_node_calls_total{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Dials Success",
+ "",
+ `evm_pool_rpc_node_dials_success{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Dials Total",
+ "",
+ `evm_pool_rpc_node_dials_total{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Highest Seen Block",
+ "",
+ `evm_pool_rpc_node_highest_seen_block{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Total Transitions to Alive",
+ "",
+ `evm_pool_rpc_node_num_transitions_to_alive{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Polls Success",
+ "",
+ `evm_pool_rpc_node_polls_success{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Polls Total",
+ "",
+ `evm_pool_rpc_node_polls_total{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node States",
+ "",
+ `evm_pool_rpc_node_states{namespace="${namespace}"}`,
+ "{{pod}} - {{evmChainID}} - {{state}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Verifies Total",
+ "",
+ `evm_pool_rpc_node_verifies{namespace="${namespace}"}`,
+ "{{pod}} - {{evmChainID}}",
+ ),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Verifies Success",
+ "",
+ `evm_pool_rpc_node_verifies_success{namespace="${namespace}"}`,
+ "{{pod}} - {{evmChainID}}",
+ ),
+ ),
+ dashboard.Row(
+ "EVM Pool RPC Node Latencies (App)",
+ row.Collapse(),
+ m.timeseriesRowOption(
+ "EVM Pool RPC Node Calls Latency 0.95 quantile",
+ "ms",
+ `histogram_quantile(0.95, sum(rate(evm_pool_rpc_node_rpc_call_time_bucket{namespace="${namespace}"}[$__rate_interval])) by (le, rpcCallName)) / 1e6`,
+ "{{pod}}",
+ ),
+ ),
+ dashboard.Row(
+ "Pipeline Tasks Metrics (App)",
+ row.Collapse(),
+ m.timeseriesRowOption(
+ "Pipeline Runs Queued",
+ "",
+ `pipeline_runs_queued{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ m.timeseriesRowOption(
+ "Pipeline Runs Tasks Queued",
+ "",
+ `pipeline_task_runs_queued{namespace="${namespace}"}`,
+ "{{pod}}",
+ ),
+ ),
+ }
+ opts = append(opts, m.extendedOpts...)
+ builder, err := dashboard.New(
+ "Chainlink Cluster Dashboard",
+ opts...,
+ )
+ m.opts = opts
+ m.builder = builder
+ return err
+}
+
+// Deploy deploys the dashboard to Grafana
+func (m *CLClusterDashboard) Deploy() error {
+ ctx := context.Background()
+ client := grabana.NewClient(&http.Client{}, m.GrafanaURL, grabana.WithAPIToken(m.GrafanaToken))
+ folder, err := client.FindOrCreateFolder(ctx, m.Folder)
+ if err != nil {
+ return errors.Wrap(err, ErrFailedToCreateFolder)
+ }
+ if _, err := client.UpsertDashboard(ctx, folder, m.builder); err != nil {
+ return errors.Wrap(err, ErrFailedToCreateDashboard)
+ }
+ return nil
+}
diff --git a/charts/chainlink-cluster/devspace.yaml b/charts/chainlink-cluster/devspace.yaml
index 54b5f9f01e..688660d918 100644
--- a/charts/chainlink-cluster/devspace.yaml
+++ b/charts/chainlink-cluster/devspace.yaml
@@ -32,6 +32,7 @@ images:
deployments:
app:
helm:
+ releaseName: "app"
chart:
name: cl-cluster
path: .
@@ -68,6 +69,7 @@ deployments:
- name: node-4
image: ${DEVSPACE_IMAGE}
version: latest
+ prometheusMonitor: "true"
podAnnotations: { }
nodeSelector: { }
tolerations: [ ]
diff --git a/charts/chainlink-cluster/go.mod b/charts/chainlink-cluster/go.mod
new file mode 100644
index 0000000000..990ebbf713
--- /dev/null
+++ b/charts/chainlink-cluster/go.mod
@@ -0,0 +1,15 @@
+module github.com/smartcontractkit/chainlink/v2/dashboard
+
+go 1.21
+
+require (
+ github.com/K-Phoen/grabana v0.21.19
+ github.com/pkg/errors v0.9.1
+)
+
+require (
+ github.com/K-Phoen/sdk v0.12.3 // indirect
+ github.com/gosimple/slug v1.13.1 // indirect
+ github.com/gosimple/unidecode v1.0.1 // indirect
+ github.com/prometheus/common v0.39.0 // indirect
+)
diff --git a/charts/chainlink-cluster/go.sum b/charts/chainlink-cluster/go.sum
new file mode 100644
index 0000000000..093a42d608
--- /dev/null
+++ b/charts/chainlink-cluster/go.sum
@@ -0,0 +1,20 @@
+github.com/K-Phoen/grabana v0.21.19 h1:tJjRO8nN9JrFjLoQGtOB9P5ILoqENZZGAtt3nK+Ry2Y=
+github.com/K-Phoen/grabana v0.21.19/go.mod h1:B7gxVxacQUgHWmgqduf4WPZoKYHO1mvZnRVCoyQiwdw=
+github.com/K-Phoen/sdk v0.12.3 h1:ScutEQASc9VEKJCm3OjIMD82BIS9B2XtNg3gEf6Gs+M=
+github.com/K-Phoen/sdk v0.12.3/go.mod h1:qmM0wO23CtoDux528MXPpYvS4XkRWkWX6rvX9Za8EVU=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q=
+github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
+github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=
+github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI=
+github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/charts/chainlink-cluster/templates/chainlink-cm.yaml b/charts/chainlink-cluster/templates/chainlink-cm.yaml
index fa9c2c2657..736a332204 100644
--- a/charts/chainlink-cluster/templates/chainlink-cm.yaml
+++ b/charts/chainlink-cluster/templates/chainlink-cm.yaml
@@ -29,10 +29,9 @@ data:
[OCR]
Enabled = true
[P2P]
- [P2P.V1]
+ [P2P.V2]
Enabled = true
- ListenIP = '0.0.0.0'
- ListenPort = 6690
+ ListenAddresses = ["0.0.0.0:6690"]
[[EVM]]
ChainID = '1337'
MinContractPayment = '0'
diff --git a/charts/chainlink-cluster/templates/chainlink-deployment.yaml b/charts/chainlink-cluster/templates/chainlink-deployment.yaml
index 16665916f5..b434c9894b 100644
--- a/charts/chainlink-cluster/templates/chainlink-deployment.yaml
+++ b/charts/chainlink-cluster/templates/chainlink-deployment.yaml
@@ -37,6 +37,8 @@ spec:
{{- 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 }}
diff --git a/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml b/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml
index 4a74ff6c45..2cd9c3df2b 100644
--- a/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml
+++ b/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml
@@ -1,16 +1,18 @@
-{{- range $cfg := .Values.chainlink.nodes }}
{{- if $.Values.prometheusMonitor }}
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
+ name: {{ $.Release.Name }}-pod-monitor
labels:
release: grafana-agent
spec:
- selector:
- matchLabels:
- release: {{ $.Release.Name }}-{{ $cfg.name }}
+ namespaceSelector:
+ matchNames:
+ - "cl-cluster"
podMetricsEndpoints:
- port: access
- {{- end }}
----
-{{- end }}
\ No newline at end of file
+ selector:
+ matchLabels:
+ app: {{ $.Release.Name }}
+{{- end }}
+---
\ No newline at end of file
diff --git a/sonar-project.properties b/sonar-project.properties
index ea142ce17f..c40b5f361e 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -12,4 +12,4 @@ sonar.cpd.exclusions=**/contracts/**/*.sol, **/config.go, /core/services/ocr2/pl
# Tests' root folder, inclusions (tests to check and count) and exclusions
sonar.tests=.
sonar.test.inclusions=**/*_test.go, **/*.test.ts
-sonar.test.exclusions=**/integration-tests/**/*
+sonar.test.exclusions=**/integration-tests/**/*, **/charts/chainlink-cluster/dashboard/cmd/*
From 55d4d9c88667065f56257a71c133d3b700690097 Mon Sep 17 00:00:00 2001
From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com>
Date: Fri, 17 Nov 2023 09:10:37 +0400
Subject: [PATCH 168/327] [AUTO-7258] Setup log trigger load test using wasp
(#11267)
* add simple log upkeep counter contract
* WIP- add automationv2_1 load test
* update contract
* working state
* add config
* try GHA
* disable reads inside loadgen
* updates
* add specs
* fix linkfunds
* detach runner, add loglevel config
* increase geth capacity
* fix batching - test end FilterLogs
* fix batching
* fix log filter context and batching
* increase upkeep funding, fix event count calc
* increase GasLimitPerReport to 10.3M
* Decrease PerformLockoutWindow to 80k
* reduce sleep time - log filter batch
* use ConcurrentEVMClients
* increase RR CPU and Mem
* add pyroscope, add slack notifications
* add tag and image to test config
* fix dashbord URL
* contracts prettier
* run lint
* add new load test workflow
* fix AddNetworksConfig
* undo changes to benchmark test workflow
* add load/automationv2_1 to build test image steps
* lint
---
.github/actions/build-test-image/action.yml | 2 +-
.../workflows/automation-benchmark-tests.yml | 3 +-
.github/workflows/automation-load-tests.yml | 105 +++
CODEOWNERS | 1 +
.../native_solc_compile_all_automation | 1 +
.../testhelpers/SimpleLogUpkeepCounter.sol | 45 ++
.../simple_log_upkeep_counter_wrapper.go | 504 ++++++++++++++
...rapper-dependency-versions-do-not-edit.txt | 1 +
core/gethwrappers/go_generate.go | 1 +
.../contracts/contract_deployer.go | 21 +
.../contracts/ethereum_keeper_contracts.go | 27 +
.../automationv2_1/automationv2_1_test.go | 621 ++++++++++++++++++
integration-tests/load/automationv2_1/gun.go | 43 ++
.../load/automationv2_1/helpers.go | 71 ++
.../testreporters/keeper_benchmark.go | 6 +-
15 files changed, 1447 insertions(+), 5 deletions(-)
create mode 100644 .github/workflows/automation-load-tests.yml
create mode 100644 contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol
create mode 100644 core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go
create mode 100644 integration-tests/load/automationv2_1/automationv2_1_test.go
create mode 100644 integration-tests/load/automationv2_1/gun.go
create mode 100644 integration-tests/load/automationv2_1/helpers.go
diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml
index 252b292d03..4b1dce6ee1 100644
--- a/.github/actions/build-test-image/action.yml
+++ b/.github/actions/build-test-image/action.yml
@@ -15,7 +15,7 @@ inputs:
required: false
suites:
description: The test suites to build into the image
- default: chaos migration performance reorg smoke soak benchmark
+ default: chaos migration performance reorg smoke soak benchmark load/automationv2_1
required: false
base_image_tag:
description: The test base image version to use, if not provided it will use the version from the ./integration-tests/go.mod file
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index a4338d642b..0fff36f8df 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -6,7 +6,7 @@ on:
description: Chainlink image version to use
required: true
type: string
- default: 2.5.0
+ default: 2.6.0
chainlinkImage:
description: Chainlink image repo to use
required: true
@@ -108,6 +108,7 @@ jobs:
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 }}
+ suites: benchmark load/automationv2_1 chaos reorg
- name: Run Tests
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
env:
diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml
new file mode 100644
index 0000000000..eebd87322c
--- /dev/null
+++ b/.github/workflows/automation-load-tests.yml
@@ -0,0 +1,105 @@
+name: Automation Load Test
+on:
+ workflow_dispatch:
+ inputs:
+ chainlinkVersion:
+ description: Chainlink image version to use
+ required: true
+ type: string
+ default: 2.6.0
+ chainlinkImage:
+ description: Chainlink image repo to use
+ required: true
+ type: string
+ default: public.ecr.aws/chainlink/chainlink
+ network:
+ description: Network to run tests on
+ required: true
+ type: choice
+ options:
+ - SIMULATED
+ TestInputs:
+ description: TestInputs
+ required: false
+ type: string
+ slackMemberID:
+ description: Notifies test results (Not your @)
+ required: true
+ default: U02Q14G80TY
+ type: string
+
+jobs:
+ automation_load:
+ environment: integration
+ permissions:
+ checks: write
+ pull-requests: write
+ id-token: write
+ contents: read
+ name: ${{ inputs.network }} Automation Load Test
+ runs-on: ubuntu20.04-16cores-64GB
+ env:
+ SELECTED_NETWORKS: ${{ inputs.network }}
+ SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }}
+ SLACK_CHANNEL: C03KJ5S7KEK
+ TEST_INPUTS: ${{ inputs.TestInputs }}
+ CHAINLINK_ENV_USER: ${{ github.actor }}
+ REF_NAME: ${{ github.head_ref || github.ref_name }}
+ steps:
+ - name: Setup Push Tag
+ shell: bash
+ run: |
+ echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY
+ echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY
+ echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY
+ echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY
+
+ - name: Add mask
+ run: |
+ SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH)
+ echo ::add-mask::$SLACK_USER
+ echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV
+ - name: Checkout the repo
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ env.REF_NAME }}
+ - name: Build Test Image
+ 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 }}
+ suites: benchmark load/automationv2_1 chaos reorg
+ - name: Run Tests
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ env:
+ RR_CPU: 4000m
+ RR_MEM: 4Gi
+ DETACH_RUNNER: true
+ TEST_SUITE: automationv2_1
+ TEST_ARGS: -test.timeout 720h
+ ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }}
+ INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com
+ PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
+ PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
+ with:
+ test_command_to_run: cd integration-tests && go test -timeout 1h -v -run TestLogTrigger ./load/automationv2_1 -count=1
+ test_download_vendor_packages_command: make gomod
+ cl_repo: ${{ inputs.chainlinkImage }}
+ cl_image_tag: ${{ inputs.chainlinkVersion }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+ should_cleanup: false
+ go_mod_path: ./integration-tests/go.mod
+ QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
+ QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
+ - name: Collect Metrics
+ if: always()
+ id: collect-gha-metrics
+ uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ with:
+ basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ this-job-name: ${{ inputs.network }} Automation Load Test
+ test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
+ continue-on-error: true
diff --git a/CODEOWNERS b/CODEOWNERS
index 8ec42ed6dd..5f33e68e51 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -104,6 +104,7 @@ core/scripts/gateway @bolekk @pinebit
/.github/workflows/performance-tests.yml @smartcontractkit/test-tooling-team
/.github/workflows/automation-ondemand-tests.yml @smartcontractkit/keepers
/.github/workflows/automation-benchmark-tests.yml @smartcontractkit/keepers
+/.github/workflows/automation-load-tests.yml @smartcontractkit/keepers
/core/chainlink.Dockerfile @smartcontractkit/prodsec-public
diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation
index 1c54d67713..ddf6c2c8bf 100755
--- a/contracts/scripts/native_solc_compile_all_automation
+++ b/contracts/scripts/native_solc_compile_all_automation
@@ -41,6 +41,7 @@ compileContract automation/v2_0/KeeperRegistryLogic2_0.sol
compileContract automation/UpkeepTranscoder.sol
compileContract automation/mocks/MockAggregatorProxy.sol
compileContract automation/testhelpers/LogUpkeepCounter.sol
+compileContract automation/testhelpers/SimpleLogUpkeepCounter.sol
compileContract automation/mocks/KeeperRegistrar1_2Mock.sol
compileContract automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol
diff --git a/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol b/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol
new file mode 100644
index 0000000000..563c1354b6
--- /dev/null
+++ b/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity 0.8.6;
+
+import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol";
+
+contract SimpleLogUpkeepCounter is ILogAutomation {
+ event PerformingUpkeep(
+ address indexed from,
+ uint256 initialBlock,
+ uint256 lastBlock,
+ uint256 previousBlock,
+ uint256 counter,
+ uint256 timeToPerform
+ );
+
+ uint256 public lastBlock;
+ uint256 public previousPerformBlock;
+ uint256 public initialBlock;
+ uint256 public counter;
+ uint256 public timeToPerform;
+
+ constructor() {
+ previousPerformBlock = 0;
+ lastBlock = block.number;
+ initialBlock = 0;
+ counter = 0;
+ }
+
+ function checkLog(Log calldata log, bytes memory) external view override returns (bool, bytes memory) {
+ return (true, abi.encode(log));
+ }
+
+ function performUpkeep(bytes calldata performData) external override {
+ if (initialBlock == 0) {
+ initialBlock = block.number;
+ }
+ lastBlock = block.number;
+ counter = counter + 1;
+ previousPerformBlock = lastBlock;
+ Log memory log = abi.decode(performData, (Log));
+ timeToPerform = block.timestamp - log.timestamp;
+ emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter, timeToPerform);
+ }
+}
diff --git a/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go b/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go
new file mode 100644
index 0000000000..bb28c8bd6c
--- /dev/null
+++ b/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go
@@ -0,0 +1,504 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package simple_log_upkeep_counter_wrapper
+
+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 Log struct {
+ Index *big.Int
+ Timestamp *big.Int
+ TxHash [32]byte
+ BlockNumber *big.Int
+ BlockHash [32]byte
+ Source common.Address
+ Topics [][32]byte
+ Data []byte
+}
+
+var SimpleLogUpkeepCounterMetaData = &bind.MetaData{
+ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timeToPerform\",\"type\":\"uint256\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeToPerform\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
+ Bin: "0x608060405234801561001057600080fd5b5060006001819055438155600281905560035561088a806100326000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806361bc221a1161005b57806361bc221a146100d4578063806b984f146100dd578063917d895f146100e6578063c6066f0d146100ef57600080fd5b80632cb158641461008257806340691db41461009e5780634585e33b146100bf575b600080fd5b61008b60025481565b6040519081526020015b60405180910390f35b6100b16100ac366004610384565b6100f8565b60405161009592919061055e565b6100d26100cd366004610312565b61012a565b005b61008b60035481565b61008b60005481565b61008b60015481565b61008b60045481565b6000606060018460405160200161010f91906105db565b604051602081830303815290604052915091505b9250929050565b60025461013657436002555b436000556003546101489060016107f0565b6003556000805460015561015e828401846103f1565b90508060200151426101709190610808565b6004819055600254600054600154600354604080519485526020850193909352918301526060820152608081019190915232907f4874b8dd61a40fe23599b4360a9a824d7081742fca9f555bcee3d389c4f4bd659060a00160405180910390a2505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146101f957600080fd5b919050565b600082601f83011261020f57600080fd5b8135602067ffffffffffffffff82111561022b5761022b61084e565b8160051b61023a8282016106d6565b83815282810190868401838801850189101561025557600080fd5b600093505b8584101561027857803583526001939093019291840191840161025a565b50979650505050505050565b600082601f83011261029557600080fd5b813567ffffffffffffffff8111156102af576102af61084e565b6102e060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016106d6565b8181528460208386010111156102f557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806020838503121561032557600080fd5b823567ffffffffffffffff8082111561033d57600080fd5b818501915085601f83011261035157600080fd5b81358181111561036057600080fd5b86602082850101111561037257600080fd5b60209290920196919550909350505050565b6000806040838503121561039757600080fd5b823567ffffffffffffffff808211156103af57600080fd5b9084019061010082870312156103c457600080fd5b909250602084013590808211156103da57600080fd5b506103e785828601610284565b9150509250929050565b60006020828403121561040357600080fd5b813567ffffffffffffffff8082111561041b57600080fd5b90830190610100828603121561043057600080fd5b6104386106ac565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015261047060a084016101d5565b60a082015260c08301358281111561048757600080fd5b610493878286016101fe565b60c08301525060e0830135828111156104ab57600080fd5b6104b787828601610284565b60e08301525095945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156104f857600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b821515815260006020604081840152835180604085015260005b8181101561059457858101830151858201606001528201610578565b818111156105a6576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152608082013560a082015273ffffffffffffffffffffffffffffffffffffffff61062f60a084016101d5565b1660c0820152600061064460c0840184610725565b6101008060e086015261065c610120860183856104c6565b925061066b60e087018761078c565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086850301828701526106a1848483610515565b979650505050505050565b604051610100810167ffffffffffffffff811182821017156106d0576106d061084e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561071d5761071d61084e565b604052919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261075a57600080fd5b830160208101925035905067ffffffffffffffff81111561077a57600080fd5b8060051b360383131561012357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107c157600080fd5b830160208101925035905067ffffffffffffffff8111156107e157600080fd5b80360383131561012357600080fd5b600082198211156108035761080361081f565b500190565b60008282101561081a5761081a61081f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a",
+}
+
+var SimpleLogUpkeepCounterABI = SimpleLogUpkeepCounterMetaData.ABI
+
+var SimpleLogUpkeepCounterBin = SimpleLogUpkeepCounterMetaData.Bin
+
+func DeploySimpleLogUpkeepCounter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SimpleLogUpkeepCounter, error) {
+ parsed, err := SimpleLogUpkeepCounterMetaData.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(SimpleLogUpkeepCounterBin), backend)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &SimpleLogUpkeepCounter{address: address, abi: *parsed, SimpleLogUpkeepCounterCaller: SimpleLogUpkeepCounterCaller{contract: contract}, SimpleLogUpkeepCounterTransactor: SimpleLogUpkeepCounterTransactor{contract: contract}, SimpleLogUpkeepCounterFilterer: SimpleLogUpkeepCounterFilterer{contract: contract}}, nil
+}
+
+type SimpleLogUpkeepCounter struct {
+ address common.Address
+ abi abi.ABI
+ SimpleLogUpkeepCounterCaller
+ SimpleLogUpkeepCounterTransactor
+ SimpleLogUpkeepCounterFilterer
+}
+
+type SimpleLogUpkeepCounterCaller struct {
+ contract *bind.BoundContract
+}
+
+type SimpleLogUpkeepCounterTransactor struct {
+ contract *bind.BoundContract
+}
+
+type SimpleLogUpkeepCounterFilterer struct {
+ contract *bind.BoundContract
+}
+
+type SimpleLogUpkeepCounterSession struct {
+ Contract *SimpleLogUpkeepCounter
+ CallOpts bind.CallOpts
+ TransactOpts bind.TransactOpts
+}
+
+type SimpleLogUpkeepCounterCallerSession struct {
+ Contract *SimpleLogUpkeepCounterCaller
+ CallOpts bind.CallOpts
+}
+
+type SimpleLogUpkeepCounterTransactorSession struct {
+ Contract *SimpleLogUpkeepCounterTransactor
+ TransactOpts bind.TransactOpts
+}
+
+type SimpleLogUpkeepCounterRaw struct {
+ Contract *SimpleLogUpkeepCounter
+}
+
+type SimpleLogUpkeepCounterCallerRaw struct {
+ Contract *SimpleLogUpkeepCounterCaller
+}
+
+type SimpleLogUpkeepCounterTransactorRaw struct {
+ Contract *SimpleLogUpkeepCounterTransactor
+}
+
+func NewSimpleLogUpkeepCounter(address common.Address, backend bind.ContractBackend) (*SimpleLogUpkeepCounter, error) {
+ abi, err := abi.JSON(strings.NewReader(SimpleLogUpkeepCounterABI))
+ if err != nil {
+ return nil, err
+ }
+ contract, err := bindSimpleLogUpkeepCounter(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &SimpleLogUpkeepCounter{address: address, abi: abi, SimpleLogUpkeepCounterCaller: SimpleLogUpkeepCounterCaller{contract: contract}, SimpleLogUpkeepCounterTransactor: SimpleLogUpkeepCounterTransactor{contract: contract}, SimpleLogUpkeepCounterFilterer: SimpleLogUpkeepCounterFilterer{contract: contract}}, nil
+}
+
+func NewSimpleLogUpkeepCounterCaller(address common.Address, caller bind.ContractCaller) (*SimpleLogUpkeepCounterCaller, error) {
+ contract, err := bindSimpleLogUpkeepCounter(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SimpleLogUpkeepCounterCaller{contract: contract}, nil
+}
+
+func NewSimpleLogUpkeepCounterTransactor(address common.Address, transactor bind.ContractTransactor) (*SimpleLogUpkeepCounterTransactor, error) {
+ contract, err := bindSimpleLogUpkeepCounter(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SimpleLogUpkeepCounterTransactor{contract: contract}, nil
+}
+
+func NewSimpleLogUpkeepCounterFilterer(address common.Address, filterer bind.ContractFilterer) (*SimpleLogUpkeepCounterFilterer, error) {
+ contract, err := bindSimpleLogUpkeepCounter(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &SimpleLogUpkeepCounterFilterer{contract: contract}, nil
+}
+
+func bindSimpleLogUpkeepCounter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := SimpleLogUpkeepCounterMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SimpleLogUpkeepCounter.Contract.SimpleLogUpkeepCounterCaller.contract.Call(opts, result, method, params...)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.Contract.SimpleLogUpkeepCounterTransactor.contract.Transfer(opts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.Contract.SimpleLogUpkeepCounterTransactor.contract.Transact(opts, method, params...)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SimpleLogUpkeepCounter.Contract.contract.Call(opts, result, method, params...)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.Contract.contract.Transfer(opts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.Contract.contract.Transact(opts, method, params...)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckLog(opts *bind.CallOpts, log Log, arg1 []byte) (bool, []byte, error) {
+ var out []interface{}
+ err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "checkLog", log, arg1)
+
+ if err != nil {
+ return *new(bool), *new([]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+ out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte)
+
+ return out0, out1, err
+
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) CheckLog(log Log, arg1 []byte) (bool, []byte, error) {
+ return _SimpleLogUpkeepCounter.Contract.CheckLog(&_SimpleLogUpkeepCounter.CallOpts, log, arg1)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) CheckLog(log Log, arg1 []byte) (bool, []byte, error) {
+ return _SimpleLogUpkeepCounter.Contract.CheckLog(&_SimpleLogUpkeepCounter.CallOpts, log, arg1)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) Counter(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "counter")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) Counter() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.Counter(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) Counter() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.Counter(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) InitialBlock(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "initialBlock")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) InitialBlock() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.InitialBlock(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) InitialBlock() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.InitialBlock(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) LastBlock(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "lastBlock")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) LastBlock() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.LastBlock(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) LastBlock() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.LastBlock(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) PreviousPerformBlock(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "previousPerformBlock")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) PreviousPerformBlock() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.PreviousPerformBlock(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) PreviousPerformBlock() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.PreviousPerformBlock(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) TimeToPerform(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "timeToPerform")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) TimeToPerform() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.TimeToPerform(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) TimeToPerform() (*big.Int, error) {
+ return _SimpleLogUpkeepCounter.Contract.TimeToPerform(&_SimpleLogUpkeepCounter.CallOpts)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactor) PerformUpkeep(opts *bind.TransactOpts, performData []byte) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.contract.Transact(opts, "performUpkeep", performData)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) PerformUpkeep(performData []byte) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.Contract.PerformUpkeep(&_SimpleLogUpkeepCounter.TransactOpts, performData)
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorSession) PerformUpkeep(performData []byte) (*types.Transaction, error) {
+ return _SimpleLogUpkeepCounter.Contract.PerformUpkeep(&_SimpleLogUpkeepCounter.TransactOpts, performData)
+}
+
+type SimpleLogUpkeepCounterPerformingUpkeepIterator struct {
+ Event *SimpleLogUpkeepCounterPerformingUpkeep
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SimpleLogUpkeepCounterPerformingUpkeepIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SimpleLogUpkeepCounterPerformingUpkeep)
+ 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(SimpleLogUpkeepCounterPerformingUpkeep)
+ 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 *SimpleLogUpkeepCounterPerformingUpkeepIterator) Error() error {
+ return it.fail
+}
+
+func (it *SimpleLogUpkeepCounterPerformingUpkeepIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SimpleLogUpkeepCounterPerformingUpkeep struct {
+ From common.Address
+ InitialBlock *big.Int
+ LastBlock *big.Int
+ PreviousBlock *big.Int
+ Counter *big.Int
+ TimeToPerform *big.Int
+ Raw types.Log
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterFilterer) FilterPerformingUpkeep(opts *bind.FilterOpts, from []common.Address) (*SimpleLogUpkeepCounterPerformingUpkeepIterator, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+
+ logs, sub, err := _SimpleLogUpkeepCounter.contract.FilterLogs(opts, "PerformingUpkeep", fromRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SimpleLogUpkeepCounterPerformingUpkeepIterator{contract: _SimpleLogUpkeepCounter.contract, event: "PerformingUpkeep", logs: logs, sub: sub}, nil
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterFilterer) WatchPerformingUpkeep(opts *bind.WatchOpts, sink chan<- *SimpleLogUpkeepCounterPerformingUpkeep, from []common.Address) (event.Subscription, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+
+ logs, sub, err := _SimpleLogUpkeepCounter.contract.WatchLogs(opts, "PerformingUpkeep", fromRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SimpleLogUpkeepCounterPerformingUpkeep)
+ if err := _SimpleLogUpkeepCounter.contract.UnpackLog(event, "PerformingUpkeep", 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 (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterFilterer) ParsePerformingUpkeep(log types.Log) (*SimpleLogUpkeepCounterPerformingUpkeep, error) {
+ event := new(SimpleLogUpkeepCounterPerformingUpkeep)
+ if err := _SimpleLogUpkeepCounter.contract.UnpackLog(event, "PerformingUpkeep", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) ParseLog(log types.Log) (generated.AbigenLog, error) {
+ switch log.Topics[0] {
+ case _SimpleLogUpkeepCounter.abi.Events["PerformingUpkeep"].ID:
+ return _SimpleLogUpkeepCounter.ParsePerformingUpkeep(log)
+
+ default:
+ return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0])
+ }
+}
+
+func (SimpleLogUpkeepCounterPerformingUpkeep) Topic() common.Hash {
+ return common.HexToHash("0x4874b8dd61a40fe23599b4360a9a824d7081742fca9f555bcee3d389c4f4bd65")
+}
+
+func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) Address() common.Address {
+ return _SimpleLogUpkeepCounter.address
+}
+
+type SimpleLogUpkeepCounterInterface interface {
+ CheckLog(opts *bind.CallOpts, log Log, arg1 []byte) (bool, []byte, error)
+
+ Counter(opts *bind.CallOpts) (*big.Int, error)
+
+ InitialBlock(opts *bind.CallOpts) (*big.Int, error)
+
+ LastBlock(opts *bind.CallOpts) (*big.Int, error)
+
+ PreviousPerformBlock(opts *bind.CallOpts) (*big.Int, error)
+
+ TimeToPerform(opts *bind.CallOpts) (*big.Int, error)
+
+ PerformUpkeep(opts *bind.TransactOpts, performData []byte) (*types.Transaction, error)
+
+ FilterPerformingUpkeep(opts *bind.FilterOpts, from []common.Address) (*SimpleLogUpkeepCounterPerformingUpkeepIterator, error)
+
+ WatchPerformingUpkeep(opts *bind.WatchOpts, sink chan<- *SimpleLogUpkeepCounterPerformingUpkeep, from []common.Address) (event.Subscription, error)
+
+ ParsePerformingUpkeep(log types.Log) (*SimpleLogUpkeepCounterPerformingUpkeep, error)
+
+ ParseLog(log types.Log) (generated.AbigenLog, error)
+
+ Address() common.Address
+}
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 6482c01cf8..6efc75fce9 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
@@ -50,6 +50,7 @@ operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.a
operator_wrapper: ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin d7abd0e67f30a3a4c9c04c896124391306fa364fcf579fa6df04dbf912b48568
oracle_wrapper: ../../contracts/solc/v0.6/Oracle/Oracle.abi ../../contracts/solc/v0.6/Oracle/Oracle.bin 7af2fbac22a6e8c2847e8e685a5400cac5101d72ddf5365213beb79e4dede43a
perform_data_checker_wrapper: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73
+simple_log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin 0a7a0cc4da7dc2a3d0a0c36c746b1adc044af5cad1838367356a0604f3255a01
solidity_vrf_consumer_interface: ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.bin ecc99378aa798014de9db42b2eb81320778b0663dbe208008dad75ccdc1d4366
solidity_vrf_consumer_interface_v08: ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.bin b14f9136b15e3dc9d6154d5700f3ed4cf88ddc4f70f20c3bb57fc46050904c8f
solidity_vrf_coordinator_interface: ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.bin a23d3c395156804788c7f6fbda2994e8f7184304c0f0c9f2c4ddeaf073d346d2
diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go
index 3965c15908..07e4fa9b8f 100644
--- a/core/gethwrappers/go_generate.go
+++ b/core/gethwrappers/go_generate.go
@@ -59,6 +59,7 @@ package gethwrappers
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin AutomationUtils automation_utils_2_1
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin AutomationForwarderLogic automation_forwarder_logic
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin LogUpkeepCounter log_upkeep_counter_wrapper
+//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin SimpleLogUpkeepCounter simple_log_upkeep_counter_wrapper
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin LogTriggeredStreamsLookup log_triggered_streams_lookup_wrapper
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.bin DummyProtocol dummy_protocol_wrapper
diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go
index 45195d327e..000fe7b2b8 100644
--- a/integration-tests/contracts/contract_deployer.go
+++ b/integration-tests/contracts/contract_deployer.go
@@ -55,6 +55,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/perform_data_checker_wrapper"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_counter_wrapper"
@@ -92,6 +93,7 @@ type ContractDeployer interface {
LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error)
DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error)
DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error)
+ DeployAutomationSimpleLogTriggerConsumer() (KeeperConsumer, error)
DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error)
DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() (KeeperConsumer, error)
DeployKeeperConsumerPerformance(
@@ -1292,6 +1294,25 @@ func (e *EthereumContractDeployer) DeployAutomationLogTriggerConsumer(testInterv
}, err
}
+func (e *EthereumContractDeployer) DeployAutomationSimpleLogTriggerConsumer() (KeeperConsumer, error) {
+ address, _, instance, err := e.client.DeployContract("SimpleLogUpkeepCounter", func(
+ auth *bind.TransactOpts,
+ backend bind.ContractBackend,
+ ) (common.Address, *types.Transaction, interface{}, error) {
+ return simple_log_upkeep_counter_wrapper.DeploySimpleLogUpkeepCounter(
+ auth, backend,
+ )
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &EthereumAutomationSimpleLogCounterConsumer{
+ client: e.client,
+ consumer: instance.(*simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounter),
+ address: address,
+ }, err
+}
+
func (e *EthereumContractDeployer) DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) {
address, _, instance, err := e.client.DeployContract("StreamsLookupUpkeep", func(
auth *bind.TransactOpts,
diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go
index 2c0250e745..7519b5de4c 100644
--- a/integration-tests/contracts/ethereum_keeper_contracts.go
+++ b/integration-tests/contracts/ethereum_keeper_contracts.go
@@ -35,6 +35,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/perform_data_checker_wrapper"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder"
@@ -1821,6 +1822,32 @@ func (v *EthereumAutomationLogCounterConsumer) Counter(ctx context.Context) (*bi
return cnt, nil
}
+type EthereumAutomationSimpleLogCounterConsumer struct {
+ client blockchain.EVMClient
+ consumer *simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounter
+ address *common.Address
+}
+
+func (v *EthereumAutomationSimpleLogCounterConsumer) Address() string {
+ return v.address.Hex()
+}
+
+func (v *EthereumAutomationSimpleLogCounterConsumer) Start() error {
+ return nil
+}
+
+func (v *EthereumAutomationSimpleLogCounterConsumer) Counter(ctx context.Context) (*big.Int, error) {
+ opts := &bind.CallOpts{
+ From: common.HexToAddress(v.client.GetDefaultWallet().Address()),
+ Context: ctx,
+ }
+ cnt, err := v.consumer.Counter(opts)
+ if err != nil {
+ return nil, err
+ }
+ return cnt, nil
+}
+
// EthereumKeeperConsumerPerformance represents a more complicated keeper consumer contract, one intended only for
// performance tests.
type EthereumKeeperConsumerPerformance struct {
diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go
new file mode 100644
index 0000000000..dfef099c17
--- /dev/null
+++ b/integration-tests/load/automationv2_1/automationv2_1_test.go
@@ -0,0 +1,621 @@
+package automationv2_1
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+
+ geth "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/slack-go/slack"
+ ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
+ ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
+ "github.com/smartcontractkit/wasp"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-testing-framework/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/config"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink"
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
+ "github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/networks"
+ "github.com/smartcontractkit/chainlink/integration-tests/actions"
+ "github.com/smartcontractkit/chainlink/integration-tests/client"
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
+ contractseth "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
+ "github.com/smartcontractkit/chainlink/integration-tests/testreporters"
+ registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper"
+)
+
+const (
+ StartupWaitTime = 30 * time.Second
+ StopWaitTime = 60 * time.Second
+)
+
+var (
+ baseTOML = `[Feature]
+LogPoller = true
+
+[OCR2]
+Enabled = true
+
+[P2P]
+[P2P.V2]
+Enabled = true
+AnnounceAddresses = ["0.0.0.0:6690"]
+ListenAddresses = ["0.0.0.0:6690"]`
+
+ minimumNodeSpec = map[string]interface{}{
+ "resources": map[string]interface{}{
+ "requests": map[string]interface{}{
+ "cpu": "2000m",
+ "memory": "4Gi",
+ },
+ "limits": map[string]interface{}{
+ "cpu": "2000m",
+ "memory": "4Gi",
+ },
+ },
+ }
+
+ minimumDbSpec = map[string]interface{}{
+ "resources": map[string]interface{}{
+ "requests": map[string]interface{}{
+ "cpu": "1000m",
+ "memory": "1Gi",
+ },
+ "limits": map[string]interface{}{
+ "cpu": "1000m",
+ "memory": "1Gi",
+ },
+ },
+ "stateful": true,
+ "capacity": "5Gi",
+ }
+
+ recNodeSpec = map[string]interface{}{
+ "resources": map[string]interface{}{
+ "requests": map[string]interface{}{
+ "cpu": "4000m",
+ "memory": "8Gi",
+ },
+ "limits": map[string]interface{}{
+ "cpu": "4000m",
+ "memory": "8Gi",
+ },
+ },
+ }
+
+ recDbSpec = map[string]interface{}{
+ "resources": map[string]interface{}{
+ "requests": map[string]interface{}{
+ "cpu": "2000m",
+ "memory": "2Gi",
+ },
+ "limits": map[string]interface{}{
+ "cpu": "2000m",
+ "memory": "2Gi",
+ },
+ },
+ "stateful": true,
+ "capacity": "10Gi",
+ }
+)
+
+var (
+ numberofNodes, _ = strconv.Atoi(getEnv("NUMBEROFNODES", "6")) // Number of nodes in the DON
+ numberOfUpkeeps, _ = strconv.Atoi(getEnv("NUMBEROFUPKEEPS", "100")) // Number of log triggered upkeeps
+ duration, _ = strconv.Atoi(getEnv("DURATION", "900")) // Test duration in seconds
+ blockTime, _ = strconv.Atoi(getEnv("BLOCKTIME", "1")) // Block time in seconds for geth simulated dev network
+ numberOfEvents, _ = strconv.Atoi(getEnv("NUMBEROFEVENTS", "1")) // Number of events to emit per trigger
+ specType = getEnv("SPECTYPE", "minimum") // minimum, recommended, local specs for the test
+ logLevel = getEnv("LOGLEVEL", "info") // log level for the chainlink nodes
+ pyroscope, _ = strconv.ParseBool(getEnv("PYROSCOPE", "false")) // enable pyroscope for the chainlink nodes
+)
+
+func TestLogTrigger(t *testing.T) {
+ l := logging.GetTestLogger(t)
+
+ l.Info().Msg("Starting automation v2.1 log trigger load test")
+ l.Info().Str("TEST_INPUTS", os.Getenv("TEST_INPUTS")).Int("Number of Nodes", numberofNodes).
+ Int("Number of Upkeeps", numberOfUpkeeps).
+ Int("Duration", duration).
+ Int("Block Time", blockTime).
+ Int("Number of Events", numberOfEvents).
+ Str("Spec Type", specType).
+ Str("Log Level", logLevel).
+ Str("Image", os.Getenv(config.EnvVarCLImage)).
+ Str("Tag", os.Getenv(config.EnvVarCLTag)).
+ Msg("Test Config")
+
+ testConfig := fmt.Sprintf("Number of Nodes: %d\nNumber of Upkeeps: %d\nDuration: %d\nBlock Time: %d\n"+
+ "Number of Events: %d\nSpec Type: %s\nLog Level: %s\nImage: %s\nTag: %s\n", numberofNodes, numberOfUpkeeps, duration,
+ blockTime, numberOfEvents, specType, logLevel, os.Getenv(config.EnvVarCLImage), os.Getenv(config.EnvVarCLTag))
+
+ testNetwork := networks.MustGetSelectedNetworksFromEnv()[0]
+ testType := "load"
+ loadDuration := time.Duration(duration) * time.Second
+ automationDefaultLinkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(10000))) //10000 LINK
+ automationDefaultUpkeepGasLimit := uint32(1_000_000)
+
+ registrySettings := &contracts.KeeperRegistrySettings{
+ PaymentPremiumPPB: uint32(0),
+ FlatFeeMicroLINK: uint32(40_000),
+ BlockCountPerTurn: big.NewInt(100),
+ CheckGasLimit: uint32(45_000_000), //45M
+ StalenessSeconds: big.NewInt(90_000),
+ GasCeilingMultiplier: uint16(2),
+ MaxPerformGas: uint32(5_000_000),
+ MinUpkeepSpend: big.NewInt(0),
+ FallbackGasPrice: big.NewInt(2e11),
+ FallbackLinkPrice: big.NewInt(2e18),
+ MaxCheckDataSize: uint32(5_000),
+ MaxPerformDataSize: uint32(5_000),
+ RegistryVersion: contractseth.RegistryVersion_2_1,
+ }
+
+ testEnvironment := environment.New(&environment.Config{
+ TTL: time.Hour * 24, // 1 day,
+ NamespacePrefix: fmt.Sprintf(
+ "automation-%s-%s",
+ testType,
+ strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"),
+ ),
+ Test: t,
+ PreventPodEviction: true,
+ })
+
+ if testEnvironment.WillUseRemoteRunner() {
+ key := "TEST_INPUTS"
+ err := os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key))
+ require.NoError(t, err, "failed to set the environment variable TEST_INPUTS for remote runner")
+
+ key = config.EnvVarPyroscopeServer
+ err = os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key))
+ require.NoError(t, err, "failed to set the environment variable PYROSCOPE_SERVER for remote runner")
+
+ key = config.EnvVarPyroscopeKey
+ err = os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key))
+ require.NoError(t, err, "failed to set the environment variable PYROSCOPE_KEY for remote runner")
+
+ key = "GRAFANA_DASHBOARD_URL"
+ err = os.Setenv(fmt.Sprintf("TEST_%s", key), getEnv(key, ""))
+ require.NoError(t, err, "failed to set the environment variable GRAFANA_DASHBOARD_URL for remote runner")
+ }
+
+ testEnvironment.
+ AddHelm(ethereum.New(ðereum.Props{
+ NetworkName: testNetwork.Name,
+ Simulated: testNetwork.Simulated,
+ WsURLs: testNetwork.URLs,
+ Values: map[string]interface{}{
+ "resources": map[string]interface{}{
+ "requests": map[string]interface{}{
+ "cpu": "4000m",
+ "memory": "4Gi",
+ },
+ "limits": map[string]interface{}{
+ "cpu": "8000m",
+ "memory": "8Gi",
+ },
+ },
+ "geth": map[string]interface{}{
+ "blocktime": blockTime,
+ "capacity": "10Gi",
+ },
+ },
+ }))
+
+ err := testEnvironment.Run()
+ require.NoError(t, err, "Error launching test environment")
+
+ if testEnvironment.WillUseRemoteRunner() {
+ return
+ }
+
+ var (
+ nodeSpec = minimumNodeSpec
+ dbSpec = minimumDbSpec
+ )
+
+ switch specType {
+ case "recommended":
+ nodeSpec = recNodeSpec
+ dbSpec = recDbSpec
+ case "local":
+ nodeSpec = map[string]interface{}{}
+ dbSpec = map[string]interface{}{"stateful": true}
+ default:
+ // minimum:
+
+ }
+
+ if !pyroscope {
+ err = os.Setenv(config.EnvVarPyroscopeServer, "")
+ require.NoError(t, err, "Error setting pyroscope server env var")
+ }
+
+ err = os.Setenv(config.EnvVarPyroscopeEnvironment, testEnvironment.Cfg.Namespace)
+ require.NoError(t, err, "Error setting pyroscope environment env var")
+
+ for i := 0; i < numberofNodes+1; i++ { // +1 for the OCR boot node
+ var nodeTOML string
+ if i == 1 || i == 3 {
+ nodeTOML = fmt.Sprintf("%s\n\n[Log]\nLevel = \"%s\"", baseTOML, logLevel)
+ } else {
+ nodeTOML = fmt.Sprintf("%s\n\n[Log]\nLevel = \"info\"", baseTOML)
+ }
+ nodeTOML = networks.AddNetworksConfig(nodeTOML, testNetwork)
+ testEnvironment.AddHelm(chainlink.New(i, map[string]any{
+ "toml": nodeTOML,
+ "chainlink": nodeSpec,
+ "db": dbSpec,
+ }))
+ }
+
+ err = testEnvironment.Run()
+ require.NoError(t, err, "Error running chainlink DON")
+
+ chainClient, err := blockchain.NewEVMClient(testNetwork, testEnvironment, l)
+ require.NoError(t, err, "Error building chain client")
+
+ contractDeployer, err := contracts.NewContractDeployer(chainClient, l)
+ require.NoError(t, err, "Error building contract deployer")
+
+ chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment)
+ require.NoError(t, err, "Error connecting to chainlink nodes")
+
+ chainClient.ParallelTransactions(true)
+
+ linkToken, err := contractDeployer.DeployLinkTokenContract()
+ require.NoError(t, err, "Error deploying link token contract")
+
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Failed waiting for contracts to deploy")
+
+ registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar(
+ t, contractseth.RegistryVersion_2_1, *registrySettings, linkToken, contractDeployer, chainClient,
+ )
+
+ err = actions.FundChainlinkNodesAddress(chainlinkNodes[1:], chainClient, big.NewFloat(100), 0)
+ require.NoError(t, err, "Error funding chainlink nodes")
+
+ actions.CreateOCRKeeperJobs(
+ t,
+ chainlinkNodes,
+ registry.Address(),
+ chainClient.GetChainID().Int64(),
+ 0,
+ contractseth.RegistryVersion_2_1,
+ )
+
+ S, oracleIdentities, err := actions.GetOracleIdentities(chainlinkNodes)
+ require.NoError(t, err, "Error getting oracle identities")
+ offC, err := json.Marshal(ocr2keepers30config.OffchainConfig{
+ TargetProbability: "0.999",
+ TargetInRounds: 1,
+ PerformLockoutWindow: 80_000, // Copied from arbitrum mainnet prod value
+ GasLimitPerReport: 10_300_000,
+ GasOverheadPerUpkeep: 300_000,
+ MinConfirmations: 0,
+ MaxUpkeepBatchSize: 10,
+ })
+ require.NoError(t, err, "Error marshalling offchain config")
+
+ signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err := ocr3.ContractSetConfigArgsForTests(
+ 10*time.Second, // deltaProgress time.Duration,
+ 15*time.Second, // deltaResend time.Duration,
+ 500*time.Millisecond, // deltaInitial time.Duration,
+ 1000*time.Millisecond, // deltaRound time.Duration,
+ 200*time.Millisecond, // deltaGrace time.Duration,
+ 300*time.Millisecond, // deltaCertifiedCommitRequest time.Duration
+ 15*time.Second, // deltaStage time.Duration,
+ 24, // rMax uint64,
+ S, // s []int,
+ oracleIdentities, // oracles []OracleIdentityExtra,
+ offC, // reportingPluginConfig []byte,
+ 20*time.Millisecond, // maxDurationQuery time.Duration,
+ 20*time.Millisecond, // maxDurationObservation time.Duration, // good to here
+ 1200*time.Millisecond, // maxDurationShouldAcceptAttestedReport time.Duration,
+ 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration,
+ 1, // f int,
+ nil, // onchainConfig []byte,
+ )
+ require.NoError(t, err, "Error setting OCR config vars")
+
+ var signers []common.Address
+ for _, signer := range signerOnchainPublicKeys {
+ require.Equal(t, 20, len(signer), "OnChainPublicKey '%v' has wrong length for address", signer)
+ signers = append(signers, common.BytesToAddress(signer))
+ }
+
+ var transmitters []common.Address
+ for _, transmitter := range transmitterAccounts {
+ require.True(t, common.IsHexAddress(string(transmitter)), "TransmitAccount '%s' is not a valid Ethereum address", string(transmitter))
+ transmitters = append(transmitters, common.HexToAddress(string(transmitter)))
+ }
+
+ onchainConfig, err := registrySettings.EncodeOnChainConfig(registrar.Address(), common.HexToAddress(chainClient.GetDefaultWallet().Address()))
+ require.NoError(t, err, "Error encoding onchain config")
+ l.Info().Msg("Done building OCR config")
+ ocrConfig := contracts.OCRv2Config{
+ Signers: signers,
+ Transmitters: transmitters,
+ F: f,
+ OnchainConfig: onchainConfig,
+ OffchainConfigVersion: offchainConfigVersion,
+ OffchainConfig: offchainConfig,
+ }
+
+ err = registry.SetConfig(*registrySettings, ocrConfig)
+ require.NoError(t, err, "Error setting registry config")
+
+ consumerContracts := make([]contracts.KeeperConsumer, 0)
+ triggerContracts := make([]contracts.LogEmitter, 0)
+
+ utilsABI, err := automation_utils_2_1.AutomationUtilsMetaData.GetAbi()
+ require.NoError(t, err, "Error getting automation utils abi")
+ registrarABI, err := registrar21.AutomationRegistrarMetaData.GetAbi()
+ require.NoError(t, err, "Error getting automation registrar abi")
+ emitterABI, err := log_emitter.LogEmitterMetaData.GetAbi()
+ require.NoError(t, err, "Error getting log emitter abi")
+ consumerABI, err := simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounterMetaData.GetAbi()
+ require.NoError(t, err, "Error getting consumer abi")
+
+ var bytes0 = [32]byte{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+ registrationTxHashes := make([]common.Hash, 0)
+ upkeepIds := make([]*big.Int, 0)
+
+ for i := 0; i < numberOfUpkeeps; i++ {
+ consumerContract, err := contractDeployer.DeployAutomationSimpleLogTriggerConsumer()
+ require.NoError(t, err, "Error deploying automation consumer contract")
+ consumerContracts = append(consumerContracts, consumerContract)
+ l.Debug().
+ Str("Contract Address", consumerContract.Address()).
+ Int("Number", i+1).
+ Int("Out Of", numberOfUpkeeps).
+ Msg("Deployed Automation Log Trigger Consumer Contract")
+
+ cEVMClient, err := blockchain.ConcurrentEVMClient(testNetwork, testEnvironment, chainClient, l)
+ require.NoError(t, err, "Error building concurrent chain client")
+
+ cContractDeployer, err := contracts.NewContractDeployer(cEVMClient, l)
+ require.NoError(t, err, "Error building concurrent contract deployer")
+
+ triggerContract, err := cContractDeployer.DeployLogEmitterContract()
+ require.NoError(t, err, "Error deploying log emitter contract")
+ triggerContracts = append(triggerContracts, triggerContract)
+ l.Debug().
+ Str("Contract Address", triggerContract.Address().Hex()).
+ Int("Number", i+1).
+ Int("Out Of", numberOfUpkeeps).
+ Msg("Deployed Automation Log Trigger Emitter Contract")
+ }
+
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Failed waiting for contracts to deploy")
+
+ for i, consumerContract := range consumerContracts {
+ logTriggerConfigStruct := automation_utils_2_1.LogTriggerConfig{
+ ContractAddress: triggerContracts[i].Address(),
+ FilterSelector: 0,
+ Topic0: emitterABI.Events["Log1"].ID,
+ Topic1: bytes0,
+ Topic2: bytes0,
+ Topic3: bytes0,
+ }
+ encodedLogTriggerConfig, err := utilsABI.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct)
+ require.NoError(t, err, "Error encoding log trigger config")
+ l.Debug().Bytes("Encoded Log Trigger Config", encodedLogTriggerConfig).Msg("Encoded Log Trigger Config")
+
+ registrationRequest, err := registrarABI.Pack(
+ "register",
+ fmt.Sprintf("LogTriggerUpkeep-%d", i),
+ []byte("test@mail.com"),
+ common.HexToAddress(consumerContract.Address()),
+ automationDefaultUpkeepGasLimit,
+ common.HexToAddress(chainClient.GetDefaultWallet().Address()),
+ uint8(1),
+ []byte("0"),
+ encodedLogTriggerConfig,
+ []byte("0"),
+ automationDefaultLinkFunds,
+ common.HexToAddress(chainClient.GetDefaultWallet().Address()),
+ )
+ require.NoError(t, err, "Error encoding upkeep registration request")
+ tx, err := linkToken.TransferAndCall(registrar.Address(), automationDefaultLinkFunds, registrationRequest)
+ require.NoError(t, err, "Error sending upkeep registration request")
+ registrationTxHashes = append(registrationTxHashes, tx.Hash())
+ }
+
+ err = chainClient.WaitForEvents()
+ require.NoError(t, err, "Failed waiting for upkeeps to be registered")
+
+ for _, txHash := range registrationTxHashes {
+ receipt, err := chainClient.GetTxReceipt(txHash)
+ require.NoError(t, err, "Registration tx should be completed")
+ var upkeepId *big.Int
+ for _, rawLog := range receipt.Logs {
+ parsedUpkeepId, err := registry.ParseUpkeepIdFromRegisteredLog(rawLog)
+ if err == nil {
+ upkeepId = parsedUpkeepId
+ break
+ }
+ }
+ require.NotNil(t, upkeepId, "Upkeep ID should be found after registration")
+ l.Debug().
+ Str("TxHash", txHash.String()).
+ Str("Upkeep ID", upkeepId.String()).
+ Msg("Found upkeepId in tx hash")
+ upkeepIds = append(upkeepIds, upkeepId)
+ }
+ l.Info().Msg("Successfully registered all Automation Consumer Contracts")
+ l.Info().Interface("Upkeep IDs", upkeepIds).Msg("Upkeep IDs")
+ l.Info().Str("STARTUP_WAIT_TIME", StartupWaitTime.String()).Msg("Waiting for plugin to start")
+ time.Sleep(StartupWaitTime)
+
+ startBlock, err := chainClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+
+ p := wasp.NewProfile()
+
+ for i, triggerContract := range triggerContracts {
+ g, err := wasp.NewGenerator(&wasp.Config{
+ T: t,
+ LoadType: wasp.RPS,
+ GenName: fmt.Sprintf("log_trigger_gen_%s", triggerContract.Address().String()),
+ CallTimeout: time.Second * 10,
+ Schedule: wasp.Plain(
+ 1,
+ loadDuration,
+ ),
+ Gun: NewLogTriggerUser(
+ triggerContract,
+ consumerContracts[i],
+ l,
+ numberOfEvents,
+ ),
+ CallResultBufLen: 1000000,
+ })
+ p.Add(g, err)
+ }
+
+ l.Info().Msg("Starting load generators")
+ startTime := time.Now()
+ err = sendSlackNotification("Started", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes),
+ strconv.FormatInt(startTime.UnixMilli(), 10), "now",
+ []slack.Block{extraBlockWithText("\bTest Config\b\n```" + testConfig + "```")})
+ if err != nil {
+ l.Error().Err(err).Msg("Error sending slack notification")
+ }
+ _, err = p.Run(true)
+ require.NoError(t, err, "Error running load generators")
+
+ l.Info().Msg("Finished load generators")
+ l.Info().Str("STOP_WAIT_TIME", StopWaitTime.String()).Msg("Waiting for upkeeps to be performed")
+ time.Sleep(StopWaitTime)
+ l.Info().Msg("Finished waiting 60s for upkeeps to be performed")
+ endTime := time.Now()
+ testDuration := endTime.Sub(startTime)
+ l.Info().Str("Duration", testDuration.String()).Msg("Test Duration")
+ endBlock, err := chainClient.LatestBlockNumber(context.Background())
+ require.NoError(t, err, "Error getting latest block number")
+ l.Info().Uint64("Starting Block", startBlock).Uint64("Ending Block", endBlock).Msg("Test Block Range")
+
+ upkeepDelays := make([][]int64, 0)
+ var numberOfEventsEmitted int
+ var batchSize = 500
+
+ for _, gen := range p.Generators {
+ numberOfEventsEmitted += len(gen.GetData().OKData.Data)
+ }
+ numberOfEventsEmitted = numberOfEventsEmitted * numberOfEvents
+ l.Info().Int("Number of Events Emitted", numberOfEventsEmitted).Msg("Number of Events Emitted")
+
+ if endBlock-startBlock < uint64(batchSize) {
+ batchSize = int(endBlock - startBlock)
+ }
+
+ for cIter, consumerContract := range consumerContracts {
+ var (
+ logs []types.Log
+ address = common.HexToAddress(consumerContract.Address())
+ timeout = 5 * time.Second
+ )
+ for fromBlock := startBlock; fromBlock < endBlock; fromBlock += uint64(batchSize) + 1 {
+ var (
+ filterQuery = geth.FilterQuery{
+ Addresses: []common.Address{address},
+ FromBlock: big.NewInt(0).SetUint64(fromBlock),
+ ToBlock: big.NewInt(0).SetUint64(fromBlock + uint64(batchSize)),
+ Topics: [][]common.Hash{{consumerABI.Events["PerformingUpkeep"].ID}},
+ }
+ )
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ logsInBatch, err := chainClient.FilterLogs(ctx, filterQuery)
+ cancel()
+ if err != nil {
+ l.Error().Err(err).
+ Interface("FilterQuery", filterQuery).
+ Str("Contract Address", consumerContract.Address()).
+ Str("Timeout", timeout.String()).
+ Msg("Error getting logs")
+ }
+ logs = append(logs, logsInBatch...)
+ time.Sleep(time.Millisecond * 500)
+ }
+
+ if len(logs) > 0 {
+ delay := make([]int64, 0)
+ for _, log := range logs {
+ eventDetails, err := consumerABI.EventByID(log.Topics[0])
+ require.NoError(t, err, "Error getting event details")
+ consumer, err := simple_log_upkeep_counter_wrapper.NewSimpleLogUpkeepCounter(
+ address, chainClient.Backend(),
+ )
+ require.NoError(t, err, "Error getting consumer contract")
+ if eventDetails.Name == "PerformingUpkeep" {
+ parsedLog, err := consumer.ParsePerformingUpkeep(log)
+ require.NoError(t, err, "Error parsing log")
+ delay = append(delay, parsedLog.TimeToPerform.Int64())
+ }
+ }
+ upkeepDelays = append(upkeepDelays, delay)
+ }
+ if (cIter+1)%batchSize == 0 {
+ time.Sleep(time.Millisecond * 500)
+ }
+ }
+
+ l.Info().Interface("Upkeep Delays", upkeepDelays).Msg("Upkeep Delays")
+
+ var allUpkeepDelays []int64
+
+ for _, upkeepDelay := range upkeepDelays {
+ allUpkeepDelays = append(allUpkeepDelays, upkeepDelay...)
+ }
+
+ avg, median, ninetyPct, ninetyNinePct, maximum := testreporters.IntListStats(allUpkeepDelays)
+ l.Info().
+ Float64("Average", avg).Int64("Median", median).
+ Int64("90th Percentile", ninetyPct).Int64("99th Percentile", ninetyNinePct).
+ Int64("Max", maximum).Msg("Upkeep Delays in seconds")
+
+ l.Info().
+ Int("Total Perform Count", len(allUpkeepDelays)).
+ Int("Total Events Emitted", numberOfEventsEmitted).
+ Int("Total Events Missed", numberOfEventsEmitted-len(allUpkeepDelays)).
+ Msg("Test completed")
+
+ testReport := fmt.Sprintf("Upkeep Delays in seconds\nAverage: %f\nMedian: %d\n90th Percentile: %d\n"+
+ "99th Percentile: %d\nMax: %d\nTotal Perform Count: %d\n\nTotal Events Emitted: %d\nTotal Events Missed: %d\nTest Duration: %s\n",
+ avg, median, ninetyPct, ninetyNinePct, maximum, len(allUpkeepDelays), numberOfEventsEmitted,
+ numberOfEventsEmitted-len(allUpkeepDelays), testDuration.String())
+
+ err = sendSlackNotification("Finished", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes),
+ strconv.FormatInt(startTime.UnixMilli(), 10), strconv.FormatInt(endTime.UnixMilli(), 10),
+ []slack.Block{extraBlockWithText("\bTest Report\b\n```" + testReport + "```")})
+ if err != nil {
+ l.Error().Err(err).Msg("Error sending slack notification")
+ }
+
+ t.Cleanup(func() {
+ if err = actions.TeardownRemoteSuite(t, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, chainClient); err != nil {
+ l.Error().Err(err).Msg("Error when tearing down remote suite")
+ }
+ })
+
+}
diff --git a/integration-tests/load/automationv2_1/gun.go b/integration-tests/load/automationv2_1/gun.go
new file mode 100644
index 0000000000..a2863a6064
--- /dev/null
+++ b/integration-tests/load/automationv2_1/gun.go
@@ -0,0 +1,43 @@
+package automationv2_1
+
+import (
+ "github.com/rs/zerolog"
+ "github.com/smartcontractkit/wasp"
+
+ "github.com/smartcontractkit/chainlink/integration-tests/contracts"
+)
+
+type LogTriggerGun struct {
+ triggerContract contracts.LogEmitter
+ upkeepContract contracts.KeeperConsumer
+ logger zerolog.Logger
+ numberOfEvents int
+}
+
+func NewLogTriggerUser(
+ triggerContract contracts.LogEmitter,
+ upkeepContract contracts.KeeperConsumer,
+ logger zerolog.Logger,
+ numberOfEvents int,
+) *LogTriggerGun {
+ return &LogTriggerGun{
+ triggerContract: triggerContract,
+ upkeepContract: upkeepContract,
+ logger: logger,
+ numberOfEvents: numberOfEvents,
+ }
+}
+
+func (m *LogTriggerGun) Call(_ *wasp.Generator) *wasp.CallResult {
+ m.logger.Debug().Str("Trigger address", m.triggerContract.Address().String()).Msg("Triggering upkeep")
+ payload := make([]int, 0)
+ for i := 0; i < m.numberOfEvents; i++ {
+ payload = append(payload, 1)
+ }
+ _, err := m.triggerContract.EmitLogInts(payload)
+ if err != nil {
+ return &wasp.CallResult{Error: err.Error(), Failed: true}
+ }
+
+ return &wasp.CallResult{}
+}
diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go
new file mode 100644
index 0000000000..3c08199a9c
--- /dev/null
+++ b/integration-tests/load/automationv2_1/helpers.go
@@ -0,0 +1,71 @@
+package automationv2_1
+
+import (
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/rs/zerolog"
+ "github.com/slack-go/slack"
+
+ "github.com/smartcontractkit/chainlink-testing-framework/k8s/config"
+ reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters"
+ "github.com/smartcontractkit/chainlink/integration-tests/testreporters"
+)
+
+func getEnv(key, fallback string) string {
+ if inputs, ok := os.LookupEnv("TEST_INPUTS"); ok {
+ values := strings.Split(inputs, ",")
+ for _, value := range values {
+ if strings.Contains(value, key) {
+ return strings.Split(value, "=")[1]
+ }
+ }
+ }
+ return fallback
+}
+
+func extraBlockWithText(text string) slack.Block {
+ return slack.NewSectionBlock(slack.NewTextBlockObject(
+ "mrkdwn", text, false, false), nil, nil)
+}
+
+func sendSlackNotification(header string, l zerolog.Logger, namespace string, numberOfNodes,
+ startingTime string, endingTime string, extraBlocks []slack.Block) error {
+ slackClient := slack.New(reportModel.SlackAPIKey)
+
+ headerText := ":chainlink-keepers: Automation Load Test " + header + " :white_check_mark:"
+
+ formattedDashboardUrl := fmt.Sprintf("%s?orgId=1&from=%s&to=%s&var-namespace=%s&var-number_of_nodes=%s", testreporters.DashboardUrl, startingTime, endingTime, namespace, numberOfNodes)
+ l.Info().Str("Dashboard", formattedDashboardUrl).Msg("Dashboard URL")
+
+ pyroscopeServer := os.Getenv(config.EnvVarPyroscopeServer)
+ pyroscopeEnvironment := os.Getenv(config.EnvVarPyroscopeEnvironment)
+
+ formattedPyroscopeUrl := fmt.Sprintf("%s/?query=chainlink-node.cpu{Environment=\"%s\"}&from=%s&to=%s", pyroscopeServer, pyroscopeEnvironment, startingTime, endingTime)
+
+ var notificationBlocks []slack.Block
+
+ notificationBlocks = append(notificationBlocks,
+ slack.NewHeaderBlock(slack.NewTextBlockObject("plain_text", headerText, true, false)))
+ notificationBlocks = append(notificationBlocks,
+ slack.NewContextBlock("context_block", slack.NewTextBlockObject("plain_text", namespace, false, false)))
+ notificationBlocks = append(notificationBlocks, slack.NewDividerBlock())
+ if pyroscopeServer != "" {
+ l.Info().Str("Pyroscope", formattedPyroscopeUrl).Msg("Dashboard URL")
+ notificationBlocks = append(notificationBlocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn",
+ fmt.Sprintf("<%s|Pyroscope>",
+ formattedPyroscopeUrl), false, true), nil, nil))
+ }
+ notificationBlocks = append(notificationBlocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn",
+ fmt.Sprintf("<%s|Test Dashboard> \nNotifying <@%s>",
+ formattedDashboardUrl, reportModel.SlackUserID), false, true), nil, nil))
+
+ if len(extraBlocks) > 0 {
+ notificationBlocks = append(notificationBlocks, extraBlocks...)
+ }
+
+ ts, err := reportModel.SendSlackMessage(slackClient, slack.MsgOptionBlocks(notificationBlocks...))
+ l.Info().Str("ts", ts).Msg("Sent Slack Message")
+ return err
+}
diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go
index e9f2eaad7c..5db6cca3ec 100644
--- a/integration-tests/testreporters/keeper_benchmark.go
+++ b/integration-tests/testreporters/keeper_benchmark.go
@@ -133,7 +133,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error {
if err != nil {
return err
}
- avg, median, ninetyPct, ninetyNinePct, max := intListStats(allDelays)
+ avg, median, ninetyPct, ninetyNinePct, max := IntListStats(allDelays)
err = keeperReportWriter.Write([]string{
fmt.Sprint(totalEligibleCount),
fmt.Sprint(totalPerformed),
@@ -183,7 +183,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error {
}
for contractIndex, report := range k.Reports {
- avg, median, ninetyPct, ninetyNinePct, max = intListStats(report.AllCheckDelays)
+ avg, median, ninetyPct, ninetyNinePct, max = IntListStats(report.AllCheckDelays)
err = keeperReportWriter.Write([]string{
fmt.Sprint(contractIndex),
report.RegistryAddress,
@@ -307,7 +307,7 @@ func (k *KeeperBenchmarkTestReporter) SendSlackNotification(t *testing.T, slackC
// intListStats helper calculates some statistics on an int list: avg, median, 90pct, 99pct, max
//
//nolint:revive
-func intListStats(in []int64) (float64, int64, int64, int64, int64) {
+func IntListStats(in []int64) (float64, int64, int64, int64, int64) {
length := len(in)
if length == 0 {
return 0, 0, 0, 0, 0
From 3ed1689b9c50083770c550f9b5e072b7e283df58 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Fri, 17 Nov 2023 10:59:03 -0500
Subject: [PATCH 169/327] Fixes Live Test Blocker (#11322)
---
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 99dd990bec..aed5e0682c 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -23,7 +23,7 @@ require (
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd
- github.com/smartcontractkit/chainlink-testing-framework v1.19.0
+ github.com/smartcontractkit/chainlink-testing-framework v1.19.1
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 0402b12f3f..896ae8c6d2 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2375,8 +2375,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab0
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
-github.com/smartcontractkit/chainlink-testing-framework v1.19.0 h1:ungyY1gYcXCtmdX2yCon8pkx9HgPPLg4aNAhKNZFP5c=
-github.com/smartcontractkit/chainlink-testing-framework v1.19.0/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.19.1 h1:MdGM5jIrBi858Cv7qzfl1Qon93YW8InohAlDQqFoIb4=
+github.com/smartcontractkit/chainlink-testing-framework v1.19.1/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
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 738146e8d39eeaeef8e1479a7a2879b24cf7930d Mon Sep 17 00:00:00 2001
From: Bolek <1416262+bolekk@users.noreply.github.com>
Date: Fri, 17 Nov 2023 10:11:52 -0800
Subject: [PATCH 170/327] [Functions] Minor Listener refactor (#11323)
1. Add an interface type to make Listener mockable
2. Return internal errors from handleRequest()
---
core/services/functions/listener.go | 74 +++++++++++--------
core/services/functions/listener_test.go | 21 +++++-
.../functions/mocks/functions_listener.go | 71 ++++++++++++++++++
3 files changed, 134 insertions(+), 32 deletions(-)
create mode 100644 core/services/functions/mocks/functions_listener.go
diff --git a/core/services/functions/listener.go b/core/services/functions/listener.go
index 5614c5331d..efb40330cb 100644
--- a/core/services/functions/listener.go
+++ b/core/services/functions/listener.go
@@ -29,8 +29,6 @@ import (
)
var (
- _ job.ServiceCtx = &FunctionsListener{}
-
sizeBuckets = []float64{
1024,
1024 * 4,
@@ -118,7 +116,14 @@ const (
FlagSecretsMaxSize uint32 = 2
)
-type FunctionsListener struct {
+//go:generate mockery --quiet --name FunctionsListener --output ./mocks/ --case=underscore
+type FunctionsListener interface {
+ job.ServiceCtx
+
+ HandleOffchainRequest(ctx context.Context, request *OffchainRequest) error
+}
+
+type functionsListener struct {
services.StateMachine
client client.Client
contractAddressHex string
@@ -137,11 +142,13 @@ type FunctionsListener struct {
logPollerWrapper evmrelayTypes.LogPollerWrapper
}
-func (l *FunctionsListener) HealthReport() map[string]error {
+var _ FunctionsListener = &functionsListener{}
+
+func (l *functionsListener) HealthReport() map[string]error {
return map[string]error{l.Name(): l.Healthy()}
}
-func (l *FunctionsListener) Name() string { return l.logger.Name() }
+func (l *functionsListener) Name() string { return l.logger.Name() }
func formatRequestId(requestId [32]byte) string {
return fmt.Sprintf("0x%x", requestId)
@@ -159,8 +166,8 @@ func NewFunctionsListener(
urlsMonEndpoint commontypes.MonitoringEndpoint,
decryptor threshold.Decryptor,
logPollerWrapper evmrelayTypes.LogPollerWrapper,
-) *FunctionsListener {
- return &FunctionsListener{
+) *functionsListener {
+ return &functionsListener{
client: client,
contractAddressHex: contractAddressHex,
job: job,
@@ -177,7 +184,7 @@ func NewFunctionsListener(
}
// Start complies with job.Service
-func (l *FunctionsListener) Start(context.Context) error {
+func (l *functionsListener) Start(context.Context) error {
return l.StartOnce("FunctionsListener", func() error {
l.serviceContext, l.serviceCancel = context.WithCancel(context.Background())
@@ -204,7 +211,7 @@ func (l *FunctionsListener) Start(context.Context) error {
}
// Close complies with job.Service
-func (l *FunctionsListener) Close() error {
+func (l *functionsListener) Close() error {
return l.StopOnce("FunctionsListener", func() error {
l.serviceCancel()
close(l.chStop)
@@ -213,7 +220,7 @@ func (l *FunctionsListener) Close() error {
})
}
-func (l *FunctionsListener) processOracleEventsV1() {
+func (l *functionsListener) processOracleEventsV1() {
defer l.shutdownWaitGroup.Done()
freqMillis := l.pluginConfig.ListenerEventsCheckFrequencyMillis
if freqMillis == 0 {
@@ -247,7 +254,7 @@ func (l *FunctionsListener) processOracleEventsV1() {
}
}
-func (l *FunctionsListener) getNewHandlerContext() (context.Context, context.CancelFunc) {
+func (l *functionsListener) getNewHandlerContext() (context.Context, context.CancelFunc) {
timeoutSec := l.pluginConfig.ListenerEventHandlerTimeoutSec
if timeoutSec == 0 {
return context.WithCancel(l.serviceContext)
@@ -255,7 +262,7 @@ func (l *FunctionsListener) getNewHandlerContext() (context.Context, context.Can
return context.WithTimeout(l.serviceContext, time.Duration(timeoutSec)*time.Second)
}
-func (l *FunctionsListener) setError(ctx context.Context, requestId RequestID, errType ErrType, errBytes []byte) {
+func (l *functionsListener) setError(ctx context.Context, requestId RequestID, errType ErrType, errBytes []byte) {
if errType == INTERNAL_ERROR {
promRequestInternalError.WithLabelValues(l.contractAddressHex).Inc()
} else {
@@ -267,7 +274,7 @@ func (l *FunctionsListener) setError(ctx context.Context, requestId RequestID, e
}
}
-func (l *FunctionsListener) getMaxCBORsize(flags RequestFlags) uint32 {
+func (l *functionsListener) getMaxCBORsize(flags RequestFlags) uint32 {
idx := flags[FlagCBORMaxSize]
if int(idx) >= len(l.pluginConfig.MaxRequestSizesList) {
return l.pluginConfig.MaxRequestSizeBytes // deprecated
@@ -275,7 +282,7 @@ func (l *FunctionsListener) getMaxCBORsize(flags RequestFlags) uint32 {
return l.pluginConfig.MaxRequestSizesList[idx]
}
-func (l *FunctionsListener) getMaxSecretsSize(flags RequestFlags) uint32 {
+func (l *functionsListener) getMaxSecretsSize(flags RequestFlags) uint32 {
idx := flags[FlagSecretsMaxSize]
if int(idx) >= len(l.pluginConfig.MaxSecretsSizesList) {
return math.MaxUint32 // not enforced if not configured
@@ -283,7 +290,7 @@ func (l *FunctionsListener) getMaxSecretsSize(flags RequestFlags) uint32 {
return l.pluginConfig.MaxSecretsSizesList[idx]
}
-func (l *FunctionsListener) HandleOffchainRequest(ctx context.Context, request *OffchainRequest) error {
+func (l *functionsListener) HandleOffchainRequest(ctx context.Context, request *OffchainRequest) error {
if request == nil {
return errors.New("HandleOffchainRequest: received nil request")
}
@@ -318,11 +325,10 @@ func (l *FunctionsListener) HandleOffchainRequest(ctx context.Context, request *
}
return err
}
- l.handleRequest(ctx, requestId, request.SubscriptionId, subscriptionOwner, RequestFlags{}, &request.Data)
- return nil
+ return l.handleRequest(ctx, requestId, request.SubscriptionId, subscriptionOwner, RequestFlags{}, &request.Data)
}
-func (l *FunctionsListener) handleOracleRequestV1(request *evmrelayTypes.OracleRequest) {
+func (l *functionsListener) handleOracleRequestV1(request *evmrelayTypes.OracleRequest) {
defer l.shutdownWaitGroup.Done()
l.logger.Infow("handleOracleRequestV1: oracle request v1 received", "requestID", formatRequestId(request.RequestId))
ctx, cancel := l.getNewHandlerContext()
@@ -354,10 +360,13 @@ func (l *FunctionsListener) handleOracleRequestV1(request *evmrelayTypes.OracleR
l.setError(ctx, request.RequestId, USER_ERROR, []byte(err.Error()))
return
}
- l.handleRequest(ctx, request.RequestId, request.SubscriptionId, request.SubscriptionOwner, request.Flags, requestData)
+ err = l.handleRequest(ctx, request.RequestId, request.SubscriptionId, request.SubscriptionOwner, request.Flags, requestData)
+ if err != nil {
+ l.logger.Errorw("handleOracleRequestV1: error in handleRequest()", "requestID", formatRequestId(request.RequestId), "err", err)
+ }
}
-func (l *FunctionsListener) parseCBOR(requestId RequestID, cborData []byte, maxSizeBytes uint32) (*RequestData, error) {
+func (l *functionsListener) parseCBOR(requestId RequestID, cborData []byte, maxSizeBytes uint32) (*RequestData, error) {
if maxSizeBytes > 0 && uint32(len(cborData)) > maxSizeBytes {
l.logger.Errorw("request too big", "requestID", formatRequestId(requestId), "requestSize", len(cborData), "maxRequestSize", maxSizeBytes)
return nil, fmt.Errorf("request too big (max %d bytes)", maxSizeBytes)
@@ -372,7 +381,8 @@ func (l *FunctionsListener) parseCBOR(requestId RequestID, cborData []byte, maxS
return &requestData, nil
}
-func (l *FunctionsListener) handleRequest(ctx context.Context, requestID RequestID, subscriptionId uint64, subscriptionOwner common.Address, flags RequestFlags, requestData *RequestData) {
+// Handle secret fetching/decryption and functions computation. Return error only for internal errors.
+func (l *functionsListener) handleRequest(ctx context.Context, requestID RequestID, subscriptionId uint64, subscriptionOwner common.Address, flags RequestFlags, requestData *RequestData) error {
startTime := time.Now()
defer func() {
duration := time.Since(startTime)
@@ -385,26 +395,26 @@ func (l *FunctionsListener) handleRequest(ctx context.Context, requestID Request
if err != nil {
l.logger.Errorw("failed to create ExternalAdapterClient", "requestID", requestIDStr, "err", err)
l.setError(ctx, requestID, INTERNAL_ERROR, []byte(err.Error()))
- return
+ return err
}
nodeProvidedSecrets, userErr, internalErr := l.getSecrets(ctx, eaClient, requestID, subscriptionOwner, requestData)
if internalErr != nil {
l.logger.Errorw("internal error during getSecrets", "requestID", requestIDStr, "err", internalErr)
l.setError(ctx, requestID, INTERNAL_ERROR, []byte(internalErr.Error()))
- return
+ return internalErr
}
if userErr != nil {
l.logger.Debugw("user error during getSecrets", "requestID", requestIDStr, "err", userErr)
l.setError(ctx, requestID, USER_ERROR, []byte(userErr.Error()))
- return
+ return nil // user error
}
maxSecretsSize := l.getMaxSecretsSize(flags)
if uint32(len(nodeProvidedSecrets)) > maxSecretsSize {
l.logger.Errorw("secrets size too big", "requestID", requestIDStr, "secretsSize", len(nodeProvidedSecrets), "maxSecretsSize", maxSecretsSize)
l.setError(ctx, requestID, USER_ERROR, []byte("secrets size too big"))
- return
+ return nil // user error
}
computationResult, computationError, domains, err := eaClient.RunComputation(ctx, requestIDStr, l.job.Name.ValueOrZero(), subscriptionOwner.Hex(), subscriptionId, flags, nodeProvidedSecrets, requestData)
@@ -412,7 +422,7 @@ func (l *FunctionsListener) handleRequest(ctx context.Context, requestID Request
if err != nil {
l.logger.Errorw("internal adapter error", "requestID", requestIDStr, "err", err)
l.setError(ctx, requestID, INTERNAL_ERROR, []byte(err.Error()))
- return
+ return err
}
if len(computationError) == 0 && len(computationResult) == 0 {
@@ -438,11 +448,13 @@ func (l *FunctionsListener) handleRequest(ctx context.Context, requestID Request
l.logger.Debugw("saving computation result", "requestID", requestIDStr)
if err2 := l.pluginORM.SetResult(requestID, computationResult, time.Now(), pg.WithParentCtx(ctx)); err2 != nil {
l.logger.Errorw("call to SetResult failed", "requestID", requestIDStr, "err", err2)
+ return err2
}
}
+ return nil
}
-func (l *FunctionsListener) handleOracleResponseV1(response *evmrelayTypes.OracleResponse) {
+func (l *functionsListener) handleOracleResponseV1(response *evmrelayTypes.OracleResponse) {
defer l.shutdownWaitGroup.Done()
l.logger.Infow("oracle response v1 received", "requestID", formatRequestId(response.RequestId))
@@ -454,7 +466,7 @@ func (l *FunctionsListener) handleOracleResponseV1(response *evmrelayTypes.Oracl
promRequestConfirmed.WithLabelValues(l.contractAddressHex).Inc()
}
-func (l *FunctionsListener) timeoutRequests() {
+func (l *functionsListener) timeoutRequests() {
defer l.shutdownWaitGroup.Done()
timeoutSec, freqSec, batchSize := l.pluginConfig.RequestTimeoutSec, l.pluginConfig.RequestTimeoutCheckFrequencySec, l.pluginConfig.RequestTimeoutBatchLookupSize
if timeoutSec == 0 || freqSec == 0 || batchSize == 0 {
@@ -490,7 +502,7 @@ func (l *FunctionsListener) timeoutRequests() {
}
}
-func (l *FunctionsListener) pruneRequests() {
+func (l *functionsListener) pruneRequests() {
defer l.shutdownWaitGroup.Done()
maxStoredRequests, freqSec, batchSize := l.pluginConfig.PruneMaxStoredRequests, l.pluginConfig.PruneCheckFrequencySec, l.pluginConfig.PruneBatchSize
if maxStoredRequests == 0 {
@@ -532,7 +544,7 @@ func (l *FunctionsListener) pruneRequests() {
}
}
-func (l *FunctionsListener) reportSourceCodeDomains(requestId RequestID, domains []string) {
+func (l *functionsListener) reportSourceCodeDomains(requestId RequestID, domains []string) {
r := &telem.FunctionsRequest{
RequestId: formatRequestId(requestId),
NodeAddress: l.job.OCR2OracleSpec.TransmitterID.ValueOrZero(),
@@ -547,7 +559,7 @@ func (l *FunctionsListener) reportSourceCodeDomains(requestId RequestID, domains
}
}
-func (l *FunctionsListener) getSecrets(ctx context.Context, eaClient ExternalAdapterClient, requestID RequestID, subscriptionOwner common.Address, requestData *RequestData) (decryptedSecrets string, userError, internalError error) {
+func (l *functionsListener) getSecrets(ctx context.Context, eaClient ExternalAdapterClient, requestID RequestID, subscriptionOwner common.Address, requestData *RequestData) (decryptedSecrets string, userError, internalError error) {
if l.decryptor == nil {
l.logger.Warn("Decryptor not configured")
return "", nil, nil
diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go
index ac2bc64184..ecad9e4cce 100644
--- a/core/services/functions/listener_test.go
+++ b/core/services/functions/listener_test.go
@@ -46,7 +46,7 @@ import (
)
type FunctionsListenerUniverse struct {
- service *functions_service.FunctionsListener
+ service functions_service.FunctionsListener
bridgeAccessor *functions_mocks.BridgeAccessor
eaClient *functions_mocks.ExternalAdapterClient
pluginORM *functions_mocks.ORM
@@ -219,6 +219,25 @@ func TestFunctionsListener_HandleOffchainRequest_Invalid(t *testing.T) {
require.Error(t, uni.service.HandleOffchainRequest(testutils.Context(t), request))
}
+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.bridgeAccessor.On("NewExternalAdapterClient").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", RequestID, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
+
+ request := &functions_service.OffchainRequest{
+ RequestId: RequestID[:],
+ RequestInitiator: SubscriptionOwner.Bytes(),
+ SubscriptionId: uint64(SubscriptionID),
+ SubscriptionOwner: SubscriptionOwner.Bytes(),
+ Data: functions_service.RequestData{},
+ }
+ require.Error(t, uni.service.HandleOffchainRequest(testutils.Context(t), request))
+}
+
func TestFunctionsListener_HandleOracleRequestV1_ComputationError(t *testing.T) {
testutils.SkipShortDB(t)
t.Parallel()
diff --git a/core/services/functions/mocks/functions_listener.go b/core/services/functions/mocks/functions_listener.go
new file mode 100644
index 0000000000..d2aeb2ddab
--- /dev/null
+++ b/core/services/functions/mocks/functions_listener.go
@@ -0,0 +1,71 @@
+// Code generated by mockery v2.35.4. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ functions "github.com/smartcontractkit/chainlink/v2/core/services/functions"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// FunctionsListener is an autogenerated mock type for the FunctionsListener type
+type FunctionsListener struct {
+ mock.Mock
+}
+
+// Close provides a mock function with given fields:
+func (_m *FunctionsListener) Close() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// HandleOffchainRequest provides a mock function with given fields: ctx, request
+func (_m *FunctionsListener) HandleOffchainRequest(ctx context.Context, request *functions.OffchainRequest) error {
+ ret := _m.Called(ctx, request)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *functions.OffchainRequest) error); ok {
+ r0 = rf(ctx, request)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Start provides a mock function with given fields: _a0
+func (_m *FunctionsListener) Start(_a0 context.Context) error {
+ ret := _m.Called(_a0)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+ r0 = rf(_a0)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// NewFunctionsListener creates a new instance of FunctionsListener. 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 NewFunctionsListener(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *FunctionsListener {
+ mock := &FunctionsListener{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
From 5f09e55075e98e8863fe686f41682d4feca268b5 Mon Sep 17 00:00:00 2001
From: Tate
Date: Fri, 17 Nov 2023 12:10:28 -0700
Subject: [PATCH 171/327] [TT-707] Build Test Base Image As Needed in CI
(#11329)
---
.github/actions/build-test-image/action.yml | 62 +++++++++++++++++--
.../workflows/integration-tests-publish.yml | 20 ++----
2 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml
index 4b1dce6ee1..e6c759109b 100644
--- a/.github/actions/build-test-image/action.yml
+++ b/.github/actions/build-test-image/action.yml
@@ -17,9 +17,6 @@ inputs:
description: The test suites to build into the image
default: chaos migration performance reorg smoke soak benchmark load/automationv2_1
required: false
- base_image_tag:
- description: The test base image version to use, if not provided it will use the version from the ./integration-tests/go.mod file
- required: false
QA_AWS_ROLE_TO_ASSUME:
description: The AWS role to assume as the CD user, if any. Used in configuring the docker/login-action
required: true
@@ -33,14 +30,66 @@ inputs:
runs:
using: composite
steps:
+
+ # Base Test Image Logic
- name: Get CTF Version
- if: ${{ inputs.base_image_tag == '' }}
id: version
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
go-project-path: ./integration-tests
module-name: github.com/smartcontractkit/chainlink-testing-framework
- enforce-semantic-tag: "true" # it has to be in the form of v1.2.3 or the image won't exist
+ enforce-semantic-tag: false
+ - name: Get CTF sha
+ if: steps.version.outputs.is_semantic == 'false'
+ id: short_sha
+ env:
+ VERSION: ${{ steps.version.outputs.version }}
+ shell: bash
+ run: |
+ short_sha="${VERSION##*-}"
+ echo "short sha is: ${short_sha}"
+ echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT"
+ - name: Checkout chainlink-testing-framework
+ if: steps.version.outputs.is_semantic == 'false'
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ repository: smartcontractkit/chainlink-testing-framework
+ ref: main
+ fetch-depth: 0
+ path: ctf
+ - name: Get long sha
+ if: steps.version.outputs.is_semantic == 'false'
+ id: long_sha
+ env:
+ SHORT_SHA: ${{ steps.short_sha.outputs.short_sha }}
+ shell: bash
+ run: |
+ cd ctf
+ long_sha=$(git rev-parse ${SHORT_SHA})
+ echo "sha is: ${long_sha}"
+ echo "long_sha=${long_sha}" >> "$GITHUB_OUTPUT"
+ - name: Check if test base image exists
+ if: steps.version.outputs.is_semantic == 'false'
+ id: check-base-image
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12
+ with:
+ repository: ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image
+ tag: ${{ steps.long_sha.outputs.long_sha }}
+ AWS_REGION: ${{ inputs.QA_AWS_REGION }}
+ AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
+ - name: Build Base Image
+ if: steps.version.outputs.is_semantic == 'false' && steps.check-base-image.outputs.exists == 'false'
+ uses: smartcontractkit/chainlink-github-actions/docker/build-push@ce87f8986ca18336cc5015df75916c2ec0a7c4b3 # v2.1.2
+ env:
+ BASE_IMAGE_NAME: ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image:${{ steps.long_sha.outputs.long_sha }}
+ with:
+ tags: ${{ env.BASE_IMAGE_NAME }}
+ file: ctf/k8s/Dockerfile.base
+ AWS_REGION: ${{ inputs.QA_AWS_REGION }}
+ AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
+ # End Base Image Logic
+
+ # Test Runner Logic
- name: Check if image exists
id: check-image
uses: smartcontractkit/chainlink-github-actions/docker/image-exists@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12
@@ -59,7 +108,7 @@ runs:
file: ./integration-tests/test.Dockerfile
build-args: |
BASE_IMAGE=${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image
- IMAGE_VERSION=${{ inputs.base_image_tag || steps.version.outputs.version }}
+ IMAGE_VERSION=${{ steps.long_sha.outputs.long_sha || steps.version.outputs.version }}
SUITES="${{ inputs.suites }}"
AWS_REGION: ${{ inputs.QA_AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
@@ -71,3 +120,4 @@ runs:
run: |
echo "### ${INPUTS_REPOSITORY} image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY
echo "\`${INPUTS_TAG}\`" >>$GITHUB_STEP_SUMMARY
+ # End Test Runner Logic
diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml
index 9eb2673db2..176947a092 100644
--- a/.github/workflows/integration-tests-publish.yml
+++ b/.github/workflows/integration-tests-publish.yml
@@ -6,13 +6,6 @@ on:
branches:
- develop
workflow_dispatch:
- inputs:
- ctf-base-image-tag:
- description: |
- 'The tag of the CTF base image to be used,
- typically something like v1.18.6 from https://github.com/smartcontractkit/chainlink-testing-framework/releases
- or a custom tag or branch you have pushed.'
- required: true
env:
ECR_TAG: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:develop
@@ -39,20 +32,15 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- - name: Setup Other Tags
+ - name: Setup Other Tags If Not Workflow Dispatch
id: tags
- env:
- BASE_IMAGE_TAG: ${{ inputs.ctf-base-image-tag}}
+ if: github.event_name != 'workflow_dispatch'
run: |
- if [ -z "${BASE_IMAGE_TAG+x}" ]; then
- echo "ctf-base-image-tag is not set, we are part of a merge and want to push the develop tag"
- echo "other_tags=${ECR_TAG}" >> $GITHUB_OUTPUT
- fi
+ echo "other_tags=${ECR_TAG}" >> $GITHUB_OUTPUT
- name: Build Image
uses: ./.github/actions/build-test-image
with:
other_tags: ${{ steps.tags.outputs.other_tags }}
- base_image_tag: ${{ inputs.ctf-base-image-tag }}
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 }}
@@ -68,7 +56,7 @@ jobs:
build-chainlink-image:
environment: integration
# Only run this build for workflow_dispatch
- if: ${{ inputs.ctf-base-image-tag != '' }}
+ if: github.event_name == 'workflow_dispatch'
permissions:
id-token: write
contents: read
From b2c1a17cf529317d70674aa9f73596a4a426f418 Mon Sep 17 00:00:00 2001
From: JonWong203 <82334955+JonWong203@users.noreply.github.com>
Date: Fri, 17 Nov 2023 14:19:54 -0500
Subject: [PATCH 172/327] Automation Telemetry: Send BlockNumber and Node
Version (#9927)
* rebase on toml feature flag
* fixes + send node version
rebase on feature flag PR
* fixes
* comments
* minor changes
* lint
* constant added
* logger
* toggle by feature flag
* minor fixes
* marshal error exits start()
* marshal error fix
* add automation custom telem to job
* rename toml tag
* test
* removed print statement
* merge
* configDigest go routine getter
* configDigest var
* refactor1
* send NodeVersion msg every new ConfigDigest
* lint
* refactor
* move registry creation outside delegate.go
* plugin config bool flag
* custom telem for 2.1
* block subscriber + thread controller
* ContractConfigTracker
* reset forge-std
* use toml config flag
* set toml flag default to true
* plugin config bool flag
* make generate
* refactor
* hourly node version msg
* fix tests
* lint fix
* goimports fixed
* goimport fix 2
---------
Co-authored-by: FelixFan1992
---
core/config/docs/core.toml | 2 +-
core/services/chainlink/config_ocr2_test.go | 2 +-
core/services/chainlink/config_test.go | 4 +-
.../testdata/config-empty-effective.toml | 2 +-
.../chainlink/testdata/config-full.toml | 2 +-
.../config-multi-chain-effective.toml | 2 +-
core/services/ocr2/delegate.go | 23 ++-
.../ocr2/plugins/ocr2keeper/config.go | 2 +
.../plugins/ocr2keeper/custom_telemetry.go | 156 +++++++++++++++++
.../ocr2keeper/custom_telemetry_test.go | 17 ++
.../evm21/autotelemetry21/custom_telemetry.go | 160 ++++++++++++++++++
.../autotelemetry21/custom_telemetry_test.go | 56 ++++++
.../testdata/config-empty-effective.toml | 2 +-
core/web/resolver/testdata/config-full.toml | 2 +-
.../config-multi-chain-effective.toml | 2 +-
docs/CONFIG.md | 4 +-
testdata/scripts/node/validate/default.txtar | 2 +-
.../disk-based-logging-disabled.txtar | 2 +-
.../validate/disk-based-logging-no-dir.txtar | 2 +-
.../node/validate/disk-based-logging.txtar | 2 +-
testdata/scripts/node/validate/invalid.txtar | 2 +-
testdata/scripts/node/validate/valid.txtar | 2 +-
testdata/scripts/node/validate/warnings.txtar | 2 +-
23 files changed, 431 insertions(+), 21 deletions(-)
create mode 100644 core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/custom_telemetry_test.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
create mode 100644 core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry_test.go
diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml
index 0a8e6aba3b..148de90cd9 100644
--- a/core/config/docs/core.toml
+++ b/core/config/docs/core.toml
@@ -352,7 +352,7 @@ KeyBundleID = '7a5f66bbe6594259325bf2b4f5b1a9c900000000000000000000000000000000'
# CaptureEATelemetry toggles collecting extra information from External Adaptares
CaptureEATelemetry = false # Default
# CaptureAutomationCustomTelemetry toggles collecting automation specific telemetry
-CaptureAutomationCustomTelemetry = false # Default
+CaptureAutomationCustomTelemetry = true # Default
# DefaultTransactionQueueDepth controls the queue size for `DropOldestStrategy` in OCR2. Set to 0 to use `SendEvery` strategy instead.
DefaultTransactionQueueDepth = 1 # Default
# SimulateTransactions enables transaction simulation for OCR2.
diff --git a/core/services/chainlink/config_ocr2_test.go b/core/services/chainlink/config_ocr2_test.go
index 6642748924..5bf84934d1 100644
--- a/core/services/chainlink/config_ocr2_test.go
+++ b/core/services/chainlink/config_ocr2_test.go
@@ -38,7 +38,7 @@ func TestOCR2Config(t *testing.T) {
require.Equal(t, false, ocr2Cfg.TraceLogging())
require.Equal(t, uint32(1), ocr2Cfg.DefaultTransactionQueueDepth())
require.Equal(t, false, ocr2Cfg.CaptureEATelemetry())
- require.Equal(t, false, ocr2Cfg.CaptureAutomationCustomTelemetry())
+ require.Equal(t, true, ocr2Cfg.CaptureAutomationCustomTelemetry())
keyBundleID, err := ocr2Cfg.KeyBundleID()
require.NoError(t, err)
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index 0caae3607f..fbadb379ca 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -385,7 +385,7 @@ func TestConfig_Marshal(t *testing.T) {
DatabaseTimeout: models.MustNewDuration(8 * time.Second),
KeyBundleID: ptr(models.MustSha256HashFromHex("7a5f66bbe6594259325bf2b4f5b1a9c9")),
CaptureEATelemetry: ptr(false),
- CaptureAutomationCustomTelemetry: ptr(false),
+ CaptureAutomationCustomTelemetry: ptr(true),
DefaultTransactionQueueDepth: ptr[uint32](1),
SimulateTransactions: ptr(false),
TraceLogging: ptr(false),
@@ -848,7 +848,7 @@ ContractTransmitterTransmitTimeout = '1m0s'
DatabaseTimeout = '8s'
KeyBundleID = '7a5f66bbe6594259325bf2b4f5b1a9c900000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml
index f5d775fe74..b897fba7f1 100644
--- a/core/services/chainlink/testdata/config-empty-effective.toml
+++ b/core/services/chainlink/testdata/config-empty-effective.toml
@@ -137,7 +137,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml
index 5ede10ef69..531c98d734 100644
--- a/core/services/chainlink/testdata/config-full.toml
+++ b/core/services/chainlink/testdata/config-full.toml
@@ -143,7 +143,7 @@ ContractTransmitterTransmitTimeout = '1m0s'
DatabaseTimeout = '8s'
KeyBundleID = '7a5f66bbe6594259325bf2b4f5b1a9c900000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml
index 9dd0be8f5d..c743601ced 100644
--- a/core/services/chainlink/testdata/config-multi-chain-effective.toml
+++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml
@@ -137,7 +137,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '20s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 20c1351297..944c04c8d4 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -49,6 +49,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21"
ocr2keeper21core "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
ocr2vrfconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/config"
ocr2coordinator "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/coordinator"
@@ -174,6 +175,7 @@ type ocr2Config interface {
DatabaseTimeout() time.Duration
KeyBundleID() (string, error)
TraceLogging() bool
+ CaptureAutomationCustomTelemetry() bool
}
type insecureConfig interface {
@@ -1161,7 +1163,7 @@ func (d *Delegate) newServicesOCR2Keepers21(
d.cfg.JobPipeline().MaxSuccessfulRuns(),
)
- return []job.ServiceCtx{
+ automationServices := []job.ServiceCtx{
runResultSaver,
keeperProvider,
services.Registry(),
@@ -1171,7 +1173,24 @@ func (d *Delegate) newServicesOCR2Keepers21(
services.UpkeepStateStore(),
services.TransmitEventProvider(),
pluginService,
- }, nil
+ }
+
+ if cfg.CaptureAutomationCustomTelemetry != nil && *cfg.CaptureAutomationCustomTelemetry ||
+ cfg.CaptureAutomationCustomTelemetry == nil && d.cfg.OCR2().CaptureAutomationCustomTelemetry() {
+ endpoint := d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.AutomationCustom)
+ customTelemService, custErr := autotelemetry21.NewAutomationCustomTelemetryService(
+ endpoint,
+ lggr,
+ services.BlockSubscriber(),
+ keeperProvider.ContractConfigTracker(),
+ )
+ if custErr != nil {
+ return nil, errors.Wrap(custErr, "Error when creating AutomationCustomTelemetryService")
+ }
+ automationServices = append(automationServices, customTelemService)
+ }
+
+ return automationServices, nil
}
func (d *Delegate) newServicesOCR2Keepers20(
diff --git a/core/services/ocr2/plugins/ocr2keeper/config.go b/core/services/ocr2/plugins/ocr2keeper/config.go
index d3035878ec..ec56f9c699 100644
--- a/core/services/ocr2/plugins/ocr2keeper/config.go
+++ b/core/services/ocr2/plugins/ocr2keeper/config.go
@@ -58,6 +58,8 @@ type PluginConfig struct {
ServiceQueueLength int `json:"serviceQueueLength"`
// ContractVersion is the contract version
ContractVersion string `json:"contractVersion"`
+ // CaptureAutomationCustomTelemetry is a bool flag to toggle Custom Telemetry Service
+ CaptureAutomationCustomTelemetry *bool `json:"captureAutomationCustomTelemetry,omitempty"`
}
func ValidatePluginConfig(cfg PluginConfig) error {
diff --git a/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
new file mode 100644
index 0000000000..0f03ae5bd0
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
@@ -0,0 +1,156 @@
+package ocr2keeper
+
+import (
+ "context"
+ "encoding/hex"
+ "time"
+
+ "github.com/smartcontractkit/libocr/commontypes"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "google.golang.org/protobuf/proto"
+
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
+ "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
+ "github.com/smartcontractkit/chainlink/v2/core/static"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type AutomationCustomTelemetryService struct {
+ utils.StartStopOnce
+ monitoringEndpoint commontypes.MonitoringEndpoint
+ blockSubscriber *evm21.BlockSubscriber
+ blockSubChanID int
+ threadCtrl utils.ThreadControl
+ lggr logger.Logger
+ configDigest [32]byte
+ contractConfigTracker types.ContractConfigTracker
+}
+
+// NewAutomationCustomTelemetryService creates a telemetry service for new blocks and node version
+func NewAutomationCustomTelemetryService(me commontypes.MonitoringEndpoint,
+ lggr logger.Logger, blocksub *evm21.BlockSubscriber, configTracker types.ContractConfigTracker) (*AutomationCustomTelemetryService, error) {
+ return &AutomationCustomTelemetryService{
+ monitoringEndpoint: me,
+ threadCtrl: utils.NewThreadControl(),
+ lggr: lggr.Named("AutomationCustomTelem"),
+ contractConfigTracker: configTracker,
+ blockSubscriber: blocksub,
+ }, nil
+}
+
+// Start starts Custom Telemetry Service, sends 1 NodeVersion message to endpoint at start and sends new BlockNumber messages
+func (e *AutomationCustomTelemetryService) Start(ctx context.Context) error {
+ return e.StartOnce("AutomationCustomTelemetryService", func() error {
+ e.lggr.Infof("Starting: Custom Telemetry Service")
+ _, configDetails, err := e.contractConfigTracker.LatestConfigDetails(ctx)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while getting newestConfigDetails for initialization %s", err)
+ } else {
+ e.configDigest = configDetails
+ e.sendNodeVersionMsg()
+ }
+ e.threadCtrl.Go(func(ctx context.Context) {
+ ticker := time.NewTicker(1 * time.Minute)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ticker.C:
+ _, newConfigDigest, err := e.contractConfigTracker.LatestConfigDetails(ctx)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while getting newestConfigDetails in configDigest loop %s", err)
+ }
+ if newConfigDigest != e.configDigest {
+ e.configDigest = newConfigDigest
+ e.sendNodeVersionMsg()
+ }
+ case <-ctx.Done():
+ return
+ }
+ }
+ })
+
+ chanID, blockSubscriberChan, blockSubErr := e.blockSubscriber.Subscribe()
+ if blockSubErr != nil {
+ e.lggr.Errorf("Block Subscriber Error: Subscribe(): %s", blockSubErr)
+
+ } else {
+ e.blockSubChanID = chanID
+ e.threadCtrl.Go(func(ctx context.Context) {
+ e.lggr.Infof("Started: Sending BlockNumber Messages")
+ for {
+ select {
+ case blockHistory := <-blockSubscriberChan:
+ latestBlockKey, err := blockHistory.Latest()
+ if err != nil {
+ e.lggr.Errorf("BlockSubscriber BlockHistory.Latest() failed: %s", err)
+ continue
+ }
+ e.sendBlockNumberMsg(latestBlockKey)
+ case <-ctx.Done():
+ return
+ }
+ }
+ })
+ }
+ return nil
+ })
+}
+
+// Close stops go routines and closes channels
+func (e *AutomationCustomTelemetryService) Close() error {
+ // use utils
+ return e.StopOnce("AutomationCustomTelemetryService", func() error {
+ e.lggr.Infof("Stopping: custom telemetry service")
+ e.threadCtrl.Close()
+ err := e.blockSubscriber.Unsubscribe(e.blockSubChanID)
+ if err != nil {
+ return err
+ }
+ e.lggr.Infof("Stopped: Custom telemetry service")
+ return nil
+ })
+}
+
+func (e *AutomationCustomTelemetryService) sendNodeVersionMsg() {
+ vMsg := &telem.NodeVersion{
+ Timestamp: uint64(time.Now().UTC().UnixMilli()),
+ NodeVersion: static.Version,
+ ConfigDigest: e.configDigest[:],
+ }
+ wrappedVMsg := &telem.AutomationTelemWrapper{
+ Msg: &telem.AutomationTelemWrapper_NodeVersion{
+ NodeVersion: vMsg,
+ },
+ }
+ bytes, err := proto.Marshal(wrappedVMsg)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while marshalling the Node Version Message %s: %v", wrappedVMsg.String(), err)
+ } else {
+ e.monitoringEndpoint.SendLog(bytes)
+ e.lggr.Infof("NodeVersion Message Sent to Endpoint: %d", vMsg.Timestamp)
+ }
+}
+
+func (e *AutomationCustomTelemetryService) sendBlockNumberMsg(blockKey ocr2keepers.BlockKey) {
+ blockNumMsg := &telem.BlockNumber{
+ Timestamp: uint64(time.Now().UTC().UnixMilli()),
+ BlockNumber: uint64(blockKey.Number),
+ BlockHash: hex.EncodeToString(blockKey.Hash[:]),
+ ConfigDigest: e.configDigest[:],
+ }
+ wrappedBlockNumMsg := &telem.AutomationTelemWrapper{
+ Msg: &telem.AutomationTelemWrapper_BlockNumber{
+ BlockNumber: blockNumMsg,
+ },
+ }
+ b, err := proto.Marshal(wrappedBlockNumMsg)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while marshalling the Block Num Message %s: %v", wrappedBlockNumMsg.String(), err)
+ } else {
+ e.monitoringEndpoint.SendLog(b)
+ e.lggr.Infof("BlockNumber Message Sent to Endpoint: %d", blockNumMsg.Timestamp)
+ }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/custom_telemetry_test.go b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry_test.go
new file mode 100644
index 0000000000..a40a3f3525
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry_test.go
@@ -0,0 +1,17 @@
+package ocr2keeper
+
+import (
+ "testing"
+)
+
+func TestNewAutomationCustomTelemetryService(t *testing.T) {
+ // me := &MockMonitoringEndpoint{}
+ // lggr := &MockLogger{}
+ // blocksub := &MockBlockSubscriber{}
+ // configTracker := &MockContractConfigTracker{}
+
+ // service, err := NewAutomationCustomTelemetryService(me, lggr, blocksub, configTracker)
+ // if err != nil {
+ // t.Errorf("Expected no error, but got: %v", err)
+ // }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
new file mode 100644
index 0000000000..93f35ce0d2
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
@@ -0,0 +1,160 @@
+package autotelemetry21
+
+import (
+ "context"
+ "encoding/hex"
+ "time"
+
+ "github.com/smartcontractkit/libocr/commontypes"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "google.golang.org/protobuf/proto"
+
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
+ "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
+ "github.com/smartcontractkit/chainlink/v2/core/static"
+ "github.com/smartcontractkit/chainlink/v2/core/utils"
+)
+
+type AutomationCustomTelemetryService struct {
+ utils.StartStopOnce
+ monitoringEndpoint commontypes.MonitoringEndpoint
+ blockSubscriber *evm21.BlockSubscriber
+ blockSubChanID int
+ threadCtrl utils.ThreadControl
+ lggr logger.Logger
+ configDigest [32]byte
+ contractConfigTracker types.ContractConfigTracker
+}
+
+// NewAutomationCustomTelemetryService creates a telemetry service for new blocks and node version
+func NewAutomationCustomTelemetryService(me commontypes.MonitoringEndpoint,
+ lggr logger.Logger, blocksub *evm21.BlockSubscriber, configTracker types.ContractConfigTracker) (*AutomationCustomTelemetryService, error) {
+ return &AutomationCustomTelemetryService{
+ monitoringEndpoint: me,
+ threadCtrl: utils.NewThreadControl(),
+ lggr: lggr.Named("AutomationCustomTelem"),
+ contractConfigTracker: configTracker,
+ blockSubscriber: blocksub,
+ }, nil
+}
+
+// Start starts Custom Telemetry Service, sends 1 NodeVersion message to endpoint at start and sends new BlockNumber messages
+func (e *AutomationCustomTelemetryService) Start(ctx context.Context) error {
+ return e.StartOnce("AutomationCustomTelemetryService", func() error {
+ e.lggr.Infof("Starting: Custom Telemetry Service")
+ _, configDetails, err := e.contractConfigTracker.LatestConfigDetails(ctx)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while getting newestConfigDetails for initialization %s", err)
+ } else {
+ e.configDigest = configDetails
+ e.sendNodeVersionMsg()
+ }
+ e.threadCtrl.Go(func(ctx context.Context) {
+ minuteTicker := time.NewTicker(1 * time.Minute)
+ hourTicker := time.NewTicker(1 * time.Hour)
+ defer minuteTicker.Stop()
+ defer hourTicker.Stop()
+ for {
+ select {
+ case <-minuteTicker.C:
+ _, newConfigDigest, err := e.contractConfigTracker.LatestConfigDetails(ctx)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while getting newestConfigDetails in configDigest loop %s", err)
+ }
+ if newConfigDigest != e.configDigest {
+ e.configDigest = newConfigDigest
+ e.sendNodeVersionMsg()
+ }
+ case <-hourTicker.C:
+ e.sendNodeVersionMsg()
+ case <-ctx.Done():
+ return
+ }
+ }
+ })
+
+ chanID, blockSubscriberChan, blockSubErr := e.blockSubscriber.Subscribe()
+ if blockSubErr != nil {
+ e.lggr.Errorf("Block Subscriber Error: Subscribe(): %s", blockSubErr)
+ return blockSubErr
+ }
+ e.blockSubChanID = chanID
+ e.threadCtrl.Go(func(ctx context.Context) {
+ e.lggr.Debug("Started: Sending BlockNumber Messages")
+ for {
+ select {
+ case blockHistory := <-blockSubscriberChan:
+ // Exploratory: Debounce blocks to avoid overflow in case of re-org
+ latestBlockKey, err := blockHistory.Latest()
+ if err != nil {
+ e.lggr.Errorf("BlockSubscriber BlockHistory.Latest() failed: %s", err)
+ continue
+ }
+ e.sendBlockNumberMsg(latestBlockKey)
+ case <-ctx.Done():
+ return
+ }
+ }
+ })
+ return nil
+ })
+}
+
+// Close stops go routines and closes channels
+func (e *AutomationCustomTelemetryService) Close() error {
+ return e.StopOnce("AutomationCustomTelemetryService", func() error {
+ e.lggr.Debug("Stopping: custom telemetry service")
+ e.threadCtrl.Close()
+ err := e.blockSubscriber.Unsubscribe(e.blockSubChanID)
+ if err != nil {
+ e.lggr.Errorf("Custom telemetry service encounters error %v when stopping", err)
+ return err
+ }
+ e.lggr.Infof("Stopped: Custom telemetry service")
+ return nil
+ })
+}
+
+func (e *AutomationCustomTelemetryService) sendNodeVersionMsg() {
+ vMsg := &telem.NodeVersion{
+ Timestamp: uint64(time.Now().UTC().UnixMilli()),
+ NodeVersion: static.Version,
+ ConfigDigest: e.configDigest[:],
+ }
+ wrappedVMsg := &telem.AutomationTelemWrapper{
+ Msg: &telem.AutomationTelemWrapper_NodeVersion{
+ NodeVersion: vMsg,
+ },
+ }
+ bytes, err := proto.Marshal(wrappedVMsg)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while marshalling the Node Version Message %s: %v", wrappedVMsg.String(), err)
+ } else {
+ e.monitoringEndpoint.SendLog(bytes)
+ e.lggr.Debugf("NodeVersion Message Sent to Endpoint: %d", vMsg.Timestamp)
+ }
+}
+
+func (e *AutomationCustomTelemetryService) sendBlockNumberMsg(blockKey ocr2keepers.BlockKey) {
+ blockNumMsg := &telem.BlockNumber{
+ Timestamp: uint64(time.Now().UTC().UnixMilli()),
+ BlockNumber: uint64(blockKey.Number),
+ BlockHash: hex.EncodeToString(blockKey.Hash[:]),
+ ConfigDigest: e.configDigest[:],
+ }
+ wrappedBlockNumMsg := &telem.AutomationTelemWrapper{
+ Msg: &telem.AutomationTelemWrapper_BlockNumber{
+ BlockNumber: blockNumMsg,
+ },
+ }
+ b, err := proto.Marshal(wrappedBlockNumMsg)
+ if err != nil {
+ e.lggr.Errorf("Error occurred while marshalling the Block Num Message %s: %v", wrappedBlockNumMsg.String(), err)
+ } else {
+ e.monitoringEndpoint.SendLog(b)
+ e.lggr.Debugf("BlockNumber Message Sent to Endpoint: %d", blockNumMsg.Timestamp)
+ }
+}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry_test.go
new file mode 100644
index 0000000000..4318d9aac6
--- /dev/null
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry_test.go
@@ -0,0 +1,56 @@
+package autotelemetry21
+
+import (
+ "sync"
+ "testing"
+
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/stretchr/testify/assert"
+
+ headtracker "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ evm "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
+)
+
+// const historySize = 4
+// const blockSize = int64(4)
+const finality = uint32(4)
+
+func TestNewAutomationCustomTelemetryService(t *testing.T) {
+ me := &MockMonitoringEndpoint{}
+ lggr := logger.TestLogger(t)
+ var hb headtracker.HeadBroadcaster
+ var lp logpoller.LogPoller
+
+ bs := evm.NewBlockSubscriber(hb, lp, finality, lggr)
+ // configTracker := &MockContractConfigTracker{}
+ var configTracker types.ContractConfigTracker
+
+ service, err := NewAutomationCustomTelemetryService(me, lggr, bs, configTracker)
+ if err != nil {
+ t.Errorf("Expected no error, but got: %v", err)
+ }
+ service.monitoringEndpoint.SendLog([]byte("test"))
+ assert.Equal(t, me.LogCount(), 1)
+ service.monitoringEndpoint.SendLog([]byte("test2"))
+ assert.Equal(t, me.LogCount(), 2)
+ service.Close()
+}
+
+type MockMonitoringEndpoint struct {
+ sentLogs [][]byte
+ lock sync.RWMutex
+}
+
+func (me *MockMonitoringEndpoint) SendLog(log []byte) {
+ me.lock.Lock()
+ defer me.lock.Unlock()
+ me.sentLogs = append(me.sentLogs, log)
+}
+
+func (me *MockMonitoringEndpoint) LogCount() int {
+ me.lock.RLock()
+ defer me.lock.RUnlock()
+ return len(me.sentLogs)
+}
diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml
index f5d775fe74..b897fba7f1 100644
--- a/core/web/resolver/testdata/config-empty-effective.toml
+++ b/core/web/resolver/testdata/config-empty-effective.toml
@@ -137,7 +137,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml
index 95d898c353..6cd6eaabc3 100644
--- a/core/web/resolver/testdata/config-full.toml
+++ b/core/web/resolver/testdata/config-full.toml
@@ -143,7 +143,7 @@ ContractTransmitterTransmitTimeout = '1m0s'
DatabaseTimeout = '8s'
KeyBundleID = '7a5f66bbe6594259325bf2b4f5b1a9c900000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml
index 9dd0be8f5d..c743601ced 100644
--- a/core/web/resolver/testdata/config-multi-chain-effective.toml
+++ b/core/web/resolver/testdata/config-multi-chain-effective.toml
@@ -137,7 +137,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '20s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index 1eb9cd5023..5b93c7061e 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -890,7 +890,7 @@ ContractTransmitterTransmitTimeout = '10s' # Default
DatabaseTimeout = '10s' # Default
KeyBundleID = '7a5f66bbe6594259325bf2b4f5b1a9c900000000000000000000000000000000' # Example
CaptureEATelemetry = false # Default
-CaptureAutomationCustomTelemetry = false # Default
+CaptureAutomationCustomTelemetry = true # Default
DefaultTransactionQueueDepth = 1 # Default
SimulateTransactions = false # Default
TraceLogging = false # Default
@@ -987,7 +987,7 @@ CaptureEATelemetry toggles collecting extra information from External Adaptares
### CaptureAutomationCustomTelemetry
```toml
-CaptureAutomationCustomTelemetry = false # Default
+CaptureAutomationCustomTelemetry = true # Default
```
CaptureAutomationCustomTelemetry toggles collecting automation specific telemetry
diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar
index 8a3b1af96f..01e96ac944 100644
--- a/testdata/scripts/node/validate/default.txtar
+++ b/testdata/scripts/node/validate/default.txtar
@@ -149,7 +149,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
index 31fded1b42..1f6901e9ff 100644
--- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar
@@ -193,7 +193,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
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 78fc976912..4c1a1c75fc 100644
--- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar
@@ -193,7 +193,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar
index 226a7bbb3b..536b7d8ac0 100644
--- a/testdata/scripts/node/validate/disk-based-logging.txtar
+++ b/testdata/scripts/node/validate/disk-based-logging.txtar
@@ -193,7 +193,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar
index 5cd3d56746..89f59574fc 100644
--- a/testdata/scripts/node/validate/invalid.txtar
+++ b/testdata/scripts/node/validate/invalid.txtar
@@ -183,7 +183,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar
index fd24150b58..2d32b39a64 100644
--- a/testdata/scripts/node/validate/valid.txtar
+++ b/testdata/scripts/node/validate/valid.txtar
@@ -190,7 +190,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar
index 828d953da9..e478203e00 100644
--- a/testdata/scripts/node/validate/warnings.txtar
+++ b/testdata/scripts/node/validate/warnings.txtar
@@ -186,7 +186,7 @@ ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000'
CaptureEATelemetry = false
-CaptureAutomationCustomTelemetry = false
+CaptureAutomationCustomTelemetry = true
DefaultTransactionQueueDepth = 1
SimulateTransactions = false
TraceLogging = false
From 29315fff30d0aa112036c01b6ccd98ef47e831d4 Mon Sep 17 00:00:00 2001
From: Tate
Date: Fri, 17 Nov 2023 14:59:39 -0700
Subject: [PATCH 173/327] Bump chainlink-github-actions refs to be up to date
(#11332)
---
.github/actions/build-chainlink-image/action.yml | 4 ++--
.github/actions/build-test-image/action.yml | 8 ++++----
.github/actions/version-file-bump/action.yml | 2 +-
.github/workflows/automation-benchmark-tests.yml | 2 +-
.github/workflows/automation-load-tests.yml | 2 +-
.github/workflows/automation-ondemand-tests.yml | 6 +++---
.github/workflows/ci-core.yml | 2 +-
.github/workflows/integration-chaos-tests.yml | 6 +++---
.github/workflows/integration-tests.yml | 16 ++++++++--------
.github/workflows/live-testnet-tests.yml | 6 +++---
.github/workflows/on-demand-ocr-soak-test.yml | 2 +-
.../on-demand-vrfv2plus-performance-test.yml | 2 +-
.github/workflows/performance-tests.yml | 2 +-
13 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/.github/actions/build-chainlink-image/action.yml b/.github/actions/build-chainlink-image/action.yml
index ac29a3d7b8..d5839cc79b 100644
--- a/.github/actions/build-chainlink-image/action.yml
+++ b/.github/actions/build-chainlink-image/action.yml
@@ -25,7 +25,7 @@ runs:
steps:
- name: Check if image exists
id: check-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
repository: chainlink
tag: ${{ inputs.git_commit_sha }}${{ inputs.tag_suffix }}
@@ -33,7 +33,7 @@ runs:
AWS_ROLE_TO_ASSUME: ${{ inputs.AWS_ROLE_TO_ASSUME }}
- name: Build Image
if: steps.check-image.outputs.exists == 'false'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
cl_repo: smartcontractkit/chainlink
cl_ref: ${{ inputs.git_commit_sha }}
diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml
index e6c759109b..b7a7948d2c 100644
--- a/.github/actions/build-test-image/action.yml
+++ b/.github/actions/build-test-image/action.yml
@@ -71,7 +71,7 @@ runs:
- name: Check if test base image exists
if: steps.version.outputs.is_semantic == 'false'
id: check-base-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
repository: ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image
tag: ${{ steps.long_sha.outputs.long_sha }}
@@ -79,7 +79,7 @@ runs:
AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
- name: Build Base Image
if: steps.version.outputs.is_semantic == 'false' && steps.check-base-image.outputs.exists == 'false'
- uses: smartcontractkit/chainlink-github-actions/docker/build-push@ce87f8986ca18336cc5015df75916c2ec0a7c4b3 # v2.1.2
+ uses: smartcontractkit/chainlink-github-actions/docker/build-push@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
BASE_IMAGE_NAME: ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image:${{ steps.long_sha.outputs.long_sha }}
with:
@@ -92,7 +92,7 @@ runs:
# Test Runner Logic
- name: Check if image exists
id: check-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
repository: ${{ inputs.repository }}
tag: ${{ inputs.tag }}
@@ -100,7 +100,7 @@ runs:
AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }}
- name: Build and Publish Test Runner
if: steps.check-image.outputs.exists == 'false'
- uses: smartcontractkit/chainlink-github-actions/docker/build-push@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12
+ uses: smartcontractkit/chainlink-github-actions/docker/build-push@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
tags: |
${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/${{ inputs.repository }}:${{ inputs.tag }}
diff --git a/.github/actions/version-file-bump/action.yml b/.github/actions/version-file-bump/action.yml
index 73a374762d..2083217400 100644
--- a/.github/actions/version-file-bump/action.yml
+++ b/.github/actions/version-file-bump/action.yml
@@ -31,7 +31,7 @@ runs:
current_version=$(head -n1 ./VERSION)
echo "current_version=${current_version}" | tee -a "$GITHUB_OUTPUT"
- name: Compare semantic versions
- uses: smartcontractkit/chainlink-github-actions/semver-compare@v2.2.0
+ uses: smartcontractkit/chainlink-github-actions/semver-compare@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
id: compare
with:
version1: ${{ steps.get-current-version.outputs.current_version }}
diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml
index 0fff36f8df..efe6d2eb59 100644
--- a/.github/workflows/automation-benchmark-tests.yml
+++ b/.github/workflows/automation-benchmark-tests.yml
@@ -110,7 +110,7 @@ jobs:
QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
suites: benchmark load/automationv2_1 chaos reorg
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
DETACH_RUNNER: true
TEST_SUITE: benchmark
diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml
index eebd87322c..b19ac8fd24 100644
--- a/.github/workflows/automation-load-tests.yml
+++ b/.github/workflows/automation-load-tests.yml
@@ -71,7 +71,7 @@ jobs:
QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
suites: benchmark load/automationv2_1 chaos reorg
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
RR_CPU: 4000m
RR_MEM: 4Gi
diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml
index 88c2c126dc..5cd2182ff6 100644
--- a/.github/workflows/automation-ondemand-tests.yml
+++ b/.github/workflows/automation-ondemand-tests.yml
@@ -59,7 +59,7 @@ jobs:
- name: Check if image exists
if: inputs.chainlinkImage == ''
id: check-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
repository: chainlink
tag: ${{ github.sha }}${{ matrix.image.tag-suffix }}
@@ -67,7 +67,7 @@ jobs:
AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
- name: Build Image
if: steps.check-image.outputs.exists == 'false' && inputs.chainlinkImage == ''
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
cl_repo: smartcontractkit/chainlink
cl_ref: ${{ github.sha }}
@@ -172,7 +172,7 @@ jobs:
echo "version=${{ inputs.chainlinkVersionUpdate }}" >>$GITHUB_OUTPUT
fi
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
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 }}
diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml
index d0bae66480..e69fc64cc7 100644
--- a/.github/workflows/ci-core.yml
+++ b/.github/workflows/ci-core.yml
@@ -84,7 +84,7 @@ jobs:
run: ./tools/bin/${{ matrix.cmd }} ./...
- name: Print Filtered Test Results
if: ${{ failure() && matrix.cmd == 'go_core_tests' }}
- uses: smartcontractkit/chainlink-github-actions/go/go-test-results-parsing@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/go/go-test-results-parsing@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
results-file: ./output.txt
output-file: ./output-short.txt
diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml
index 892a43e76f..10c6281099 100644
--- a/.github/workflows/integration-chaos-tests.yml
+++ b/.github/workflows/integration-chaos-tests.yml
@@ -30,7 +30,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Check if image exists
id: check-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
repository: chainlink
tag: ${{ github.sha }}
@@ -38,7 +38,7 @@ jobs:
AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
- name: Build Image
if: steps.check-image.outputs.exists == 'false'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
cl_repo: smartcontractkit/chainlink
cl_ref: ${{ github.sha }}
@@ -109,7 +109,7 @@ jobs:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 ./chaos 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 17f571fd63..9550be83ce 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -233,7 +233,7 @@ jobs:
## Run this step when changes that require tests to be run are made
- name: Run Tests
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725
PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }}
@@ -398,7 +398,7 @@ jobs:
## Run this step when changes that require tests to be run are made
- name: Run Tests
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725
PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }}
@@ -422,7 +422,7 @@ jobs:
## Run this step when changes that do not need the test to run are made
- name: Run Setup
if: needs.changes.outputs.src == 'false'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_download_vendor_packages_command: cd ./integration-tests && go mod download
go_mod_path: ./integration-tests/go.mod
@@ -521,7 +521,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Run Setup
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_download_vendor_packages_command: |
cd ./integration-tests
@@ -569,7 +569,7 @@ jobs:
run: |
echo "Running migration tests from version '${{ steps.get_latest_version.outputs.latest_version }}' to: '${{ github.sha }}'"
- name: Run Migration Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
@@ -669,7 +669,7 @@ jobs:
steps:
- name: Check if image exists
id: check-image
- uses: smartcontractkit/chainlink-github-actions/docker/image-exists@eccde1970eca69f079d3efb3409938a72ade8497 # v2.2.13
+ uses: smartcontractkit/chainlink-github-actions/docker/image-exists@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
repository: chainlink-solana-tests
tag: ${{ needs.get_solana_sha.outputs.sha }}
@@ -814,7 +814,7 @@ jobs:
ref: ${{ needs.get_solana_sha.outputs.sha }}
- name: Run Setup
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
go_mod_path: ./integration-tests/go.mod
cache_restore_only: true
@@ -843,7 +843,7 @@ jobs:
docker rm "$CONTAINER_ID"
- name: Run Tests
if: needs.changes.outputs.src == 'true'
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_command_to_run: export ENV_JOB_IMAGE=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} && make test_smoke
cl_repo: ${{ env.CHAINLINK_IMAGE }}
diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml
index 23e9b3c04c..7eb1669b35 100644
--- a/.github/workflows/live-testnet-tests.yml
+++ b/.github/workflows/live-testnet-tests.yml
@@ -78,7 +78,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia
@@ -133,7 +133,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-optimism-goerli
@@ -188,7 +188,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-arbitrum-goerli
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index 4ea10cd482..b17fdc6beb 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -133,7 +133,7 @@ jobs:
QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
env:
DETACH_RUNNER: true
TEST_SUITE: soak
diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
index b4f9f46de0..2e765ab79b 100644
--- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml
+++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml
@@ -118,7 +118,7 @@ jobs:
with:
fetch-depth: 0
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_command_to_run: cd ./integration-tests && go test -v -count=1 -timeout 6h -run TestVRFV2PlusPerformance/vrfv2plus_performance_test ./load/vrfv2plus
test_download_vendor_packages_command: cd ./integration-tests && go mod download
diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml
index 57907fe6c2..4b6dd1a228 100644
--- a/.github/workflows/performance-tests.yml
+++ b/.github/workflows/performance-tests.yml
@@ -57,7 +57,7 @@ jobs:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15
+ uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
with:
test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 10 ./performance 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: make gomod
From 6662c1ccef948be947c225f58b7c8372b5577e74 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Fri, 17 Nov 2023 16:07:01 -0600
Subject: [PATCH 174/327] switch from chainlink-relay to chainlink-common
(#11320)
---
common/client/mock_rpc_test.go | 2 +-
common/client/multi_node.go | 4 +-
common/client/multi_node_test.go | 2 +-
common/client/node.go | 2 +-
common/client/node_lifecycle_test.go | 2 +-
common/client/send_only_node.go | 2 +-
common/client/send_only_node_test.go | 2 +-
common/client/types.go | 2 +-
common/headtracker/head_broadcaster.go | 2 +-
common/headtracker/head_tracker.go | 2 +-
common/txmgr/broadcaster.go | 4 +-
common/txmgr/confirmer.go | 4 +-
common/txmgr/resender.go | 2 +-
common/txmgr/txmgr.go | 2 +-
core/bridges/bridge_type.go | 2 +-
core/bridges/bridge_type_test.go | 2 +-
core/chains/chain_kv.go | 2 +-
core/chains/chain_kv_test.go | 2 +-
core/chains/evm/assets/assets.go | 4 +-
core/chains/evm/assets/assets_test.go | 4 +-
core/chains/evm/chain.go | 10 +--
core/chains/evm/client/chain_client.go | 4 +-
core/chains/evm/client/client.go | 2 +-
core/chains/evm/client/mocks/client.go | 2 +-
core/chains/evm/client/node.go | 2 +-
core/chains/evm/client/null_client.go | 2 +-
core/chains/evm/client/pool.go | 2 +-
core/chains/evm/client/rpc_client.go | 8 +--
core/chains/evm/client/send_only_node.go | 2 +-
.../evm/client/simulated_backend_client.go | 2 +-
core/chains/evm/config/chain_scoped.go | 2 +-
core/chains/evm/config/config.go | 4 +-
core/chains/evm/config/toml/config.go | 22 +++---
.../evm/forwarders/forwarder_manager.go | 2 +-
core/chains/evm/gas/arbitrum_estimator.go | 2 +-
.../chains/evm/gas/block_history_estimator.go | 2 +-
core/chains/evm/gas/models.go | 2 +-
.../evm/gas/rollups/l1_gas_price_oracle.go | 2 +-
.../evm/gas/suggested_price_estimator.go | 2 +-
.../evm/headtracker/head_tracker_test.go | 2 +-
core/chains/evm/log/broadcaster.go | 2 +-
core/chains/evm/logpoller/log_poller.go | 2 +-
core/chains/evm/mocks/chain.go | 2 +-
core/chains/evm/monitor/balance.go | 2 +-
core/chains/evm/types/types.go | 2 +-
core/cmd/cosmos_node_commands_test.go | 11 ++-
core/cmd/cosmos_transaction_commands_test.go | 6 +-
core/cmd/eth_keys_commands_test.go | 12 ++--
core/cmd/shell.go | 2 +-
core/cmd/solana_node_commands_test.go | 2 +-
core/cmd/solana_transaction_commands_test.go | 6 +-
core/cmd/starknet_node_commands_test.go | 6 +-
core/config/parse/parsers.go | 8 +--
core/internal/cltest/cltest.go | 2 +-
core/internal/testutils/evmtest/evmtest.go | 2 +-
core/logger/logger.go | 4 +-
core/scripts/go.mod | 8 +--
core/scripts/go.sum | 16 ++---
core/services/blockhashstore/delegate.go | 2 +-
core/services/blockheaderfeeder/delegate.go | 2 +-
core/services/chainlink/application.go | 6 +-
core/services/chainlink/config_test.go | 70 +++++++++----------
.../mocks/relayer_chain_interoperators.go | 4 +-
.../chainlink/relayer_chain_interoperators.go | 4 +-
.../relayer_chain_interoperators_test.go | 20 +++---
core/services/chainlink/relayer_factory.go | 2 +-
core/services/directrequest/delegate.go | 4 +-
core/services/directrequest/delegate_test.go | 2 +-
core/services/directrequest/validate.go | 2 +-
core/services/feeds/service.go | 2 +-
core/services/fluxmonitorv2/config.go | 2 +-
core/services/fluxmonitorv2/flux_monitor.go | 2 +-
.../fluxmonitorv2/flux_monitor_test.go | 2 +-
.../services/fluxmonitorv2/payment_checker.go | 2 +-
.../fluxmonitorv2/payment_checker_test.go | 2 +-
core/services/fluxmonitorv2/validate_test.go | 2 +-
core/services/functions/connector_handler.go | 4 +-
.../functions/connector_handler_test.go | 2 +-
core/services/functions/listener.go | 2 +-
core/services/gateway/connectionmanager.go | 2 +-
core/services/gateway/connector/connector.go | 2 +-
core/services/gateway/gateway.go | 2 +-
.../gateway/handlers/functions/allowlist.go | 2 +-
.../handlers/functions/handler.functions.go | 4 +-
.../functions/handler.functions_test.go | 2 +-
.../handlers/functions/subscriptions.go | 2 +-
core/services/gateway/network/httpserver.go | 2 +-
core/services/gateway/network/wsconnection.go | 2 +-
core/services/gateway/network/wsserver.go | 2 +-
core/services/health.go | 2 +-
core/services/job/job_orm_test.go | 2 +-
core/services/job/models.go | 8 +--
core/services/job/orm.go | 2 +-
core/services/job/spawner.go | 8 +--
core/services/job/spawner_test.go | 4 +-
.../keeper/registry_synchronizer_core.go | 2 +-
core/services/keeper/upkeep_executer.go | 2 +-
core/services/keystore/cosmos.go | 4 +-
core/services/keystore/keys/ethkey/address.go | 2 +-
core/services/keystore/starknet.go | 8 +--
core/services/mocks/checker.go | 2 +-
core/services/multi.go | 2 +-
core/services/nurse.go | 2 +-
core/services/ocr/config_overrider.go | 2 +-
core/services/ocr/contract_tracker.go | 2 +-
core/services/ocr/delegate.go | 4 +-
core/services/ocr2/delegate.go | 15 ++--
core/services/ocr2/delegate_test.go | 2 +-
.../ocr2/plugins/functions/config/config.go | 2 +-
.../services/ocr2/plugins/functions/plugin.go | 2 +-
.../ocr2/plugins/functions/plugin_test.go | 2 +-
.../ocr2/plugins/functions/reporting_test.go | 4 +-
.../generic/pipeline_runner_adapter.go | 2 +-
.../generic/pipeline_runner_adapter_test.go | 2 +-
.../ocr2/plugins/generic/telemetry_adapter.go | 2 +-
core/services/ocr2/plugins/median/plugin.go | 8 +--
core/services/ocr2/plugins/median/services.go | 4 +-
.../ocr2/plugins/mercury/integration_test.go | 8 +--
core/services/ocr2/plugins/mercury/plugin.go | 10 +--
.../plugins/ocr2keeper/evm20/log_provider.go | 2 +-
.../ocr2/plugins/ocr2keeper/evm20/registry.go | 2 +-
.../ocr2keeper/evm21/block_subscriber.go | 2 +-
.../ocr2keeper/evm21/logprovider/provider.go | 2 +-
.../ocr2keeper/evm21/logprovider/recoverer.go | 2 +-
.../evm21/mercury/streams/streams.go | 2 +-
.../evm21/transmit/event_provider.go | 2 +-
.../ocr2keeper/evm21/upkeepstate/store.go | 2 +-
.../plugins/ocr2keeper/integration_21_test.go | 11 ++-
.../plugins/ocr2keeper/integration_test.go | 10 +--
core/services/ocr2/plugins/ocr2keeper/util.go | 3 +-
.../ocr2vrf/coordinator/coordinator_test.go | 12 ++--
core/services/ocr2/plugins/s4/factory_test.go | 4 +-
.../ocr2/plugins/s4/integration_test.go | 4 +-
core/services/ocr2/plugins/s4/plugin_test.go | 19 ++---
core/services/ocr2/validate/validate.go | 2 +-
core/services/ocrbootstrap/delegate.go | 9 +--
core/services/ocrcommon/peer_wrapper.go | 7 +-
core/services/ocrcommon/peerstore.go | 2 +-
core/services/ocrcommon/run_saver.go | 2 +-
core/services/ocrcommon/telemetry.go | 8 +--
core/services/ocrcommon/telemetry_test.go | 9 +--
core/services/periodicbackup/backup.go | 2 +-
core/services/pg/event_broadcaster.go | 2 +-
core/services/pg/q.go | 2 +-
core/services/pg/sqlx.go | 2 +-
core/services/pg/transaction.go | 2 +-
core/services/pipeline/orm.go | 2 +-
core/services/pipeline/runner.go | 2 +-
core/services/promreporter/prom_reporter.go | 2 +-
core/services/relay/evm/config_poller.go | 2 +-
core/services/relay/evm/evm.go | 22 +++---
core/services/relay/evm/functions.go | 12 ++--
.../relay/evm/functions/logpoller_wrapper.go | 2 +-
core/services/relay/evm/loop_impl.go | 2 +-
.../relay/evm/mercury/persistence_manager.go | 2 +-
core/services/relay/evm/mercury/queue.go | 2 +-
.../services/relay/evm/mercury/transmitter.go | 5 +-
.../relay/evm/mercury/v1/data_source.go | 4 +-
.../relay/evm/mercury/v1/data_source_test.go | 4 +-
.../mercury/v1/reportcodec/report_codec.go | 3 +-
.../v1/reportcodec/report_codec_test.go | 2 +-
.../relay/evm/mercury/v2/data_source.go | 4 +-
.../relay/evm/mercury/v2/data_source_test.go | 4 +-
.../mercury/v2/reportcodec/report_codec.go | 3 +-
.../v2/reportcodec/report_codec_test.go | 2 +-
.../relay/evm/mercury/v3/data_source.go | 4 +-
.../relay/evm/mercury/v3/data_source_test.go | 4 +-
.../mercury/v3/reportcodec/report_codec.go | 3 +-
.../v3/reportcodec/report_codec_test.go | 2 +-
.../relay/evm/mercury/wsrpc/client.go | 2 +-
core/services/relay/evm/mercury_provider.go | 14 ++--
.../relay/evm/mocks/loop_relay_adapter.go | 2 +-
core/services/relay/evm/ocr2keeper.go | 15 ++--
core/services/relay/evm/ocr2vrf.go | 17 ++---
core/services/relay/evm/relayer_extender.go | 8 +--
.../relay/evm/request_round_tracker.go | 3 +-
core/services/relay/evm/types/types.go | 12 ++--
core/services/relay/grpc_provider_server.go | 4 +-
.../relay/grpc_provider_server_test.go | 2 +-
core/services/relay/relay.go | 4 +-
core/services/relay/relay_test.go | 7 +-
core/services/service.go | 2 +-
.../telemetry_ingress_batch_client.go | 2 +-
.../telemetry_ingress_client.go | 2 +-
core/services/telemetry/manager.go | 2 +-
core/services/telemetry/manager_test.go | 2 +-
.../vrf_coordinator_interface.go | 2 +-
core/services/vrf/v1/listener_v1.go | 2 +-
core/services/vrf/v2/integration_v2_test.go | 4 +-
core/services/vrf/v2/listener_v2.go | 2 +-
core/store/migrate/migrate_test.go | 2 +-
core/utils/big.go | 2 +-
core/utils/config/validate.go | 2 +-
core/utils/mailbox_prom.go | 2 +-
core/utils/sleeper_task.go | 2 +-
core/utils/utils.go | 2 +-
core/web/bridge_types_controller.go | 2 +-
core/web/bridge_types_controller_test.go | 2 +-
core/web/chains_controller.go | 2 +-
core/web/cosmos_chains_controller_test.go | 2 +-
core/web/eth_keys_controller.go | 8 +--
core/web/eth_keys_controller_test.go | 2 +-
core/web/loader/getters.go | 6 +-
core/web/loader/loader_test.go | 22 +++---
core/web/loader/node.go | 2 +-
core/web/loop_registry_test.go | 2 +-
core/web/nodes_controller.go | 2 +-
core/web/presenters/bridges.go | 2 +-
core/web/presenters/bridges_test.go | 2 +-
core/web/presenters/cosmos_chain.go | 2 +-
core/web/presenters/eth_key.go | 20 +++---
core/web/presenters/eth_key_test.go | 6 +-
core/web/presenters/evm_chain.go | 2 +-
core/web/presenters/job.go | 6 +-
core/web/presenters/job_test.go | 2 +-
core/web/presenters/solana_chain.go | 2 +-
core/web/presenters/starknet_chain.go | 2 +-
core/web/resolver/bridge_test.go | 2 +-
core/web/resolver/chain.go | 2 +-
core/web/resolver/eth_key_test.go | 8 +--
core/web/resolver/helpers.go | 2 +-
core/web/resolver/mutation.go | 2 +-
core/web/resolver/node.go | 2 +-
core/web/resolver/node_test.go | 2 +-
core/web/resolver/query.go | 2 +-
core/web/resolver/spec_test.go | 10 +--
core/web/solana_chains_controller_test.go | 8 +--
go.mod | 8 +--
go.sum | 16 ++---
.../actions/vrfv2plus/vrfv2plus_steps.go | 12 ++--
integration-tests/go.mod | 8 +--
integration-tests/go.sum | 16 ++---
integration-tests/types/config/node/core.go | 6 +-
plugins/cmd/chainlink-median/main.go | 2 +-
plugins/cmd/chainlink-medianpoc/main.go | 6 +-
plugins/config.go | 2 +-
plugins/loop_registry.go | 4 +-
plugins/medianpoc/data_source.go | 4 +-
plugins/medianpoc/data_source_test.go | 5 +-
plugins/medianpoc/plugin.go | 10 +--
plugins/medianpoc/plugin_test.go | 2 +-
241 files changed, 551 insertions(+), 538 deletions(-)
diff --git a/common/client/mock_rpc_test.go b/common/client/mock_rpc_test.go
index 8f171302a2..d5e8db8283 100644
--- a/common/client/mock_rpc_test.go
+++ b/common/client/mock_rpc_test.go
@@ -5,7 +5,7 @@ package client
import (
big "math/big"
- assets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ assets "github.com/smartcontractkit/chainlink-common/pkg/assets"
context "context"
diff --git a/common/client/multi_node.go b/common/client/multi_node.go
index df91c61a9d..acab47f083 100644
--- a/common/client/multi_node.go
+++ b/common/client/multi_node.go
@@ -11,8 +11,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/config"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go
index 3621d6d862..4c0ebb1db9 100644
--- a/common/client/multi_node_test.go
+++ b/common/client/multi_node_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/common/types"
diff --git a/common/client/node.go b/common/client/node.go
index f28a171a55..5faaa5da62 100644
--- a/common/client/node.go
+++ b/common/client/node.go
@@ -11,7 +11,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go
index 564c08bbdc..0dffe935fe 100644
--- a/common/client/node_lifecycle_test.go
+++ b/common/client/node_lifecycle_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/common/types/mocks"
diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go
index fa793a826a..767fff5aee 100644
--- a/common/client/send_only_node.go
+++ b/common/client/send_only_node.go
@@ -6,7 +6,7 @@ import (
"net/url"
"sync"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/common/client/send_only_node_test.go b/common/client/send_only_node_test.go
index bfe5515365..3034b3f0a1 100644
--- a/common/client/send_only_node_test.go
+++ b/common/client/send_only_node_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/common/client/types.go b/common/client/types.go
index ef9f94dafe..6d3a22cee7 100644
--- a/common/client/types.go
+++ b/common/client/types.go
@@ -4,7 +4,7 @@ import (
"context"
"math/big"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/common/headtracker/head_broadcaster.go b/common/headtracker/head_broadcaster.go
index e9ae93419b..3efe64e1c3 100644
--- a/common/headtracker/head_broadcaster.go
+++ b/common/headtracker/head_broadcaster.go
@@ -7,7 +7,7 @@ import (
"sync"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go
index 54262dd93f..bf63675128 100644
--- a/common/headtracker/head_tracker.go
+++ b/common/headtracker/head_tracker.go
@@ -10,7 +10,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index 1e3b2fa0a9..ba01fb9e2a 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -15,8 +15,8 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/chains/label"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/chains/label"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go
index 4d3626ffac..bf35611582 100644
--- a/common/txmgr/confirmer.go
+++ b/common/txmgr/confirmer.go
@@ -14,8 +14,8 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/chains/label"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/chains/label"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/client"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go
index 75781c0840..e604a960bf 100644
--- a/common/txmgr/resender.go
+++ b/common/txmgr/resender.go
@@ -6,7 +6,7 @@ import (
"fmt"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/chains/label"
+ "github.com/smartcontractkit/chainlink-common/pkg/chains/label"
"github.com/smartcontractkit/chainlink/v2/common/client"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go
index 5b7afd3224..24d2428f61 100644
--- a/common/txmgr/txmgr.go
+++ b/common/txmgr/txmgr.go
@@ -11,7 +11,7 @@ import (
"github.com/google/uuid"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
diff --git a/core/bridges/bridge_type.go b/core/bridges/bridge_type.go
index 9031541f22..b2e86df4b9 100644
--- a/core/bridges/bridge_type.go
+++ b/core/bridges/bridge_type.go
@@ -10,7 +10,7 @@ import (
"strings"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/bridges/bridge_type_test.go b/core/bridges/bridge_type_test.go
index c04aba5c2c..6a719d5b53 100644
--- a/core/bridges/bridge_type_test.go
+++ b/core/bridges/bridge_type_test.go
@@ -11,7 +11,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
diff --git a/core/chains/chain_kv.go b/core/chains/chain_kv.go
index 5094f2885e..4365a859bb 100644
--- a/core/chains/chain_kv.go
+++ b/core/chains/chain_kv.go
@@ -6,7 +6,7 @@ import (
"golang.org/x/exp/maps"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
type ChainsKV[T types.ChainService] struct {
diff --git a/core/chains/chain_kv_test.go b/core/chains/chain_kv_test.go
index a30de3090b..205ee693d6 100644
--- a/core/chains/chain_kv_test.go
+++ b/core/chains/chain_kv_test.go
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains"
)
diff --git a/core/chains/evm/assets/assets.go b/core/chains/evm/assets/assets.go
index c6c81b5ab4..377e92a855 100644
--- a/core/chains/evm/assets/assets.go
+++ b/core/chains/evm/assets/assets.go
@@ -5,8 +5,8 @@ import (
"fmt"
"math/big"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils/bytes"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/shopspring/decimal"
diff --git a/core/chains/evm/assets/assets_test.go b/core/chains/evm/assets/assets_test.go
index 9496554f11..09eb7b6888 100644
--- a/core/chains/evm/assets/assets_test.go
+++ b/core/chains/evm/assets/assets_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
)
@@ -69,7 +69,7 @@ func TestAssets_Eth_UnmarshalJsonError(t *testing.T) {
assert.EqualError(t, err, "assets: cannot unmarshal \"x\" into a *assets.Eth")
err = json.Unmarshal([]byte(`1`), ð)
- assert.Equal(t, relayassets.ErrNoQuotesForCurrency, err)
+ assert.Equal(t, commonassets.ErrNoQuotesForCurrency, err)
}
func TestAssets_NewEth(t *testing.T) {
diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go
index f21bf2525a..1e52bed5cb 100644
--- a/core/chains/evm/chain.go
+++ b/core/chains/evm/chain.go
@@ -13,9 +13,9 @@ import (
"github.com/jmoiron/sqlx"
- relaychains "github.com/smartcontractkit/chainlink-relay/pkg/chains"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ common "github.com/smartcontractkit/chainlink-common/pkg/chains"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains"
@@ -422,7 +422,7 @@ func (c *chain) listNodeStatuses(start, end int) ([]types.NodeStatus, int, error
nodes := c.cfg.Nodes()
total := len(nodes)
if start >= total {
- return nil, total, relaychains.ErrOutOfRange
+ return nil, total, common.ErrOutOfRange
}
if end > total {
end = total
@@ -459,7 +459,7 @@ func (c *chain) listNodeStatuses(start, end int) ([]types.NodeStatus, int, error
}
func (c *chain) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []types.NodeStatus, nextPageToken string, total int, err error) {
- return relaychains.ListNodeStatuses(int(pageSize), pageToken, c.listNodeStatuses)
+ return common.ListNodeStatuses(int(pageSize), pageToken, c.listNodeStatuses)
}
func (c *chain) ID() *big.Int { return c.id }
diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go
index 79a91dfc05..0f15b35ee9 100644
--- a/core/chains/evm/client/chain_client.go
+++ b/core/chains/evm/client/chain_client.go
@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
@@ -183,7 +183,7 @@ func (c *chainClient) IsL2() bool {
return c.multiNode.IsL2()
}
-func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*relayassets.Link, error) {
+func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*commonassets.Link, error) {
return c.multiNode.LINKBalance(ctx, address, linkAddress)
}
diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go
index 988a7404c9..5263c74de1 100644
--- a/core/chains/evm/client/client.go
+++ b/core/chains/evm/client/client.go
@@ -6,7 +6,7 @@ import (
"strings"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/common/config"
htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types"
diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go
index f1ff5fab45..22498370a2 100644
--- a/core/chains/evm/client/mocks/client.go
+++ b/core/chains/evm/client/mocks/client.go
@@ -5,7 +5,7 @@ package mocks
import (
big "math/big"
- assets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ assets "github.com/smartcontractkit/chainlink-common/pkg/assets"
common "github.com/ethereum/go-ethereum/common"
diff --git a/core/chains/evm/client/node.go b/core/chains/evm/client/node.go
index 80bac25448..b690720240 100644
--- a/core/chains/evm/client/node.go
+++ b/core/chains/evm/client/node.go
@@ -19,7 +19,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go
index 45876d9259..e25fed6d96 100644
--- a/core/chains/evm/client/null_client.go
+++ b/core/chains/evm/client/null_client.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go
index 473ab6d1eb..18f59b172d 100644
--- a/core/chains/evm/client/pool.go
+++ b/core/chains/evm/client/pool.go
@@ -15,7 +15,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/config"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go
index f952c04d5b..785acbb2b7 100644
--- a/core/chains/evm/client/rpc_client.go
+++ b/core/chains/evm/client/rpc_client.go
@@ -17,7 +17,7 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
commontypes "github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
@@ -869,12 +869,12 @@ func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, co
}
// LINKBalance returns the balance of LINK at the given address
-func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*relayassets.Link, error) {
+func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*commonassets.Link, error) {
balance, err := r.TokenBalance(ctx, address, linkAddress)
if err != nil {
- return relayassets.NewLinkFromJuels(0), err
+ return commonassets.NewLinkFromJuels(0), err
}
- return (*relayassets.Link)(balance), nil
+ return (*commonassets.Link)(balance), nil
}
func (r *rpcClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
diff --git a/core/chains/evm/client/send_only_node.go b/core/chains/evm/client/send_only_node.go
index 3f2481c189..beb12dbc4d 100644
--- a/core/chains/evm/client/send_only_node.go
+++ b/core/chains/evm/client/send_only_node.go
@@ -14,7 +14,7 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go
index 33ecc3d0d5..e922715eb9 100644
--- a/core/chains/evm/client/simulated_backend_client.go
+++ b/core/chains/evm/client/simulated_backend_client.go
@@ -18,7 +18,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/chains/evm/config/chain_scoped.go b/core/chains/evm/config/chain_scoped.go
index 6030991179..804c354e0e 100644
--- a/core/chains/evm/config/chain_scoped.go
+++ b/core/chains/evm/config/chain_scoped.go
@@ -9,7 +9,7 @@ import (
ocr "github.com/smartcontractkit/libocr/offchainreporting"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config"
diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go
index ec90797d7f..2dd2d4704c 100644
--- a/core/chains/evm/config/config.go
+++ b/core/chains/evm/config/config.go
@@ -6,7 +6,7 @@ import (
gethcommon "github.com/ethereum/go-ethereum/common"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/config"
@@ -34,7 +34,7 @@ type EVM interface {
LogBackfillBatchSize() uint32
LogKeepBlocksDepth() uint32
LogPollInterval() time.Duration
- MinContractPayment() *relayassets.Link
+ MinContractPayment() *commonassets.Link
MinIncomingConfirmations() uint32
NonceAutoSync() bool
OperatorFactoryAddress() string
diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go
index ae0fb41c5e..26587cd3b0 100644
--- a/core/chains/evm/config/toml/config.go
+++ b/core/chains/evm/config/toml/config.go
@@ -12,8 +12,8 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains"
@@ -107,7 +107,7 @@ func (cs EVMConfigs) totalChains() int {
}
return total
}
-func (cs EVMConfigs) Chains(ids ...relay.ChainID) (r []relaytypes.ChainStatus, total int, err error) {
+func (cs EVMConfigs) Chains(ids ...relay.ChainID) (r []commontypes.ChainStatus, total int, err error) {
total = cs.totalChains()
for _, ch := range cs {
if ch == nil {
@@ -126,7 +126,7 @@ func (cs EVMConfigs) Chains(ids ...relay.ChainID) (r []relaytypes.ChainStatus, t
continue
}
}
- ch2 := relaytypes.ChainStatus{
+ ch2 := commontypes.ChainStatus{
ID: ch.ChainID.String(),
Enabled: ch.IsEnabled(),
}
@@ -150,7 +150,7 @@ func (cs EVMConfigs) Node(name string) (types.Node, error) {
return types.Node{}, fmt.Errorf("node %s: %w", name, chains.ErrNotFound)
}
-func (cs EVMConfigs) NodeStatus(name string) (relaytypes.NodeStatus, error) {
+func (cs EVMConfigs) NodeStatus(name string) (commontypes.NodeStatus, error) {
for i := range cs {
for _, n := range cs[i].Nodes {
if n.Name != nil && *n.Name == name {
@@ -158,7 +158,7 @@ func (cs EVMConfigs) NodeStatus(name string) (relaytypes.NodeStatus, error) {
}
}
}
- return relaytypes.NodeStatus{}, fmt.Errorf("node %s: %w", name, chains.ErrNotFound)
+ return commontypes.NodeStatus{}, fmt.Errorf("node %s: %w", name, chains.ErrNotFound)
}
func legacyNode(n *Node, chainID *utils.Big) (v2 types.Node) {
@@ -179,13 +179,13 @@ func legacyNode(n *Node, chainID *utils.Big) (v2 types.Node) {
return
}
-func nodeStatus(n *Node, chainID relay.ChainID) (relaytypes.NodeStatus, error) {
- var s relaytypes.NodeStatus
+func nodeStatus(n *Node, chainID relay.ChainID) (commontypes.NodeStatus, error) {
+ var s commontypes.NodeStatus
s.ChainID = chainID
s.Name = *n.Name
b, err := toml.Marshal(n)
if err != nil {
- return relaytypes.NodeStatus{}, err
+ return commontypes.NodeStatus{}, err
}
s.Config = string(b)
return s, nil
@@ -220,7 +220,7 @@ func (cs EVMConfigs) Nodes(chainID relay.ChainID) (ns []types.Node, err error) {
return
}
-func (cs EVMConfigs) NodeStatuses(chainIDs ...relay.ChainID) (ns []relaytypes.NodeStatus, err error) {
+func (cs EVMConfigs) NodeStatuses(chainIDs ...relay.ChainID) (ns []commontypes.NodeStatus, err error) {
if len(chainIDs) == 0 {
for i := range cs {
for _, n := range cs[i].Nodes {
@@ -355,7 +355,7 @@ type Chain struct {
LogPollInterval *models.Duration
LogKeepBlocksDepth *uint32
MinIncomingConfirmations *uint32
- MinContractPayment *relayassets.Link
+ MinContractPayment *commonassets.Link
NonceAutoSync *bool
NoNewHeadsThreshold *models.Duration
OperatorFactoryAddress *ethkey.EIP55Address
diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go
index 934da487fd..819fb31951 100644
--- a/core/chains/evm/forwarders/forwarder_manager.go
+++ b/core/chains/evm/forwarders/forwarder_manager.go
@@ -12,7 +12,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmlogpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go
index 860126a588..c79202c731 100644
--- a/core/chains/evm/gas/arbitrum_estimator.go
+++ b/core/chains/evm/gas/arbitrum_estimator.go
@@ -13,7 +13,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go
index eb35cd2751..a3f3520b36 100644
--- a/core/chains/evm/gas/block_history_estimator.go
+++ b/core/chains/evm/gas/block_history_estimator.go
@@ -15,7 +15,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/config"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go
index 50cbddcd9b..b6f34ab87a 100644
--- a/core/chains/evm/gas/models.go
+++ b/core/chains/evm/gas/models.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/config"
commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
index 09244e9d31..88c61c4934 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go
index 24cf20f172..dadec6210c 100644
--- a/core/chains/evm/gas/suggested_price_estimator.go
+++ b/core/chains/evm/gas/suggested_price_estimator.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go
index 8af344098f..d734b230e1 100644
--- a/core/chains/evm/headtracker/head_tracker_test.go
+++ b/core/chains/evm/headtracker/head_tracker_test.go
@@ -20,7 +20,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go
index 9c4050fd79..11c282a4d2 100644
--- a/core/chains/evm/log/broadcaster.go
+++ b/core/chains/evm/log/broadcaster.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go
index b86ede5dbc..6676b694b0 100644
--- a/core/chains/evm/logpoller/log_poller.go
+++ b/core/chains/evm/logpoller/log_poller.go
@@ -20,7 +20,7 @@ import (
"github.com/pkg/errors"
"golang.org/x/exp/maps"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/chains/evm/mocks/chain.go b/core/chains/evm/mocks/chain.go
index f0f202b093..3a686887d7 100644
--- a/core/chains/evm/mocks/chain.go
+++ b/core/chains/evm/mocks/chain.go
@@ -30,7 +30,7 @@ import (
txmgr "github.com/smartcontractkit/chainlink/v2/common/txmgr"
- types "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ types "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// Chain is an autogenerated mock type for the Chain type
diff --git a/core/chains/evm/monitor/balance.go b/core/chains/evm/monitor/balance.go
index 476d3c7019..b12346ac00 100644
--- a/core/chains/evm/monitor/balance.go
+++ b/core/chains/evm/monitor/balance.go
@@ -13,7 +13,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/chains/evm/types/types.go b/core/chains/evm/types/types.go
index 7d756485d0..d0e7292b20 100644
--- a/core/chains/evm/types/types.go
+++ b/core/chains/evm/types/types.go
@@ -12,7 +12,7 @@ import (
"github.com/pkg/errors"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/cmd/cosmos_node_commands_test.go b/core/cmd/cosmos_node_commands_test.go
index 591160629e..728be9396f 100644
--- a/core/cmd/cosmos_node_commands_test.go
+++ b/core/cmd/cosmos_node_commands_test.go
@@ -9,9 +9,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
+ "github.com/smartcontractkit/chainlink-common/pkg/config"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
@@ -33,14 +32,14 @@ func TestShell_IndexCosmosNodes(t *testing.T) {
t.Parallel()
chainID := cosmostest.RandomChainID()
- node := config.Node{
+ node := coscfg.Node{
Name: ptr("second"),
- TendermintURL: relaycfg.MustParseURL("http://tender.mint.test/bombay-12"),
+ TendermintURL: config.MustParseURL("http://tender.mint.test/bombay-12"),
}
- chain := config.TOMLConfig{
+ chain := coscfg.TOMLConfig{
ChainID: ptr(chainID),
Enabled: ptr(true),
- Nodes: config.Nodes{&node},
+ Nodes: coscfg.Nodes{&node},
}
app := cosmosStartNewApplication(t, &chain)
client, r := app.NewShellAndRenderer()
diff --git a/core/cmd/cosmos_transaction_commands_test.go b/core/cmd/cosmos_transaction_commands_test.go
index 67b014af2c..f54ccaf4a6 100644
--- a/core/cmd/cosmos_transaction_commands_test.go
+++ b/core/cmd/cosmos_transaction_commands_test.go
@@ -13,16 +13,16 @@ import (
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
+ "github.com/smartcontractkit/chainlink-common/pkg/config"
cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
cosmosdb "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/denom"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"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/internal/testutils/cosmostest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
)
@@ -50,7 +50,7 @@ func TestShell_SendCosmosCoins(t *testing.T) {
nodes := coscfg.Nodes{
&coscfg.Node{
Name: ptr("random"),
- TendermintURL: utils.MustParseURL(url),
+ TendermintURL: config.MustParseURL(url),
},
}
chainConfig := coscfg.TOMLConfig{ChainID: &chainID, Enabled: ptr(true), Chain: cosmosChain, Nodes: nodes}
diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go
index d74ae231d7..293a2d3f6d 100644
--- a/core/cmd/eth_keys_commands_test.go
+++ b/core/cmd/eth_keys_commands_test.go
@@ -12,7 +12,7 @@ import (
"github.com/pkg/errors"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
@@ -35,7 +35,7 @@ func TestEthKeysPresenter_RenderTable(t *testing.T) {
var (
address = "0x5431F5F973781809D18643b87B44921b11355d81"
ethBalance = assets.NewEth(1)
- linkBalance = relayassets.NewLinkFromJuels(2)
+ linkBalance = commonassets.NewLinkFromJuels(2)
isDisabled = true
createdAt = time.Now()
updatedAt = time.Now().Add(time.Second)
@@ -90,7 +90,7 @@ func TestShell_ListETHKeys(t *testing.T) {
ethClient := newEthMock(t)
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(13), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(13), nil)
ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil)
app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].Enabled = ptr(true)
@@ -169,7 +169,7 @@ func TestShell_CreateETHKey(t *testing.T) {
ethClient := newEthMock(t)
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(42), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(42), nil)
ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil)
app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
@@ -244,7 +244,7 @@ func TestShell_ImportExportETHKey_NoChains(t *testing.T) {
ethClient := newEthMock(t)
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(42), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(42), nil)
ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil)
app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].Enabled = ptr(true)
@@ -362,7 +362,7 @@ func TestShell_ImportExportETHKey_WithChains(t *testing.T) {
ethClient.On("Dial", mock.Anything).Maybe()
ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil)
- ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(relayassets.NewLinkFromJuels(42), nil)
+ ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(42), nil)
set := flag.NewFlagSet("test", 0)
cltest.FlagSetApplyFromAction(client.RemoteLogin, set, "")
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 07cd2185dc..52c9090736 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -31,7 +31,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/build"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/cmd/solana_node_commands_test.go b/core/cmd/solana_node_commands_test.go
index 7c88557c6d..316cf16212 100644
--- a/core/cmd/solana_node_commands_test.go
+++ b/core/cmd/solana_node_commands_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/config"
+ "github.com/smartcontractkit/chainlink-common/pkg/config"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
diff --git a/core/cmd/solana_transaction_commands_test.go b/core/cmd/solana_transaction_commands_test.go
index cdb182cba4..f019616cb8 100644
--- a/core/cmd/solana_transaction_commands_test.go
+++ b/core/cmd/solana_transaction_commands_test.go
@@ -15,11 +15,11 @@ import (
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils"
+ "github.com/smartcontractkit/chainlink-common/pkg/config"
+ "github.com/smartcontractkit/chainlink-solana/pkg/solana"
solanaClient "github.com/smartcontractkit/chainlink-solana/pkg/solana/client"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
- "github.com/smartcontractkit/chainlink-solana/pkg/solana"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
)
@@ -29,7 +29,7 @@ func TestShell_SolanaSendSol(t *testing.T) {
url := solanaClient.SetupLocalSolNode(t)
node := solcfg.Node{
Name: ptr(t.Name()),
- URL: utils.MustParseURL(url),
+ URL: config.MustParseURL(url),
}
cfg := solana.TOMLConfig{
ChainID: &chainID,
diff --git a/core/cmd/starknet_node_commands_test.go b/core/cmd/starknet_node_commands_test.go
index 9d7c6fcaf4..0347cdd18f 100644
--- a/core/cmd/starknet_node_commands_test.go
+++ b/core/cmd/starknet_node_commands_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
+ commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
@@ -34,11 +34,11 @@ func TestShell_IndexStarkNetNodes(t *testing.T) {
id := "starknet chain ID"
node1 := config.Node{
Name: ptr("first"),
- URL: relaycfg.MustParseURL("https://starknet1.example"),
+ URL: commoncfg.MustParseURL("https://starknet1.example"),
}
node2 := config.Node{
Name: ptr("second"),
- URL: relaycfg.MustParseURL("https://starknet2.example"),
+ URL: commoncfg.MustParseURL("https://starknet2.example"),
}
chain := config.TOMLConfig{
ChainID: &id,
diff --git a/core/config/parse/parsers.go b/core/config/parse/parsers.go
index e2f6978187..6243b74dd5 100644
--- a/core/config/parse/parsers.go
+++ b/core/config/parse/parsers.go
@@ -13,7 +13,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/zap/zapcore"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/static"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -23,10 +23,10 @@ func String(str string) (string, error) {
return str, nil
}
-func Link(str string) (*relayassets.Link, error) {
- i, ok := new(relayassets.Link).SetString(str, 10)
+func Link(str string) (*commonassets.Link, error) {
+ i, ok := new(commonassets.Link).SetString(str, 10)
if !ok {
- return i, fmt.Errorf("unable to parse '%v' into *relayassets.Link(base 10)", str)
+ return i, fmt.Errorf("unable to parse '%s'", str)
}
return i, nil
}
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 83a97833bd..02aa2de0cc 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -43,7 +43,7 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/common/client"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go
index 80237d218d..7674650c01 100644
--- a/core/internal/testutils/evmtest/evmtest.go
+++ b/core/internal/testutils/evmtest/evmtest.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains"
diff --git a/core/logger/logger.go b/core/logger/logger.go
index 8e847a99ac..1feaf0f5d6 100644
--- a/core/logger/logger.go
+++ b/core/logger/logger.go
@@ -12,7 +12,7 @@ import (
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ common "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/v2/core/static"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -49,7 +49,7 @@ func init() {
}
}
-var _ relaylogger.Logger = (Logger)(nil)
+var _ common.Logger = (Logger)(nil)
//go:generate mockery --quiet --name Logger --output . --filename logger_mock_test.go --inpackage --case=underscore
//go:generate mockery --quiet --name Logger --output ./mocks/ --case=underscore
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 7bf60aff8b..1d8ba40b82 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -303,10 +303,10 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd // indirect
- github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
- github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
+ github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 // indirect
+ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 // indirect
+ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect
github.com/smartcontractkit/wsrpc v0.7.2 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 7139f0efa4..13496adb7a 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1462,14 +1462,14 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd h1:PRVJxNK67pQWufXuB1cxckH/xZkcQFDy8KjN9ZYqong=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd/go.mod h1:rOayi690YxLlkQy959PD8INhOAIAUi9LoN0G+J/CEf4=
-github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
-github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
-github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
-github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542/go.mod h1:EpvRoycRD+kniYlz+pCpRT5e+fmPm0mSD/vmND+0oMg=
+github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 h1:D7yb4kgNGVAiD5lFYqm/LW8d5jU66TXyYvSskDiW9yg=
+github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1/go.mod h1:UfW7/PZKon+iDEHtrHOfvMnS5GfYOW/SdMZ6P97rPEk=
+github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 h1:yxaHuDTtj2xxtsR8b+LJw8xDvyr6v/F6GP3InsP4wPI=
+github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/core/services/blockhashstore/delegate.go b/core/services/blockhashstore/delegate.go
index c8e55e47c3..1a84323b6f 100644
--- a/core/services/blockhashstore/delegate.go
+++ b/core/services/blockhashstore/delegate.go
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
v1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
diff --git a/core/services/blockheaderfeeder/delegate.go b/core/services/blockheaderfeeder/delegate.go
index 971a691d77..3de42d7a9e 100644
--- a/core/services/blockheaderfeeder/delegate.go
+++ b/core/services/blockheaderfeeder/delegate.go
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go
index 0d479b1f1a..29679ee92f 100644
--- a/core/services/chainlink/application.go
+++ b/core/services/chainlink/application.go
@@ -18,8 +18,8 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- relayservices "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ commonservices "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/build"
@@ -417,7 +417,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
globalLogger.Debug("Off-chain reporting v2 disabled")
}
- healthChecker := relayservices.NewChecker()
+ healthChecker := commonservices.NewChecker()
var lbs []utils.DependentAwaiter
for _, c := range legacyEVMChains.Slice() {
diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go
index fbadb379ca..891c0a490f 100644
--- a/core/services/chainlink/config_test.go
+++ b/core/services/chainlink/config_test.go
@@ -16,9 +16,9 @@ import (
ocrcommontypes "github.com/smartcontractkit/libocr/commontypes"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
@@ -145,7 +145,7 @@ var (
MaxMsgsPerBatch: ptr[int64](13),
},
Nodes: []*coscfg.Node{
- {Name: ptr("primary"), TendermintURL: relaycfg.MustParseURL("http://columbus.cosmos.com")},
+ {Name: ptr("primary"), TendermintURL: commoncfg.MustParseURL("http://columbus.cosmos.com")},
}},
{
ChainID: ptr("Malaga-420"),
@@ -153,7 +153,7 @@ var (
BlocksUntilTxTimeout: ptr[int64](20),
},
Nodes: []*coscfg.Node{
- {Name: ptr("secondary"), TendermintURL: relaycfg.MustParseURL("http://bombay.cosmos.com")},
+ {Name: ptr("secondary"), TendermintURL: commoncfg.MustParseURL("http://bombay.cosmos.com")},
}},
},
Solana: []*solana.TOMLConfig{
@@ -163,16 +163,16 @@ var (
MaxRetries: ptr[int64](12),
},
Nodes: []*solcfg.Node{
- {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://mainnet.solana.com")},
+ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://mainnet.solana.com")},
},
},
{
ChainID: ptr("testnet"),
Chain: solcfg.Chain{
- OCR2CachePollPeriod: relaycfg.MustNewDuration(time.Minute),
+ OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute),
},
Nodes: []*solcfg.Node{
- {Name: ptr("secondary"), URL: relaycfg.MustParseURL("http://testnet.solana.com")},
+ {Name: ptr("secondary"), URL: commoncfg.MustParseURL("http://testnet.solana.com")},
},
},
},
@@ -180,10 +180,10 @@ var (
{
ChainID: ptr("foobar"),
Chain: stkcfg.Chain{
- ConfirmationPoll: relaycfg.MustNewDuration(time.Hour),
+ ConfirmationPoll: commoncfg.MustNewDuration(time.Hour),
},
Nodes: []*stkcfg.Node{
- {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://stark.node")},
+ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://stark.node")},
},
},
},
@@ -538,7 +538,7 @@ func TestConfig_Marshal(t *testing.T) {
LogBackfillBatchSize: ptr[uint32](17),
LogPollInterval: &minute,
LogKeepBlocksDepth: ptr[uint32](100000),
- MinContractPayment: relayassets.NewLinkFromJuels(math.MaxInt64),
+ MinContractPayment: commonassets.NewLinkFromJuels(math.MaxInt64),
MinIncomingConfirmations: ptr[uint32](13),
NonceAutoSync: ptr(true),
NoNewHeadsThreshold: &minute,
@@ -603,13 +603,13 @@ func TestConfig_Marshal(t *testing.T) {
ChainID: ptr("mainnet"),
Enabled: ptr(false),
Chain: solcfg.Chain{
- BalancePollPeriod: relaycfg.MustNewDuration(time.Minute),
- ConfirmPollPeriod: relaycfg.MustNewDuration(time.Second),
- OCR2CachePollPeriod: relaycfg.MustNewDuration(time.Minute),
- OCR2CacheTTL: relaycfg.MustNewDuration(time.Hour),
- TxTimeout: relaycfg.MustNewDuration(time.Hour),
- TxRetryTimeout: relaycfg.MustNewDuration(time.Minute),
- TxConfirmTimeout: relaycfg.MustNewDuration(time.Second),
+ BalancePollPeriod: commoncfg.MustNewDuration(time.Minute),
+ ConfirmPollPeriod: commoncfg.MustNewDuration(time.Second),
+ OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute),
+ OCR2CacheTTL: commoncfg.MustNewDuration(time.Hour),
+ TxTimeout: commoncfg.MustNewDuration(time.Hour),
+ TxRetryTimeout: commoncfg.MustNewDuration(time.Minute),
+ TxConfirmTimeout: commoncfg.MustNewDuration(time.Second),
SkipPreflight: ptr(true),
Commitment: ptr("banana"),
MaxRetries: ptr[int64](7),
@@ -617,12 +617,12 @@ func TestConfig_Marshal(t *testing.T) {
ComputeUnitPriceMax: ptr[uint64](1000),
ComputeUnitPriceMin: ptr[uint64](10),
ComputeUnitPriceDefault: ptr[uint64](100),
- FeeBumpPeriod: relaycfg.MustNewDuration(time.Minute),
+ FeeBumpPeriod: commoncfg.MustNewDuration(time.Minute),
},
Nodes: []*solcfg.Node{
- {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://solana.web")},
- {Name: ptr("foo"), URL: relaycfg.MustParseURL("http://solana.foo")},
- {Name: ptr("bar"), URL: relaycfg.MustParseURL("http://solana.bar")},
+ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://solana.web")},
+ {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo")},
+ {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar")},
},
},
}
@@ -631,14 +631,14 @@ func TestConfig_Marshal(t *testing.T) {
ChainID: ptr("foobar"),
Enabled: ptr(true),
Chain: stkcfg.Chain{
- OCR2CachePollPeriod: relaycfg.MustNewDuration(6 * time.Hour),
- OCR2CacheTTL: relaycfg.MustNewDuration(3 * time.Minute),
- RequestTimeout: relaycfg.MustNewDuration(time.Minute + 3*time.Second),
- TxTimeout: relaycfg.MustNewDuration(13 * time.Second),
- ConfirmationPoll: relaycfg.MustNewDuration(42 * time.Second),
+ OCR2CachePollPeriod: commoncfg.MustNewDuration(6 * time.Hour),
+ OCR2CacheTTL: commoncfg.MustNewDuration(3 * time.Minute),
+ RequestTimeout: commoncfg.MustNewDuration(time.Minute + 3*time.Second),
+ TxTimeout: commoncfg.MustNewDuration(13 * time.Second),
+ ConfirmationPoll: commoncfg.MustNewDuration(42 * time.Second),
},
Nodes: []*stkcfg.Node{
- {Name: ptr("primary"), URL: relaycfg.MustParseURL("http://stark.node")},
+ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://stark.node")},
},
},
}
@@ -648,21 +648,21 @@ func TestConfig_Marshal(t *testing.T) {
Enabled: ptr(true),
Chain: coscfg.Chain{
Bech32Prefix: ptr("wasm"),
- BlockRate: relaycfg.MustNewDuration(time.Minute),
+ BlockRate: commoncfg.MustNewDuration(time.Minute),
BlocksUntilTxTimeout: ptr[int64](12),
- ConfirmPollPeriod: relaycfg.MustNewDuration(time.Second),
+ ConfirmPollPeriod: commoncfg.MustNewDuration(time.Second),
FallbackGasPrice: mustDecimal("0.001"),
GasToken: ptr("ucosm"),
GasLimitMultiplier: mustDecimal("1.2"),
MaxMsgsPerBatch: ptr[int64](17),
- OCR2CachePollPeriod: relaycfg.MustNewDuration(time.Minute),
- OCR2CacheTTL: relaycfg.MustNewDuration(time.Hour),
- TxMsgTimeout: relaycfg.MustNewDuration(time.Second),
+ OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute),
+ OCR2CacheTTL: commoncfg.MustNewDuration(time.Hour),
+ TxMsgTimeout: commoncfg.MustNewDuration(time.Second),
},
Nodes: []*coscfg.Node{
- {Name: ptr("primary"), TendermintURL: relaycfg.MustParseURL("http://tender.mint")},
- {Name: ptr("foo"), TendermintURL: relaycfg.MustParseURL("http://foo.url")},
- {Name: ptr("bar"), TendermintURL: relaycfg.MustParseURL("http://bar.web")},
+ {Name: ptr("primary"), TendermintURL: commoncfg.MustParseURL("http://tender.mint")},
+ {Name: ptr("foo"), TendermintURL: commoncfg.MustParseURL("http://foo.url")},
+ {Name: ptr("bar"), TendermintURL: commoncfg.MustParseURL("http://bar.web")},
},
},
}
diff --git a/core/services/chainlink/mocks/relayer_chain_interoperators.go b/core/services/chainlink/mocks/relayer_chain_interoperators.go
index 81f112f766..f778f61b0c 100644
--- a/core/services/chainlink/mocks/relayer_chain_interoperators.go
+++ b/core/services/chainlink/mocks/relayer_chain_interoperators.go
@@ -9,11 +9,11 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// FakeRelayerChainInteroperators is a fake chainlink.RelayerChainInteroperators.
diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go
index 1183277ac0..3be1395694 100644
--- a/core/services/chainlink/relayer_chain_interoperators.go
+++ b/core/services/chainlink/relayer_chain_interoperators.go
@@ -7,10 +7,10 @@ import (
"sort"
"sync"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go
index 293cc298c8..da1246c7bf 100644
--- a/core/services/chainlink/relayer_chain_interoperators_test.go
+++ b/core/services/chainlink/relayer_chain_interoperators_test.go
@@ -9,9 +9,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
@@ -84,7 +84,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Chain: solcfg.Chain{},
Nodes: []*solcfg.Node{{
Name: ptr("solana chain 1 node 1"),
- URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8547").URL())),
+ URL: ((*commoncfg.URL)(models.MustParseURL("http://localhost:8547").URL())),
}},
},
&solana.TOMLConfig{
@@ -93,7 +93,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Chain: solcfg.Chain{},
Nodes: []*solcfg.Node{{
Name: ptr("solana chain 2 node 1"),
- URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8527").URL())),
+ URL: ((*commoncfg.URL)(models.MustParseURL("http://localhost:8527").URL())),
}},
},
}
@@ -106,15 +106,15 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: []*stkcfg.Node{
{
Name: ptr("starknet chain 1 node 1"),
- URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8547").URL())),
+ URL: ((*commoncfg.URL)(models.MustParseURL("http://localhost:8547").URL())),
},
{
Name: ptr("starknet chain 1 node 2"),
- URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8548").URL())),
+ URL: ((*commoncfg.URL)(models.MustParseURL("http://localhost:8548").URL())),
},
{
Name: ptr("starknet chain 1 node 3"),
- URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:8549").URL())),
+ URL: ((*commoncfg.URL)(models.MustParseURL("http://localhost:8549").URL())),
},
},
},
@@ -125,7 +125,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: []*stkcfg.Node{
{
Name: ptr("starknet chain 2 node 1"),
- URL: ((*relaycfg.URL)(models.MustParseURL("http://localhost:3547").URL())),
+ URL: ((*commoncfg.URL)(models.MustParseURL("http://localhost:3547").URL())),
},
},
},
@@ -143,7 +143,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: coscfg.Nodes{
&coscfg.Node{
Name: ptr("cosmos chain 1 node 1"),
- TendermintURL: (*relaycfg.URL)(models.MustParseURL("http://localhost:9548").URL()),
+ TendermintURL: (*commoncfg.URL)(models.MustParseURL("http://localhost:9548").URL()),
},
},
},
@@ -158,7 +158,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
Nodes: coscfg.Nodes{
&coscfg.Node{
Name: ptr("cosmos chain 2 node 1"),
- TendermintURL: (*relaycfg.URL)(models.MustParseURL("http://localhost:9598").URL()),
+ TendermintURL: (*commoncfg.URL)(models.MustParseURL("http://localhost:9598").URL()),
},
},
},
diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go
index 4bbabea4c8..6376839c70 100644
--- a/core/services/chainlink/relayer_factory.go
+++ b/core/services/chainlink/relayer_factory.go
@@ -9,9 +9,9 @@ import (
"github.com/jmoiron/sqlx"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
pkgsolana "github.com/smartcontractkit/chainlink-solana/pkg/solana"
pkgstarknet "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink"
diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go
index 10943308b3..9da84fd3ee 100644
--- a/core/services/directrequest/delegate.go
+++ b/core/services/directrequest/delegate.go
@@ -9,8 +9,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go
index 1c7929d94d..56c28e5745 100644
--- a/core/services/directrequest/delegate_test.go
+++ b/core/services/directrequest/delegate_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
diff --git a/core/services/directrequest/validate.go b/core/services/directrequest/validate.go
index cdb478e8aa..bc31f09b68 100644
--- a/core/services/directrequest/validate.go
+++ b/core/services/directrequest/validate.go
@@ -4,7 +4,7 @@ import (
"github.com/pelletier/go-toml"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go
index f6e8952d6b..da19a33abc 100644
--- a/core/services/feeds/service.go
+++ b/core/services/feeds/service.go
@@ -17,7 +17,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/fluxmonitorv2/config.go b/core/services/fluxmonitorv2/config.go
index 0360e9ce03..2680f30a77 100644
--- a/core/services/fluxmonitorv2/config.go
+++ b/core/services/fluxmonitorv2/config.go
@@ -3,7 +3,7 @@ package fluxmonitorv2
import (
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go
index 5dbeaeafc3..ea853d879d 100644
--- a/core/services/fluxmonitorv2/flux_monitor.go
+++ b/core/services/fluxmonitorv2/flux_monitor.go
@@ -15,7 +15,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go
index e8bbf739bb..1a14fb8bd0 100644
--- a/core/services/fluxmonitorv2/flux_monitor_test.go
+++ b/core/services/fluxmonitorv2/flux_monitor_test.go
@@ -20,7 +20,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks"
diff --git a/core/services/fluxmonitorv2/payment_checker.go b/core/services/fluxmonitorv2/payment_checker.go
index b5dbd73c06..e4cc40c96a 100644
--- a/core/services/fluxmonitorv2/payment_checker.go
+++ b/core/services/fluxmonitorv2/payment_checker.go
@@ -3,7 +3,7 @@ package fluxmonitorv2
import (
"math/big"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
)
// MinFundedRounds defines the minimum number of rounds that needs to be paid
diff --git a/core/services/fluxmonitorv2/payment_checker_test.go b/core/services/fluxmonitorv2/payment_checker_test.go
index 48a06553cb..baec564233 100644
--- a/core/services/fluxmonitorv2/payment_checker_test.go
+++ b/core/services/fluxmonitorv2/payment_checker_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2"
)
diff --git a/core/services/fluxmonitorv2/validate_test.go b/core/services/fluxmonitorv2/validate_test.go
index b397e6d374..94dc8b6b70 100644
--- a/core/services/fluxmonitorv2/validate_test.go
+++ b/core/services/fluxmonitorv2/validate_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils/tomlutils"
diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go
index 5b67e333d2..343980afdd 100644
--- a/core/services/functions/connector_handler.go
+++ b/core/services/functions/connector_handler.go
@@ -10,8 +10,8 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/functions/connector_handler_test.go b/core/services/functions/connector_handler_test.go
index 1bf9f8e593..82c3dab3af 100644
--- a/core/services/functions/connector_handler_test.go
+++ b/core/services/functions/connector_handler_test.go
@@ -7,7 +7,7 @@ import (
"math/big"
"testing"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/functions"
diff --git a/core/services/functions/listener.go b/core/services/functions/listener.go
index efb40330cb..3a30843180 100644
--- a/core/services/functions/listener.go
+++ b/core/services/functions/listener.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/cbor"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/gateway/connectionmanager.go b/core/services/gateway/connectionmanager.go
index 278c4beaaa..ce4a54f4c2 100644
--- a/core/services/gateway/connectionmanager.go
+++ b/core/services/gateway/connectionmanager.go
@@ -15,7 +15,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go
index 5578681944..0694e9ad15 100644
--- a/core/services/gateway/connector/connector.go
+++ b/core/services/gateway/connector/connector.go
@@ -10,7 +10,7 @@ import (
"github.com/gorilla/websocket"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/gateway/gateway.go b/core/services/gateway/gateway.go
index 42e03107f3..79ddf0a5c6 100644
--- a/core/services/gateway/gateway.go
+++ b/core/services/gateway/gateway.go
@@ -13,7 +13,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/config"
diff --git a/core/services/gateway/handlers/functions/allowlist.go b/core/services/gateway/handlers/functions/allowlist.go
index 914a933eb1..3ba9a65d57 100644
--- a/core/services/gateway/handlers/functions/allowlist.go
+++ b/core/services/gateway/handlers/functions/allowlist.go
@@ -13,7 +13,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_allow_list"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router"
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index a4301ef7e9..32a132c075 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -13,8 +13,8 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/gateway/handlers/functions/handler.functions_test.go b/core/services/gateway/handlers/functions/handler.functions_test.go
index 4c8ba5bec3..00334d3068 100644
--- a/core/services/gateway/handlers/functions/handler.functions_test.go
+++ b/core/services/gateway/handlers/functions/handler.functions_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/api"
diff --git a/core/services/gateway/handlers/functions/subscriptions.go b/core/services/gateway/handlers/functions/subscriptions.go
index c7a6519e69..7a59e05731 100644
--- a/core/services/gateway/handlers/functions/subscriptions.go
+++ b/core/services/gateway/handlers/functions/subscriptions.go
@@ -11,7 +11,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/gateway/network/httpserver.go b/core/services/gateway/network/httpserver.go
index 3cae8dc276..d4340a92e9 100644
--- a/core/services/gateway/network/httpserver.go
+++ b/core/services/gateway/network/httpserver.go
@@ -8,7 +8,7 @@ import (
"net/http"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
)
diff --git a/core/services/gateway/network/wsconnection.go b/core/services/gateway/network/wsconnection.go
index 9215d183d1..813b644282 100644
--- a/core/services/gateway/network/wsconnection.go
+++ b/core/services/gateway/network/wsconnection.go
@@ -5,7 +5,7 @@ import (
"errors"
"sync/atomic"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/gorilla/websocket"
diff --git a/core/services/gateway/network/wsserver.go b/core/services/gateway/network/wsserver.go
index 86812a313e..58b2dfe663 100644
--- a/core/services/gateway/network/wsserver.go
+++ b/core/services/gateway/network/wsserver.go
@@ -10,7 +10,7 @@ import (
"github.com/gorilla/websocket"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
)
diff --git a/core/services/health.go b/core/services/health.go
index 568823fa32..32e97fd8db 100644
--- a/core/services/health.go
+++ b/core/services/health.go
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index c2fc425918..87ee15873d 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
diff --git a/core/services/job/models.go b/core/services/job/models.go
index 0b3e622f59..05dcab831f 100644
--- a/core/services/job/models.go
+++ b/core/services/job/models.go
@@ -14,8 +14,8 @@ import (
"github.com/pkg/errors"
"gopkg.in/guregu/null.v4"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
@@ -434,7 +434,7 @@ type DirectRequestSpec struct {
ContractAddress ethkey.EIP55Address `toml:"contractAddress"`
MinIncomingConfirmations clnull.Uint32 `toml:"minIncomingConfirmations"`
Requesters models.AddressCollection `toml:"requesters"`
- MinContractPayment *relayassets.Link `toml:"minContractPaymentLinkJuels"`
+ MinContractPayment *commonassets.Link `toml:"minContractPaymentLinkJuels"`
EVMChainID *utils.Big `toml:"evmChainID"`
CreatedAt time.Time `toml:"-"`
UpdatedAt time.Time `toml:"-"`
@@ -475,7 +475,7 @@ type FluxMonitorSpec struct {
DrumbeatSchedule string
DrumbeatRandomDelay time.Duration
DrumbeatEnabled bool
- MinPayment *relayassets.Link
+ MinPayment *commonassets.Link
EVMChainID *utils.Big `toml:"evmChainID"`
CreatedAt time.Time `toml:"-"`
UpdatedAt time.Time `toml:"-"`
diff --git a/core/services/job/orm.go b/core/services/job/orm.go
index fb897bc928..ba102c6bb8 100644
--- a/core/services/job/orm.go
+++ b/core/services/job/orm.go
@@ -18,7 +18,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go
index 03ee8cee13..5656011e14 100644
--- a/core/services/job/spawner.go
+++ b/core/services/job/spawner.go
@@ -11,7 +11,7 @@ import (
"github.com/jmoiron/sqlx"
- relayservices "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ commonservices "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services"
@@ -43,7 +43,7 @@ type (
}
spawner struct {
- relayservices.StateMachine
+ commonservices.StateMachine
orm ORM
config Config
checker services.Checker
@@ -170,7 +170,7 @@ func (js *spawner) stopService(jobID int32) {
for i := len(aj.services) - 1; i >= 0; i-- {
service := aj.services[i]
sLggr := lggr.With("subservice", i, "serviceType", reflect.TypeOf(service))
- if c, ok := service.(relayservices.HealthReporter); ok {
+ if c, ok := service.(commonservices.HealthReporter); ok {
if err := js.checker.Unregister(c.Name()); err != nil {
sLggr.Warnw("Failed to unregister service from health checker", "err", err)
}
@@ -230,7 +230,7 @@ func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) e
lggr.Criticalw("Error starting service for job", "err", err)
return err
}
- if c, ok := srv.(relayservices.HealthReporter); ok {
+ if c, ok := srv.(commonservices.HealthReporter); ok {
err = js.checker.Register(c)
if err != nil {
lggr.Errorw("Error registering service with health checker", "err", err)
diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go
index cfe646d866..0ad7649143 100644
--- a/core/services/job/spawner_test.go
+++ b/core/services/job/spawner_test.go
@@ -11,8 +11,8 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
diff --git a/core/services/keeper/registry_synchronizer_core.go b/core/services/keeper/registry_synchronizer_core.go
index 761958ce19..db7cca1763 100644
--- a/core/services/keeper/registry_synchronizer_core.go
+++ b/core/services/keeper/registry_synchronizer_core.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go
index 30e9f36357..ece6f85b06 100644
--- a/core/services/keeper/upkeep_executer.go
+++ b/core/services/keeper/upkeep_executer.go
@@ -12,7 +12,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
diff --git a/core/services/keystore/cosmos.go b/core/services/keystore/cosmos.go
index c06dfcdbce..e3549fdb93 100644
--- a/core/services/keystore/cosmos.go
+++ b/core/services/keystore/cosmos.go
@@ -6,7 +6,7 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
)
@@ -147,7 +147,7 @@ func (ks *cosmos) getByID(id string) (cosmoskey.Key, error) {
return key, nil
}
-// CosmosLoopKeystore implements the [github.com/smartcontractkit/chainlink-relay/pkg/loop.Keystore] interface and
+// CosmosLoopKeystore implements the [github.com/smartcontractkit/chainlink-common/pkg/loop.Keystore] interface and
// handles signing for Cosmos messages.
type CosmosLoopKeystore struct {
Cosmos
diff --git a/core/services/keystore/keys/ethkey/address.go b/core/services/keystore/keys/ethkey/address.go
index c14b602c59..1b26413f63 100644
--- a/core/services/keystore/keys/ethkey/address.go
+++ b/core/services/keystore/keys/ethkey/address.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils/bytes"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes"
)
// EIP55Address is a new type for string which persists an ethereum address in
diff --git a/core/services/keystore/starknet.go b/core/services/keystore/starknet.go
index 7bf454004d..251c74d0e0 100644
--- a/core/services/keystore/starknet.go
+++ b/core/services/keystore/starknet.go
@@ -9,8 +9,8 @@ import (
"github.com/smartcontractkit/caigo"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- adapters "github.com/smartcontractkit/chainlink-relay/pkg/loop/adapters/starknet"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ adapters "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/starknet"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey"
)
@@ -155,7 +155,7 @@ func (ks *starknet) getByID(id string) (starkkey.Key, error) {
return key, nil
}
-// StarknetLooppSigner implements [github.com/smartcontractkit/chainlink-relay/pkg/loop.Keystore] interface and the requirements
+// StarknetLooppSigner implements [github.com/smartcontractkit/chainlink-common/pkg/loop.Keystore] interface and the requirements
// of signature d/encoding of the [github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/txm.NewKeystoreAdapter]
type StarknetLooppSigner struct {
StarkNet
@@ -165,7 +165,7 @@ var _ loop.Keystore = &StarknetLooppSigner{}
// Sign implements [loop.Keystore]
// hash is expected to be the byte representation of big.Int
-// the returned []byte is an encoded [github.com/smartcontractkit/chainlink-relay/pkg/loop/adapters/starknet.Signature].
+// the returned []byte is an encoded [github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/starknet.Signature].
// this enables compatibility with [github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/txm.NewKeystoreAdapter]
func (lk *StarknetLooppSigner) Sign(ctx context.Context, id string, hash []byte) ([]byte, error) {
diff --git a/core/services/mocks/checker.go b/core/services/mocks/checker.go
index 354812d021..e0c209d8af 100644
--- a/core/services/mocks/checker.go
+++ b/core/services/mocks/checker.go
@@ -3,7 +3,7 @@
package mocks
import (
- pkgservices "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ pkgservices "github.com/smartcontractkit/chainlink-common/pkg/services"
mock "github.com/stretchr/testify/mock"
)
diff --git a/core/services/multi.go b/core/services/multi.go
index 4ea263f5a3..1e465d5e72 100644
--- a/core/services/multi.go
+++ b/core/services/multi.go
@@ -3,7 +3,7 @@ package services
import (
"io"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
// StartClose is a subset of the ServiceCtx interface.
diff --git a/core/services/nurse.go b/core/services/nurse.go
index e414ca280e..3d896a80ff 100644
--- a/core/services/nurse.go
+++ b/core/services/nurse.go
@@ -17,7 +17,7 @@ import (
"github.com/google/pprof/profile"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/services/ocr/config_overrider.go b/core/services/ocr/config_overrider.go
index 5b2ac20c00..b1acf9a7d7 100644
--- a/core/services/ocr/config_overrider.go
+++ b/core/services/ocr/config_overrider.go
@@ -12,7 +12,7 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index 3e614fef4a..5fecbe8628 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -20,7 +20,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting/confighelper"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/config"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go
index 0559469abb..c8de3ec33c 100644
--- a/core/services/ocr/delegate.go
+++ b/core/services/ocr/delegate.go
@@ -11,7 +11,7 @@ import (
"github.com/jmoiron/sqlx"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator"
ocrnetworking "github.com/smartcontractkit/libocr/networking"
@@ -167,7 +167,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) (services []job.ServiceCtx, err e
v2Bootstrappers = peerWrapper.P2PConfig().V2().DefaultBootstrappers()
}
- ocrLogger := relaylogger.NewOCRWrapper(lggr, chain.Config().OCR().TraceLogging(), func(msg string) {
+ ocrLogger := commonlogger.NewOCRWrapper(lggr, chain.Config().OCR().TraceLogging(), func(msg string) {
d.jobORM.TryRecordError(jb.ID, msg)
})
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 944c04c8d4..4b5932cd70 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -15,6 +15,7 @@ import (
"github.com/pkg/errors"
"github.com/jmoiron/sqlx"
+
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
@@ -29,10 +30,10 @@ import (
dkgpkg "github.com/smartcontractkit/ocr2vrf/dkg"
"github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop/reportingplugins"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -387,7 +388,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) {
return nil, errors.New("peerWrapper is not started. OCR2 jobs require a started and running p2p v2 peer")
}
- ocrLogger := relaylogger.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(msg string) {
+ ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(msg string) {
lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error")
})
@@ -958,11 +959,11 @@ func (d *Delegate) newServicesOCR2VRF(
"jobName", jb.Name.ValueOrZero(),
"jobID", jb.ID,
)
- vrfLogger := relaylogger.NewOCRWrapper(l.With(
+ 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")
})
- dkgLogger := relaylogger.NewOCRWrapper(l.With(
+ 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")
})
diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go
index daffac3f96..b55e128119 100644
--- a/core/services/ocr2/delegate_test.go
+++ b/core/services/ocr2/delegate_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
diff --git a/core/services/ocr2/plugins/functions/config/config.go b/core/services/ocr2/plugins/functions/config/config.go
index a179a22ce4..13e0204250 100644
--- a/core/services/ocr2/plugins/functions/config/config.go
+++ b/core/services/ocr2/plugins/functions/config/config.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions"
diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go
index 14d7415cab..475cf0a2af 100644
--- a/core/services/ocr2/plugins/functions/plugin.go
+++ b/core/services/ocr2/plugins/functions/plugin.go
@@ -13,7 +13,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/functions/plugin_test.go b/core/services/ocr2/plugins/functions/plugin_test.go
index eea751789a..453d4b67aa 100644
--- a/core/services/ocr2/plugins/functions/plugin_test.go
+++ b/core/services/ocr2/plugins/functions/plugin_test.go
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector"
hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
diff --git a/core/services/ocr2/plugins/functions/reporting_test.go b/core/services/ocr2/plugins/functions/reporting_test.go
index 860492bfc5..5b9f59ccb2 100644
--- a/core/services/ocr2/plugins/functions/reporting_test.go
+++ b/core/services/ocr2/plugins/functions/reporting_test.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
functions_srv "github.com/smartcontractkit/chainlink/v2/core/services/functions"
@@ -24,7 +24,7 @@ import (
func preparePlugin(t *testing.T, batchSize uint32, maxTotalGasLimit uint32) (types.ReportingPlugin, *functions_mocks.ORM, encoding.ReportCodec, *functions_mocks.OffchainTransmitter) {
lggr := logger.TestLogger(t)
- ocrLogger := relaylogger.NewOCRWrapper(lggr, true, func(msg string) {})
+ ocrLogger := commonlogger.NewOCRWrapper(lggr, true, func(msg string) {})
orm := functions_mocks.NewORM(t)
offchainTransmitter := functions_mocks.NewOffchainTransmitter(t)
factory := functions.FunctionsReportingPluginFactory{
diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
index def33114e8..872f83d3c3 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter.go
@@ -4,7 +4,7 @@ import (
"context"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
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 ef0e7421b5..f70e0dd443 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
_ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter.go b/core/services/ocr2/plugins/generic/telemetry_adapter.go
index 51d94f5cfe..a2ec6ba20c 100644
--- a/core/services/ocr2/plugins/generic/telemetry_adapter.go
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization"
"github.com/smartcontractkit/chainlink/v2/core/services/telemetry"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
var _ types.TelemetryService = (*TelemetryAdapter)(nil)
diff --git a/core/services/ocr2/plugins/median/plugin.go b/core/services/ocr2/plugins/median/plugin.go
index f8517386b3..4f83c4b5dd 100644
--- a/core/services/ocr2/plugins/median/plugin.go
+++ b/core/services/ocr2/plugins/median/plugin.go
@@ -6,10 +6,10 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/services/ocr2/plugins/median/services.go b/core/services/ocr2/plugins/median/services.go
index 8d121083f3..9d65921ef2 100644
--- a/core/services/ocr2/plugins/median/services.go
+++ b/core/services/ocr2/plugins/median/services.go
@@ -9,8 +9,8 @@ import (
libocr "github.com/smartcontractkit/libocr/offchainreporting2plus"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/config/env"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/mercury/integration_test.go b/core/services/ocr2/plugins/mercury/integration_test.go
index ae2b4ca974..e8adb55b39 100644
--- a/core/services/ocr2/plugins/mercury/integration_test.go
+++ b/core/services/ocr2/plugins/mercury/integration_test.go
@@ -34,10 +34,10 @@ import (
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/wsrpc/credentials"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaycodecv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- relaycodecv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
- relaycodecv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaycodecv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
+ relaycodecv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
+ relaycodecv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
diff --git a/core/services/ocr2/plugins/mercury/plugin.go b/core/services/ocr2/plugins/mercury/plugin.go
index ddef1374a4..bd68ccd8b7 100644
--- a/core/services/ocr2/plugins/mercury/plugin.go
+++ b/core/services/ocr2/plugins/mercury/plugin.go
@@ -7,10 +7,10 @@ import (
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
- relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
- relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ relaymercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -30,7 +30,7 @@ type Config interface {
func NewServices(
jb job.Job,
- ocr2Provider relaytypes.MercuryProvider,
+ ocr2Provider commontypes.MercuryProvider,
pipelineRunner pipeline.Runner,
runResults chan *pipeline.Run,
lggr logger.Logger,
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
index 4044bb5f2a..d8941d505b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
@@ -15,7 +15,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
"github.com/smartcontractkit/ocr2keepers/pkg/v2/encoding"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
index 2d49a91e98..7fe4087cfa 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
@@ -19,7 +19,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
index 6cc19a4d02..ae407b0ea9 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
@@ -11,7 +11,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
index 349db2902b..d3f069a9bf 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
@@ -18,7 +18,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
index d6e7ad51d1..c656656815 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/ocr2keepers/pkg/v3/random"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
index b83aca8a02..d34787f501 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
@@ -17,7 +17,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
index 8f84ca1495..000d40f407 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
@@ -10,7 +10,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
index 6c5f767bd3..f5e3969bc7 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
@@ -10,7 +10,7 @@ import (
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
index f4fbf24f41..109a644ca0 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
@@ -18,7 +18,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/hashicorp/consul/sdk/freeport"
"github.com/onsi/gomega"
@@ -34,10 +34,9 @@ import (
ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
-
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
automationForwarderLogic "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_forwarder_logic"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/basic_upkeep_contract"
@@ -67,7 +66,7 @@ func TestFilterNamesFromSpec21(t *testing.T) {
address := common.HexToAddress(hexutil.Encode(b))
spec := &job.OCR2OracleSpec{
- PluginType: relaytypes.OCR2Keeper,
+ PluginType: types.OCR2Keeper,
ContractID: address.String(), // valid contract addr
}
@@ -79,7 +78,7 @@ func TestFilterNamesFromSpec21(t *testing.T) {
assert.Equal(t, logpoller.FilterName("KeeperRegistry Events", address), names[1])
spec = &job.OCR2OracleSpec{
- PluginType: relaytypes.OCR2Keeper,
+ PluginType: types.OCR2Keeper,
ContractID: "0x5431", // invalid contract addr
}
_, err = ocr2keeper.FilterNamesFromSpec21(spec)
@@ -723,7 +722,7 @@ func deployKeeper21Registry(
return registryMaster
}
-func getUpkeepIdFromTx21(t *testing.T, registry *iregistry21.IKeeperRegistryMaster, registrationTx *types.Transaction, backend *backends.SimulatedBackend) *big.Int {
+func getUpkeepIdFromTx21(t *testing.T, registry *iregistry21.IKeeperRegistryMaster, registrationTx *gethtypes.Transaction, backend *backends.SimulatedBackend) *big.Int {
receipt, err := backend.TransactionReceipt(testutils.Context(t), registrationTx.Hash())
require.NoError(t, err)
parsedLog, err := registry.ParseUpkeepRegistered(*receipt.Logs[0])
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
index 569dc20753..a2184d92ae 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
@@ -19,7 +19,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/hashicorp/consul/sdk/freeport"
"github.com/onsi/gomega"
@@ -62,7 +62,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
const (
@@ -196,7 +196,7 @@ func accountsToAddress(accounts []ocrTypes.Account) (addresses []common.Address,
return addresses, nil
}
-func getUpkeepIdFromTx(t *testing.T, registry *keeper_registry_wrapper2_0.KeeperRegistry, registrationTx *types.Transaction, backend *backends.SimulatedBackend) *big.Int {
+func getUpkeepIdFromTx(t *testing.T, registry *keeper_registry_wrapper2_0.KeeperRegistry, registrationTx *gethtypes.Transaction, backend *backends.SimulatedBackend) *big.Int {
receipt, err := backend.TransactionReceipt(testutils.Context(t), registrationTx.Hash())
require.NoError(t, err)
parsedLog, err := registry.ParseUpkeepRegistered(*receipt.Logs[0])
@@ -714,7 +714,7 @@ func TestFilterNamesFromSpec20(t *testing.T) {
address := common.HexToAddress(hexutil.Encode(b))
spec := &job.OCR2OracleSpec{
- PluginType: relaytypes.OCR2Keeper,
+ PluginType: types.OCR2Keeper,
ContractID: address.String(), // valid contract addr
}
@@ -726,7 +726,7 @@ func TestFilterNamesFromSpec20(t *testing.T) {
assert.Equal(t, logpoller.FilterName("EvmRegistry - Upkeep events for", address), names[1])
spec = &job.OCR2OracleSpec{
- PluginType: relaytypes.OCR2Keeper,
+ PluginType: types.OCR2Keeper,
ContractID: "0x5431", // invalid contract addr
}
_, err = ocr2keeper.FilterNamesFromSpec20(spec)
diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go
index fca98d8700..504b6267c6 100644
--- a/core/services/ocr2/plugins/ocr2keeper/util.go
+++ b/core/services/ocr2/plugins/ocr2keeper/util.go
@@ -4,13 +4,14 @@ import (
"fmt"
"github.com/jmoiron/sqlx"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
ocr2keepers20 "github.com/smartcontractkit/ocr2keepers/pkg/v2"
ocr2keepers20coordinator "github.com/smartcontractkit/ocr2keepers/pkg/v2/coordinator"
ocr2keepers20polling "github.com/smartcontractkit/ocr2keepers/pkg/v2/observer/polling"
ocr2keepers20runner "github.com/smartcontractkit/ocr2keepers/pkg/v2/runner"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
ocr2keepers21 "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
index dc489b4958..f634ee0c01 100644
--- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
@@ -12,7 +12,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"
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
@@ -25,7 +25,7 @@ import (
"github.com/smartcontractkit/ocr2vrf/ocr2vrf"
ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -1469,7 +1469,7 @@ func newRandomnessRequestedLog(
SubID: big.NewInt(1),
CostJuels: big.NewInt(50_000),
NewSubBalance: big.NewInt(100_000),
- Raw: types.Log{
+ Raw: gethtypes.Log{
BlockNumber: requestBlock,
},
}
@@ -1544,7 +1544,7 @@ func newRandomnessFulfillmentRequestedLog(
Requester: common.HexToAddress("0x1234567890"),
CostJuels: big.NewInt(50_000),
NewSubBalance: big.NewInt(100_000),
- Raw: types.Log{
+ Raw: gethtypes.Log{
BlockNumber: requestBlock,
},
}
@@ -1763,7 +1763,7 @@ func TestFilterNamesFromSpec(t *testing.T) {
spec := &job.OCR2OracleSpec{
ContractID: beaconAddress.String(),
- PluginType: relaytypes.OCR2VRF,
+ PluginType: types.OCR2VRF,
PluginConfig: job.JSONConfig{
"VRFCoordinatorAddress": coordinatorAddress.String(),
"DKGContractAddress": dkgAddress.String(),
@@ -1777,7 +1777,7 @@ func TestFilterNamesFromSpec(t *testing.T) {
assert.Equal(t, logpoller.FilterName("VRF Coordinator", beaconAddress, coordinatorAddress, dkgAddress), names[0])
spec = &job.OCR2OracleSpec{
- PluginType: relaytypes.OCR2VRF,
+ PluginType: types.OCR2VRF,
ContractID: beaconAddress.String(),
PluginConfig: nil, // missing coordinator & dkg addresses
}
diff --git a/core/services/ocr2/plugins/s4/factory_test.go b/core/services/ocr2/plugins/s4/factory_test.go
index 1b75988d83..13a36a5382 100644
--- a/core/services/ocr2/plugins/s4/factory_test.go
+++ b/core/services/ocr2/plugins/s4/factory_test.go
@@ -8,7 +8,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/s4"
s4_mocks "github.com/smartcontractkit/chainlink/v2/core/services/s4/mocks"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/libocr/offchainreporting2/types"
@@ -18,7 +18,7 @@ import (
func TestS4ReportingPluginFactory_NewReportingPlugin(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
orm := s4_mocks.NewORM(t)
f := s4.S4ReportingPluginFactory{
diff --git a/core/services/ocr2/plugins/s4/integration_test.go b/core/services/ocr2/plugins/s4/integration_test.go
index 98ccd312e4..54f0f02ad9 100644
--- a/core/services/ocr2/plugins/s4/integration_test.go
+++ b/core/services/ocr2/plugins/s4/integration_test.go
@@ -18,7 +18,7 @@ import (
s4_svc "github.com/smartcontractkit/chainlink/v2/core/services/s4"
"github.com/smartcontractkit/chainlink/v2/core/utils"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2/types"
@@ -56,7 +56,7 @@ func newDON(t *testing.T, size int, config *s4.PluginConfig) *don {
orm := s4_svc.NewPostgresORM(db, logger, pgtest.NewQConfig(false), s4_svc.SharedTableName, ns)
orms[i] = orm
- ocrLogger := relaylogger.NewOCRWrapper(logger, true, func(msg string) {})
+ ocrLogger := commonlogger.NewOCRWrapper(logger, true, func(msg string) {})
plugin, err := s4.NewReportingPlugin(ocrLogger, config, orm)
require.NoError(t, err)
plugins[i] = plugin
diff --git a/core/services/ocr2/plugins/s4/plugin_test.go b/core/services/ocr2/plugins/s4/plugin_test.go
index 94c876a4f7..e2b5d21b84 100644
--- a/core/services/ocr2/plugins/s4/plugin_test.go
+++ b/core/services/ocr2/plugins/s4/plugin_test.go
@@ -13,13 +13,14 @@ import (
s4_mocks "github.com/smartcontractkit/chainlink/v2/core/services/s4/mocks"
"github.com/smartcontractkit/chainlink/v2/core/utils"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/protobuf/proto"
+
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
)
func createPluginConfig(maxEntries uint) *s4.PluginConfig {
@@ -121,7 +122,7 @@ func rowsToShapshotRows(rows []*s4_svc.Row) []*s4_svc.SnapshotRow {
func TestPlugin_NewReportingPlugin(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
orm := s4_mocks.NewORM(t)
t.Run("ErrInvalidIntervals", func(t *testing.T) {
@@ -167,7 +168,7 @@ func TestPlugin_NewReportingPlugin(t *testing.T) {
func TestPlugin_Close(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
config := createPluginConfig(10)
orm := s4_mocks.NewORM(t)
plugin, err := s4.NewReportingPlugin(logger, config, orm)
@@ -180,7 +181,7 @@ func TestPlugin_Close(t *testing.T) {
func TestPlugin_ShouldTransmitAcceptedReport(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
config := createPluginConfig(10)
orm := s4_mocks.NewORM(t)
plugin, err := s4.NewReportingPlugin(logger, config, orm)
@@ -194,7 +195,7 @@ func TestPlugin_ShouldTransmitAcceptedReport(t *testing.T) {
func TestPlugin_ShouldAcceptFinalizedReport(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
config := createPluginConfig(10)
orm := s4_mocks.NewORM(t)
plugin, err := s4.NewReportingPlugin(logger, config, orm)
@@ -255,7 +256,7 @@ func TestPlugin_ShouldAcceptFinalizedReport(t *testing.T) {
func TestPlugin_Query(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
config := createPluginConfig(10)
orm := s4_mocks.NewORM(t)
plugin, err := s4.NewReportingPlugin(logger, config, orm)
@@ -332,7 +333,7 @@ func TestPlugin_Query(t *testing.T) {
func TestPlugin_Observation(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
config := createPluginConfig(10)
orm := s4_mocks.NewORM(t)
plugin, err := s4.NewReportingPlugin(logger, config, orm)
@@ -465,7 +466,7 @@ func TestPlugin_Observation(t *testing.T) {
func TestPlugin_Report(t *testing.T) {
t.Parallel()
- logger := relaylogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
+ logger := commonlogger.NewOCRWrapper(logger.TestLogger(t), true, func(msg string) {})
config := createPluginConfig(10)
orm := s4_mocks.NewORM(t)
plugin, err := s4.NewReportingPlugin(logger, config, orm)
diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go
index 65b95cb31a..c97d23dca0 100644
--- a/core/services/ocr2/validate/validate.go
+++ b/core/services/ocr2/validate/validate.go
@@ -12,7 +12,7 @@ import (
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
dkgconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config"
mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config"
diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go
index 34e3ee0a71..7912741802 100644
--- a/core/services/ocrbootstrap/delegate.go
+++ b/core/services/ocrbootstrap/delegate.go
@@ -8,11 +8,12 @@ import (
"github.com/pkg/errors"
"github.com/jmoiron/sqlx"
+
ocr "github.com/smartcontractkit/libocr/offchainreporting2plus"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -165,7 +166,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) (services []job.ServiceCtx, err e
ContractConfigTracker: configProvider.ContractConfigTracker(),
Database: NewDB(d.db.DB, spec.ID, lggr),
LocalConfig: lc,
- Logger: relaylogger.NewOCRWrapper(lggr.Named("OCRBootstrap"), d.ocr2Cfg.TraceLogging(), func(msg string) {
+ 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")
}),
OffchainConfigDigester: configProvider.OffchainConfigDigester(),
diff --git a/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go
index 1daa84b721..a7d510ef90 100644
--- a/core/services/ocrcommon/peer_wrapper.go
+++ b/core/services/ocrcommon/peer_wrapper.go
@@ -12,13 +12,14 @@ import (
"go.uber.org/multierr"
"github.com/jmoiron/sqlx"
+
ocrnetworking "github.com/smartcontractkit/libocr/networking"
ocrnetworkingtypes "github.com/smartcontractkit/libocr/networking/types"
ocr1types "github.com/smartcontractkit/libocr/offchainreporting/types"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -194,7 +195,7 @@ func (p *SingletonPeerWrapper) peerConfig() (ocrnetworking.PeerConfig, error) {
peerConfig := ocrnetworking.PeerConfig{
NetworkingStack: config.NetworkStack(),
PrivKey: key.PrivKey,
- Logger: relaylogger.NewOCRWrapper(p.lggr, p.ocrCfg.TraceLogging(), func(string) {}),
+ Logger: commonlogger.NewOCRWrapper(p.lggr, p.ocrCfg.TraceLogging(), func(string) {}),
// V1 config
V1ListenIP: config.V1().ListenIP(),
V1ListenPort: p2pPort,
diff --git a/core/services/ocrcommon/peerstore.go b/core/services/ocrcommon/peerstore.go
index 02a4d90f57..1d859184ab 100644
--- a/core/services/ocrcommon/peerstore.go
+++ b/core/services/ocrcommon/peerstore.go
@@ -14,7 +14,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/recovery"
diff --git a/core/services/ocrcommon/run_saver.go b/core/services/ocrcommon/run_saver.go
index d8dcc34358..184226605f 100644
--- a/core/services/ocrcommon/run_saver.go
+++ b/core/services/ocrcommon/run_saver.go
@@ -3,7 +3,7 @@ package ocrcommon
import (
"context"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
)
diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go
index be139723ef..c9d3e85cd2 100644
--- a/core/services/ocrcommon/telemetry.go
+++ b/core/services/ocrcommon/telemetry.go
@@ -13,7 +13,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
@@ -21,9 +21,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
"github.com/smartcontractkit/chainlink/v2/core/utils"
- relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
- relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
+ relaymercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
)
type eaTelemetry struct {
diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go
index 9e3dedce8a..24c798259d 100644
--- a/core/services/ocrcommon/telemetry_test.go
+++ b/core/services/ocrcommon/telemetry_test.go
@@ -6,16 +6,17 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
- "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- mercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- mercury_v2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ mercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
+ mercury_v2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/periodicbackup/backup.go b/core/services/periodicbackup/backup.go
index f43698bbdb..b1bcf40ee3 100644
--- a/core/services/periodicbackup/backup.go
+++ b/core/services/periodicbackup/backup.go
@@ -11,7 +11,7 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/pg/event_broadcaster.go b/core/services/pg/event_broadcaster.go
index f18ac3251a..70008f4c0d 100644
--- a/core/services/pg/event_broadcaster.go
+++ b/core/services/pg/event_broadcaster.go
@@ -11,7 +11,7 @@ import (
"github.com/lib/pq"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/static"
diff --git a/core/services/pg/q.go b/core/services/pg/q.go
index 9c9c15d983..050606c793 100644
--- a/core/services/pg/q.go
+++ b/core/services/pg/q.go
@@ -17,7 +17,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
)
var promSQLQueryTime = promauto.NewHistogram(prometheus.HistogramOpts{
diff --git a/core/services/pg/sqlx.go b/core/services/pg/sqlx.go
index c371c29213..c252edf9f5 100644
--- a/core/services/pg/sqlx.go
+++ b/core/services/pg/sqlx.go
@@ -9,7 +9,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
)
type Queryer interface {
diff --git a/core/services/pg/transaction.go b/core/services/pg/transaction.go
index 74841d010b..fd7e74baca 100644
--- a/core/services/pg/transaction.go
+++ b/core/services/pg/transaction.go
@@ -11,7 +11,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
corelogger "github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go
index 056a7deab2..eb242e6276 100644
--- a/core/services/pipeline/orm.go
+++ b/core/services/pipeline/orm.go
@@ -13,7 +13,7 @@ import (
"github.com/jmoiron/sqlx"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go
index d33913b475..edb1d337af 100644
--- a/core/services/pipeline/runner.go
+++ b/core/services/pipeline/runner.go
@@ -14,7 +14,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/services/promreporter/prom_reporter.go b/core/services/promreporter/prom_reporter.go
index fd6afeeb8e..2306640bea 100644
--- a/core/services/promreporter/prom_reporter.go
+++ b/core/services/promreporter/prom_reporter.go
@@ -13,7 +13,7 @@ import (
"go.uber.org/multierr"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/utils"
diff --git a/core/services/relay/evm/config_poller.go b/core/services/relay/evm/config_poller.go
index daccf400ea..fe39ed0e34 100644
--- a/core/services/relay/evm/config_poller.go
+++ b/core/services/relay/evm/config_poller.go
@@ -16,7 +16,7 @@ import (
"github.com/smartcontractkit/libocr/gethwrappers2/ocrconfigurationstoreevmsimple"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go
index aa1d1d774b..e8267c9a84 100644
--- a/core/services/relay/evm/evm.go
+++ b/core/services/relay/evm/evm.go
@@ -20,8 +20,8 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -44,7 +44,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
)
-var _ relaytypes.Relayer = &Relayer{} //nolint:staticcheck
+var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck
type Relayer struct {
db *sqlx.DB
@@ -130,7 +130,7 @@ func (r *Relayer) HealthReport() (report map[string]error) {
return
}
-func (r *Relayer) NewMercuryProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (relaytypes.MercuryProvider, error) {
+func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MercuryProvider, error) {
lggr := r.lggr.Named("MercuryProvider").Named(rargs.ExternalJobID.String())
relayOpts := types.NewRelayOpts(rargs)
relayConfig, err := relayOpts.RelayConfig()
@@ -193,13 +193,13 @@ func (r *Relayer) NewMercuryProvider(rargs relaytypes.RelayArgs, pargs relaytype
return NewMercuryProvider(cw, transmitter, reportCodecV1, reportCodecV2, reportCodecV3, chainReader, lggr), nil
}
-func (r *Relayer) NewFunctionsProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (relaytypes.FunctionsProvider, error) {
+func (r *Relayer) NewFunctionsProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.FunctionsProvider, error) {
lggr := r.lggr.Named("FunctionsProvider").Named(rargs.ExternalJobID.String())
// TODO(FUN-668): Not ready yet (doesn't implement FunctionsEvents() properly)
return NewFunctionsProvider(r.chain, rargs, pargs, lggr, r.ks.Eth(), functions.FunctionsPlugin)
}
-func (r *Relayer) NewConfigProvider(args relaytypes.RelayArgs) (relaytypes.ConfigProvider, error) {
+func (r *Relayer) NewConfigProvider(args commontypes.RelayArgs) (commontypes.ConfigProvider, error) {
lggr := r.lggr.Named("ConfigProvider").Named(args.ExternalJobID.String())
relayOpts := types.NewRelayOpts(args)
relayConfig, err := relayOpts.RelayConfig()
@@ -219,7 +219,7 @@ func (r *Relayer) NewConfigProvider(args relaytypes.RelayArgs) (relaytypes.Confi
return configProvider, err
}
-func FilterNamesFromRelayArgs(args relaytypes.RelayArgs) (filterNames []string, err error) {
+func FilterNamesFromRelayArgs(args commontypes.RelayArgs) (filterNames []string, err error) {
var addr ethkey.EIP55Address
if addr, err = ethkey.NewEIP55Address(args.ContractID); err != nil {
return nil, err
@@ -373,7 +373,7 @@ func newConfigProvider(lggr logger.Logger, chain evm.Chain, opts *types.RelayOpt
return newConfigWatcher(lggr, aggregatorAddress, contractABI, offchainConfigDigester, cp, chain, relayConfig.FromBlock, opts.New), nil
}
-func newContractTransmitter(lggr logger.Logger, rargs relaytypes.RelayArgs, transmitterID string, configWatcher *configWatcher, ethKeystore keystore.Eth) (*contractTransmitter, error) {
+func newContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, configWatcher *configWatcher, ethKeystore keystore.Eth) (*contractTransmitter, error) {
var relayConfig types.RelayConfig
if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil {
return nil, err
@@ -442,7 +442,7 @@ func newContractTransmitter(lggr logger.Logger, rargs relaytypes.RelayArgs, tran
)
}
-func newPipelineContractTransmitter(lggr logger.Logger, rargs relaytypes.RelayArgs, transmitterID string, pluginGasLimit *uint32, configWatcher *configWatcher, spec job.Job, pr pipeline.Runner) (*contractTransmitter, error) {
+func newPipelineContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, pluginGasLimit *uint32, configWatcher *configWatcher, spec job.Job, pr pipeline.Runner) (*contractTransmitter, error) {
var relayConfig types.RelayConfig
if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil {
return nil, err
@@ -491,7 +491,7 @@ func newPipelineContractTransmitter(lggr logger.Logger, rargs relaytypes.RelayAr
)
}
-func (r *Relayer) NewMedianProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (relaytypes.MedianProvider, error) {
+func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MedianProvider, error) {
lggr := r.lggr.Named("MedianProvider").Named(rargs.ExternalJobID.String())
relayOpts := types.NewRelayOpts(rargs)
relayConfig, err := relayOpts.RelayConfig()
@@ -526,7 +526,7 @@ func (r *Relayer) NewMedianProvider(rargs relaytypes.RelayArgs, pargs relaytypes
}, nil
}
-var _ relaytypes.MedianProvider = (*medianProvider)(nil)
+var _ commontypes.MedianProvider = (*medianProvider)(nil)
type medianProvider struct {
configWatcher *configWatcher
diff --git a/core/services/relay/evm/functions.go b/core/services/relay/evm/functions.go
index fdd6201c69..88f9d22099 100644
--- a/core/services/relay/evm/functions.go
+++ b/core/services/relay/evm/functions.go
@@ -16,8 +16,8 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
txm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
@@ -46,7 +46,7 @@ func (p *functionsProvider) LogPollerWrapper() evmRelayTypes.LogPollerWrapper {
return p.logPollerWrapper
}
-func (p *functionsProvider) FunctionsEvents() relaytypes.FunctionsEvents {
+func (p *functionsProvider) FunctionsEvents() commontypes.FunctionsEvents {
// TODO (FUN-668): implement
return nil
}
@@ -85,7 +85,7 @@ func (p *functionsProvider) Name() string {
return p.configWatcher.Name()
}
-func NewFunctionsProvider(chain evm.Chain, rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs, lggr logger.Logger, ethKeystore keystore.Eth, pluginType functionsRelay.FunctionsPluginType) (evmRelayTypes.FunctionsProvider, error) {
+func NewFunctionsProvider(chain evm.Chain, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs, lggr logger.Logger, ethKeystore keystore.Eth, pluginType functionsRelay.FunctionsPluginType) (evmRelayTypes.FunctionsProvider, error) {
relayOpts := evmRelayTypes.NewRelayOpts(rargs)
relayConfig, err := relayOpts.RelayConfig()
if err != nil {
@@ -130,7 +130,7 @@ func NewFunctionsProvider(chain evm.Chain, rargs relaytypes.RelayArgs, pargs rel
}, nil
}
-func newFunctionsConfigProvider(pluginType functionsRelay.FunctionsPluginType, chain evm.Chain, args relaytypes.RelayArgs, fromBlock uint64, logPollerWrapper evmRelayTypes.LogPollerWrapper, lggr logger.Logger) (*configWatcher, error) {
+func newFunctionsConfigProvider(pluginType functionsRelay.FunctionsPluginType, chain evm.Chain, args commontypes.RelayArgs, fromBlock uint64, logPollerWrapper evmRelayTypes.LogPollerWrapper, lggr logger.Logger) (*configWatcher, error) {
if !common.IsHexAddress(args.ContractID) {
return nil, errors.Errorf("invalid contractID, expected hex address")
}
@@ -153,7 +153,7 @@ func newFunctionsConfigProvider(pluginType functionsRelay.FunctionsPluginType, c
return newConfigWatcher(lggr, routerContractAddress, contractABI, offchainConfigDigester, cp, chain, fromBlock, args.New), nil
}
-func newFunctionsContractTransmitter(contractVersion uint32, rargs relaytypes.RelayArgs, transmitterID string, configWatcher *configWatcher, ethKeystore keystore.Eth, logPollerWrapper evmRelayTypes.LogPollerWrapper, lggr logger.Logger) (ContractTransmitter, error) {
+func newFunctionsContractTransmitter(contractVersion uint32, rargs commontypes.RelayArgs, transmitterID string, configWatcher *configWatcher, ethKeystore keystore.Eth, logPollerWrapper evmRelayTypes.LogPollerWrapper, lggr logger.Logger) (ContractTransmitter, error) {
var relayConfig evmRelayTypes.RelayConfig
if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil {
return nil, err
diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go
index 6193f4ba86..230185d0ad 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper.go
@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator"
diff --git a/core/services/relay/evm/loop_impl.go b/core/services/relay/evm/loop_impl.go
index f69660373e..309b5e24f6 100644
--- a/core/services/relay/evm/loop_impl.go
+++ b/core/services/relay/evm/loop_impl.go
@@ -1,7 +1,7 @@
package evm
import (
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
diff --git a/core/services/relay/evm/mercury/persistence_manager.go b/core/services/relay/evm/mercury/persistence_manager.go
index 9de1f80c6b..69dfce9c16 100644
--- a/core/services/relay/evm/mercury/persistence_manager.go
+++ b/core/services/relay/evm/mercury/persistence_manager.go
@@ -7,7 +7,7 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb"
diff --git a/core/services/relay/evm/mercury/queue.go b/core/services/relay/evm/mercury/queue.go
index 3d20b3f2b0..07ef8a9742 100644
--- a/core/services/relay/evm/mercury/queue.go
+++ b/core/services/relay/evm/mercury/queue.go
@@ -13,7 +13,7 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb"
diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go
index 269f28b122..73aa10243f 100644
--- a/core/services/relay/evm/mercury/transmitter.go
+++ b/core/services/relay/evm/mercury/transmitter.go
@@ -17,11 +17,12 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/jmoiron/sqlx"
+
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
diff --git a/core/services/relay/evm/mercury/v1/data_source.go b/core/services/relay/evm/mercury/v1/data_source.go
index 0bdfb67de7..79eb32af44 100644
--- a/core/services/relay/evm/mercury/v1/data_source.go
+++ b/core/services/relay/evm/mercury/v1/data_source.go
@@ -13,8 +13,8 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go
index 3aea503ae6..635658d786 100644
--- a/core/services/relay/evm/mercury/v1/data_source_test.go
+++ b/core/services/relay/evm/mercury/v1/data_source_test.go
@@ -15,8 +15,8 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go
index fefddd6395..28688e3b17 100644
--- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go
+++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go
@@ -8,9 +8,10 @@ import (
"github.com/ethereum/go-ethereum/common"
pkgerrors "github.com/pkg/errors"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- reportcodec "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
+ reportcodec "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go
index 3f4838c3e7..f630b4522b 100644
--- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go
+++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go
@@ -11,7 +11,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
+ relaymercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/services/relay/evm/mercury/v2/data_source.go b/core/services/relay/evm/mercury/v2/data_source.go
index 17bc4a6670..f7b7892513 100644
--- a/core/services/relay/evm/mercury/v2/data_source.go
+++ b/core/services/relay/evm/mercury/v2/data_source.go
@@ -10,8 +10,8 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/core/services/relay/evm/mercury/v2/data_source_test.go b/core/services/relay/evm/mercury/v2/data_source_test.go
index b66355ac7f..0249203193 100644
--- a/core/services/relay/evm/mercury/v2/data_source_test.go
+++ b/core/services/relay/evm/mercury/v2/data_source_test.go
@@ -8,8 +8,8 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
diff --git a/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go
index 0e1dfe9c46..6b13b3b6ef 100644
--- a/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go
+++ b/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go
@@ -6,9 +6,10 @@ import (
"math/big"
pkgerrors "github.com/pkg/errors"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- reportcodec "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
+ reportcodec "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
diff --git a/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go
index 8cf16a5dab..3a58337b4c 100644
--- a/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go
+++ b/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
)
func newValidReportFields() relaymercuryv2.ReportFields {
diff --git a/core/services/relay/evm/mercury/v3/data_source.go b/core/services/relay/evm/mercury/v3/data_source.go
index 6f2b2eb6bd..34dbd13be9 100644
--- a/core/services/relay/evm/mercury/v3/data_source.go
+++ b/core/services/relay/evm/mercury/v3/data_source.go
@@ -11,8 +11,8 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/core/services/relay/evm/mercury/v3/data_source_test.go b/core/services/relay/evm/mercury/v3/data_source_test.go
index aefc766996..c4b5b4c610 100644
--- a/core/services/relay/evm/mercury/v3/data_source_test.go
+++ b/core/services/relay/evm/mercury/v3/data_source_test.go
@@ -8,8 +8,8 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
diff --git a/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go
index 4c0b3756d7..6b379dc194 100644
--- a/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go
+++ b/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go
@@ -7,9 +7,10 @@ import (
"math/big"
pkgerrors "github.com/pkg/errors"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- reportcodec "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
+ reportcodec "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
diff --git a/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go
index 98b81edb00..88416f7ea6 100644
--- a/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go
+++ b/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
)
func newValidReportFields() relaymercuryv3.ReportFields {
diff --git a/core/services/relay/evm/mercury/wsrpc/client.go b/core/services/relay/evm/mercury/wsrpc/client.go
index f6ed1d0db8..c4db80a58d 100644
--- a/core/services/relay/evm/mercury/wsrpc/client.go
+++ b/core/services/relay/evm/mercury/wsrpc/client.go
@@ -15,7 +15,7 @@ import (
"github.com/smartcontractkit/wsrpc"
"github.com/smartcontractkit/wsrpc/connectivity"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey"
diff --git a/core/services/relay/evm/mercury_provider.go b/core/services/relay/evm/mercury_provider.go
index bba5e699bc..9025380817 100644
--- a/core/services/relay/evm/mercury_provider.go
+++ b/core/services/relay/evm/mercury_provider.go
@@ -6,19 +6,19 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaymercury "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury"
- relaymercuryv1 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v1"
- relaymercuryv2 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v2"
- relaymercuryv3 "github.com/smartcontractkit/chainlink-relay/pkg/reportingplugins/mercury/v3"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ relaymercury "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury"
+ relaymercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v1"
+ relaymercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v2"
+ relaymercuryv3 "github.com/smartcontractkit/chainlink-common/pkg/reportingplugins/mercury/v3"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury"
)
-var _ relaytypes.MercuryProvider = (*mercuryProvider)(nil)
+var _ commontypes.MercuryProvider = (*mercuryProvider)(nil)
type mercuryProvider struct {
configWatcher *configWatcher
diff --git a/core/services/relay/evm/mocks/loop_relay_adapter.go b/core/services/relay/evm/mocks/loop_relay_adapter.go
index 13107fe8ae..13a73036a1 100644
--- a/core/services/relay/evm/mocks/loop_relay_adapter.go
+++ b/core/services/relay/evm/mocks/loop_relay_adapter.go
@@ -9,7 +9,7 @@ import (
evm "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
mock "github.com/stretchr/testify/mock"
- types "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ types "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// LoopRelayAdapter is an autogenerated mock type for the LoopRelayAdapter type
diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go
index a284d677eb..2e8f9cbf48 100644
--- a/core/services/relay/evm/ocr2keeper.go
+++ b/core/services/relay/evm/ocr2keeper.go
@@ -10,12 +10,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
"github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
@@ -33,19 +34,19 @@ var (
// OCR2KeeperProviderOpts is the custom options to create a keeper provider
type OCR2KeeperProviderOpts struct {
- RArgs relaytypes.RelayArgs
- PArgs relaytypes.PluginArgs
+ RArgs commontypes.RelayArgs
+ PArgs commontypes.PluginArgs
InstanceID int
}
// OCR2KeeperProvider provides all components needed for a OCR2Keeper plugin.
type OCR2KeeperProvider interface {
- relaytypes.Plugin
+ commontypes.Plugin
}
// OCR2KeeperRelayer contains the relayer and instantiating functions for OCR2Keeper providers.
type OCR2KeeperRelayer interface {
- NewOCR2KeeperProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (OCR2KeeperProvider, error)
+ NewOCR2KeeperProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error)
}
// ocr2keeperRelayer is the relayer with added DKG and OCR2Keeper provider functions.
@@ -68,7 +69,7 @@ func NewOCR2KeeperRelayer(db *sqlx.DB, chain evm.Chain, pr pipeline.Runner, spec
}
}
-func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (OCR2KeeperProvider, error) {
+func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error) {
cfgWatcher, err := newOCR2KeeperConfigProvider(r.lggr, r.chain, rargs)
if err != nil {
return nil, err
@@ -129,7 +130,7 @@ func (c *ocr2keeperProvider) ContractTransmitter() ocrtypes.ContractTransmitter
return c.contractTransmitter
}
-func newOCR2KeeperConfigProvider(lggr logger.Logger, chain evm.Chain, rargs relaytypes.RelayArgs) (*configWatcher, error) {
+func newOCR2KeeperConfigProvider(lggr logger.Logger, chain evm.Chain, rargs commontypes.RelayArgs) (*configWatcher, error) {
var relayConfig types.RelayConfig
err := json.Unmarshal(rargs.RelayConfig, &relayConfig)
if err != nil {
diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go
index 0c9414068e..66ce42b7d8 100644
--- a/core/services/relay/evm/ocr2vrf.go
+++ b/core/services/relay/evm/ocr2vrf.go
@@ -9,11 +9,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -24,18 +25,18 @@ import (
// DKGProvider provides all components needed for a DKG plugin.
type DKGProvider interface {
- relaytypes.Plugin
+ commontypes.Plugin
}
// OCR2VRFProvider provides all components needed for a OCR2VRF plugin.
type OCR2VRFProvider interface {
- relaytypes.Plugin
+ commontypes.Plugin
}
// OCR2VRFRelayer contains the relayer and instantiating functions for OCR2VRF providers.
type OCR2VRFRelayer interface {
- NewDKGProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (DKGProvider, error)
- NewOCR2VRFProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (OCR2VRFProvider, error)
+ NewDKGProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (DKGProvider, error)
+ NewOCR2VRFProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2VRFProvider, error)
}
var (
@@ -61,7 +62,7 @@ func NewOCR2VRFRelayer(db *sqlx.DB, chain evm.Chain, lggr logger.Logger, ethKeys
}
}
-func (r *ocr2vrfRelayer) NewDKGProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (DKGProvider, error) {
+func (r *ocr2vrfRelayer) NewDKGProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (DKGProvider, error) {
configWatcher, err := newOCR2VRFConfigProvider(r.lggr, r.chain, rargs)
if err != nil {
return nil, err
@@ -84,7 +85,7 @@ func (r *ocr2vrfRelayer) NewDKGProvider(rargs relaytypes.RelayArgs, pargs relayt
}, nil
}
-func (r *ocr2vrfRelayer) NewOCR2VRFProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (OCR2VRFProvider, error) {
+func (r *ocr2vrfRelayer) NewOCR2VRFProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2VRFProvider, error) {
configWatcher, err := newOCR2VRFConfigProvider(r.lggr, r.chain, rargs)
if err != nil {
return nil, err
@@ -118,7 +119,7 @@ func (c *ocr2vrfProvider) ContractTransmitter() ocrtypes.ContractTransmitter {
return c.contractTransmitter
}
-func newOCR2VRFConfigProvider(lggr logger.Logger, chain evm.Chain, rargs relaytypes.RelayArgs) (*configWatcher, error) {
+func newOCR2VRFConfigProvider(lggr logger.Logger, chain evm.Chain, rargs commontypes.RelayArgs) (*configWatcher, error) {
var relayConfig types.RelayConfig
err := json.Unmarshal(rargs.RelayConfig, &relayConfig)
if err != nil {
diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go
index b6ca4d75fb..43626037a1 100644
--- a/core/services/relay/evm/relayer_extender.go
+++ b/core/services/relay/evm/relayer_extender.go
@@ -8,8 +8,8 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
evmchain "github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -75,11 +75,11 @@ type ChainRelayerExt struct {
var _ EVMChainRelayerExtender = &ChainRelayerExt{}
-func (s *ChainRelayerExt) GetChainStatus(ctx context.Context) (relaytypes.ChainStatus, error) {
+func (s *ChainRelayerExt) GetChainStatus(ctx context.Context) (commontypes.ChainStatus, error) {
return s.chain.GetChainStatus(ctx)
}
-func (s *ChainRelayerExt) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []relaytypes.NodeStatus, nextPageToken string, total int, err error) {
+func (s *ChainRelayerExt) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []commontypes.NodeStatus, nextPageToken string, total int, err error) {
return s.chain.ListNodeStatuses(ctx, pageSize, pageToken)
}
diff --git a/core/services/relay/evm/request_round_tracker.go b/core/services/relay/evm/request_round_tracker.go
index c1c3a49e0e..1f1ed71fc3 100644
--- a/core/services/relay/evm/request_round_tracker.go
+++ b/core/services/relay/evm/request_round_tracker.go
@@ -10,10 +10,11 @@ import (
"github.com/pkg/errors"
"github.com/jmoiron/sqlx"
+
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
diff --git a/core/services/relay/evm/types/types.go b/core/services/relay/evm/types/types.go
index 6a1e66bd09..d2edef8b11 100644
--- a/core/services/relay/evm/types/types.go
+++ b/core/services/relay/evm/types/types.go
@@ -13,9 +13,9 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -36,7 +36,7 @@ type RelayConfig struct {
type RelayOpts struct {
// TODO BCF-2508 -- should anyone ever get the raw config bytes that are embedded in args? if not,
// make this private and wrap the arg fields with funcs on RelayOpts
- relaytypes.RelayArgs
+ commontypes.RelayArgs
c *RelayConfig
}
@@ -71,9 +71,9 @@ type ConfigPoller interface {
Replay(ctx context.Context, fromBlock int64) error
}
-// TODO(FUN-668): Migrate this fully into relaytypes.FunctionsProvider
+// TODO(FUN-668): Migrate this fully into commontypes.FunctionsProvider
type FunctionsProvider interface {
- relaytypes.FunctionsProvider
+ commontypes.FunctionsProvider
LogPollerWrapper() LogPollerWrapper
}
diff --git a/core/services/relay/grpc_provider_server.go b/core/services/relay/grpc_provider_server.go
index 943af0e636..67bbb8c6c2 100644
--- a/core/services/relay/grpc_provider_server.go
+++ b/core/services/relay/grpc_provider_server.go
@@ -8,8 +8,8 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/services/relay/grpc_provider_server_test.go b/core/services/relay/grpc_provider_server_test.go
index e7ee8d7f15..fafe20ef12 100644
--- a/core/services/relay/grpc_provider_server_test.go
+++ b/core/services/relay/grpc_provider_server_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go
index 5c7bf5cab5..eb6d3faf4f 100644
--- a/core/services/relay/relay.go
+++ b/core/services/relay/relay.go
@@ -5,8 +5,8 @@ import (
"fmt"
"regexp"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
type Network = string
diff --git a/core/services/relay/relay_test.go b/core/services/relay/relay_test.go
index 5bcd14c64a..fc9e273e30 100644
--- a/core/services/relay/relay_test.go
+++ b/core/services/relay/relay_test.go
@@ -4,12 +4,13 @@ import (
"context"
"testing"
+ "github.com/stretchr/testify/assert"
+
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
func TestIdentifier_UnmarshalString(t *testing.T) {
diff --git a/core/services/service.go b/core/services/service.go
index 066405ac01..19ca118373 100644
--- a/core/services/service.go
+++ b/core/services/service.go
@@ -1,7 +1,7 @@
package services
import (
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
type ServiceCtx = services.Service
diff --git a/core/services/synchronization/telemetry_ingress_batch_client.go b/core/services/synchronization/telemetry_ingress_batch_client.go
index 26abda65d3..c551ac85b3 100644
--- a/core/services/synchronization/telemetry_ingress_batch_client.go
+++ b/core/services/synchronization/telemetry_ingress_batch_client.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/wsrpc"
"github.com/smartcontractkit/wsrpc/examples/simple/keys"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
diff --git a/core/services/synchronization/telemetry_ingress_client.go b/core/services/synchronization/telemetry_ingress_client.go
index 9458b7627c..b889b3fc97 100644
--- a/core/services/synchronization/telemetry_ingress_client.go
+++ b/core/services/synchronization/telemetry_ingress_client.go
@@ -11,7 +11,7 @@ import (
"github.com/smartcontractkit/wsrpc"
"github.com/smartcontractkit/wsrpc/examples/simple/keys"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
diff --git a/core/services/telemetry/manager.go b/core/services/telemetry/manager.go
index cc14a956c1..d760d13b2b 100644
--- a/core/services/telemetry/manager.go
+++ b/core/services/telemetry/manager.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go
index 2d51d9f449..d24fb348b7 100644
--- a/core/services/telemetry/manager_test.go
+++ b/core/services/telemetry/manager_test.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/config/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go
index a8e662c931..35556c6b45 100644
--- a/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go
+++ b/core/services/vrf/solidity_cross_tests/vrf_coordinator_interface.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go
index b1f9bbb503..566e5ac9bd 100644
--- a/core/services/vrf/v1/listener_v1.go
+++ b/core/services/vrf/v1/listener_v1.go
@@ -16,7 +16,7 @@ import (
heaps "github.com/theodesp/go-heaps"
"github.com/theodesp/go-heaps/pairing"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index df886924aa..15121ba306 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -30,7 +30,7 @@ import (
"github.com/jmoiron/sqlx"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -1462,7 +1462,7 @@ func simulatedOverrides(t *testing.T, defaultGasPrice *assets.Wei, ks ...toml.Ke
c.EVM[0].FinalityDepth = ptr[uint32](15)
c.EVM[0].MinIncomingConfirmations = ptr[uint32](1)
- c.EVM[0].MinContractPayment = relayassets.NewLinkFromJuels(100)
+ c.EVM[0].MinContractPayment = commonassets.NewLinkFromJuels(100)
c.EVM[0].KeySpecific = ks
}
}
diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go
index 3480f63f09..5b73ac9e24 100644
--- a/core/services/vrf/v2/listener_v2.go
+++ b/core/services/vrf/v2/listener_v2.go
@@ -25,7 +25,7 @@ import (
"github.com/theodesp/go-heaps/pairing"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go
index 0ff0900016..43ddd41d56 100644
--- a/core/store/migrate/migrate_test.go
+++ b/core/store/migrate/migrate_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/utils/big.go b/core/utils/big.go
index f0f9a2d96d..22cd8e64e5 100644
--- a/core/utils/big.go
+++ b/core/utils/big.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/smartcontractkit/chainlink-relay/pkg/utils/bytes"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes"
bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math"
)
diff --git a/core/utils/config/validate.go b/core/utils/config/validate.go
index 32cb94b520..5fbae24ad5 100644
--- a/core/utils/config/validate.go
+++ b/core/utils/config/validate.go
@@ -9,7 +9,7 @@ import (
"github.com/Masterminds/semver/v3"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink-relay/pkg/config"
+ "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/core/utils/mailbox_prom.go b/core/utils/mailbox_prom.go
index dc20db84d9..33cbb2357b 100644
--- a/core/utils/mailbox_prom.go
+++ b/core/utils/mailbox_prom.go
@@ -10,7 +10,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
var mailboxLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{
diff --git a/core/utils/sleeper_task.go b/core/utils/sleeper_task.go
index fcec254249..d84457e932 100644
--- a/core/utils/sleeper_task.go
+++ b/core/utils/sleeper_task.go
@@ -4,7 +4,7 @@ import (
"fmt"
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
// SleeperTask represents a task that waits in the background to process some work.
diff --git a/core/utils/utils.go b/core/utils/utils.go
index 6ea7164df1..a2e418fe04 100644
--- a/core/utils/utils.go
+++ b/core/utils/utils.go
@@ -32,7 +32,7 @@ import (
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/sha3"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
const (
diff --git a/core/web/bridge_types_controller.go b/core/web/bridge_types_controller.go
index 57a79e2b61..f320a52523 100644
--- a/core/web/bridge_types_controller.go
+++ b/core/web/bridge_types_controller.go
@@ -8,7 +8,7 @@ import (
"github.com/jackc/pgconn"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/web/bridge_types_controller_test.go b/core/web/bridge_types_controller_test.go
index a65362ba9a..a7873ad9f7 100644
--- a/core/web/bridge_types_controller_test.go
+++ b/core/web/bridge_types_controller_test.go
@@ -6,7 +6,7 @@ import (
"net/http"
"testing"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/web/chains_controller.go b/core/web/chains_controller.go
index c11d457c49..e547cf0150 100644
--- a/core/web/chains_controller.go
+++ b/core/web/chains_controller.go
@@ -7,7 +7,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/manyminds/api2go/jsonapi"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
diff --git a/core/web/cosmos_chains_controller_test.go b/core/web/cosmos_chains_controller_test.go
index f8dbe4614f..5491b33c35 100644
--- a/core/web/cosmos_chains_controller_test.go
+++ b/core/web/cosmos_chains_controller_test.go
@@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
diff --git a/core/web/eth_keys_controller.go b/core/web/eth_keys_controller.go
index 6e2a3b2efc..b202d90f21 100644
--- a/core/web/eth_keys_controller.go
+++ b/core/web/eth_keys_controller.go
@@ -9,7 +9,7 @@ import (
"strconv"
"strings"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/config/toml"
@@ -365,13 +365,13 @@ func (ekc *ETHKeysController) getEthBalance(ctx context.Context, state ethkey.St
}
-func (ekc *ETHKeysController) setLinkBalance(bal *relayassets.Link) presenters.NewETHKeyOption {
+func (ekc *ETHKeysController) setLinkBalance(bal *commonassets.Link) presenters.NewETHKeyOption {
return presenters.SetETHKeyLinkBalance(bal)
}
// queries the EthClient for the LINK balance at the address associated with state
-func (ekc *ETHKeysController) getLinkBalance(ctx context.Context, state ethkey.State) *relayassets.Link {
- var bal *relayassets.Link
+func (ekc *ETHKeysController) getLinkBalance(ctx context.Context, state ethkey.State) *commonassets.Link {
+ var bal *commonassets.Link
chainID := state.EVMChainID.ToInt()
chain, err := ekc.app.GetRelayers().LegacyEVMChains().Get(chainID.String())
if err != nil {
diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go
index 8941c2d2fd..d0ad27262f 100644
--- a/core/web/eth_keys_controller_test.go
+++ b/core/web/eth_keys_controller_test.go
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
diff --git a/core/web/loader/getters.go b/core/web/loader/getters.go
index 8ca29cc962..27a39181ff 100644
--- a/core/web/loader/getters.go
+++ b/core/web/loader/getters.go
@@ -7,7 +7,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -21,7 +21,7 @@ import (
var ErrInvalidType = errors.New("invalid type")
// GetChainByID fetches the chain by it's id.
-func GetChainByID(ctx context.Context, id string) (*relaytypes.ChainStatus, error) {
+func GetChainByID(ctx context.Context, id string) (*commontypes.ChainStatus, error) {
ldr := For(ctx)
thunk := ldr.ChainsByIDLoader.Load(ctx, dataloader.StringKey(id))
@@ -30,7 +30,7 @@ func GetChainByID(ctx context.Context, id string) (*relaytypes.ChainStatus, erro
return nil, err
}
- chain, ok := result.(relaytypes.ChainStatus)
+ chain, ok := result.(commontypes.ChainStatus)
if !ok {
return nil, ErrInvalidType
}
diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go
index 984aa9f618..9bd1feb05b 100644
--- a/core/web/loader/loader_test.go
+++ b/core/web/loader/loader_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- relaytypes "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
@@ -50,12 +50,12 @@ func TestLoader_Chains(t *testing.T) {
assert.Len(t, results, 3)
config2, err := chain2.TOMLString()
require.NoError(t, err)
- want2 := relaytypes.ChainStatus{ID: "2", Enabled: true, Config: config2}
- assert.Equal(t, want2, results[0].Data.(relaytypes.ChainStatus))
+ want2 := commontypes.ChainStatus{ID: "2", Enabled: true, Config: config2}
+ assert.Equal(t, want2, results[0].Data.(commontypes.ChainStatus))
config1, err := chain.TOMLString()
require.NoError(t, err)
- want1 := relaytypes.ChainStatus{ID: "1", Enabled: true, Config: config1}
- assert.Equal(t, want1, results[1].Data.(relaytypes.ChainStatus))
+ want1 := commontypes.ChainStatus{ID: "1", Enabled: true, Config: config1}
+ assert.Equal(t, want1, results[1].Data.(commontypes.ChainStatus))
assert.Nil(t, results[2].Data)
assert.Error(t, results[2].Error)
assert.ErrorIs(t, results[2].Error, chains.ErrNotFound)
@@ -69,13 +69,13 @@ func TestLoader_Nodes(t *testing.T) {
chainID1, chainID2, notAnID := big.NewInt(1), big.NewInt(2), big.NewInt(3)
- genNodeStat := func(id string) relaytypes.NodeStatus {
- return relaytypes.NodeStatus{
+ genNodeStat := func(id string) commontypes.NodeStatus {
+ return commontypes.NodeStatus{
Name: "test-node-" + id,
ChainID: id,
}
}
- rcInterops := &chainlinkmocks.FakeRelayerChainInteroperators{Nodes: []relaytypes.NodeStatus{
+ rcInterops := &chainlinkmocks.FakeRelayerChainInteroperators{Nodes: []commontypes.NodeStatus{
genNodeStat(chainID2.String()), genNodeStat(chainID1.String()),
}}
@@ -86,9 +86,9 @@ func TestLoader_Nodes(t *testing.T) {
found := batcher.loadByChainIDs(ctx, keys)
require.Len(t, found, 3)
- assert.Equal(t, []relaytypes.NodeStatus{genNodeStat(chainID2.String())}, found[0].Data)
- assert.Equal(t, []relaytypes.NodeStatus{genNodeStat(chainID1.String())}, found[1].Data)
- assert.Equal(t, []relaytypes.NodeStatus{}, found[2].Data)
+ assert.Equal(t, []commontypes.NodeStatus{genNodeStat(chainID2.String())}, found[0].Data)
+ assert.Equal(t, []commontypes.NodeStatus{genNodeStat(chainID1.String())}, found[1].Data)
+ assert.Equal(t, []commontypes.NodeStatus{}, found[2].Data)
}
func TestLoader_FeedsManagers(t *testing.T) {
diff --git a/core/web/loader/node.go b/core/web/loader/node.go
index 9ea6062dc2..ef8e363d9f 100644
--- a/core/web/loader/node.go
+++ b/core/web/loader/node.go
@@ -5,7 +5,7 @@ import (
"github.com/graph-gophers/dataloader"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
diff --git a/core/web/loop_registry_test.go b/core/web/loop_registry_test.go
index ea76672564..94e2bc856d 100644
--- a/core/web/loop_registry_test.go
+++ b/core/web/loop_registry_test.go
@@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"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"
diff --git a/core/web/nodes_controller.go b/core/web/nodes_controller.go
index 3547b150bc..04c4693983 100644
--- a/core/web/nodes_controller.go
+++ b/core/web/nodes_controller.go
@@ -7,7 +7,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/manyminds/api2go/jsonapi"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
diff --git a/core/web/presenters/bridges.go b/core/web/presenters/bridges.go
index 440e444c61..82f4a961c9 100644
--- a/core/web/presenters/bridges.go
+++ b/core/web/presenters/bridges.go
@@ -3,7 +3,7 @@ package presenters
import (
"time"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
)
diff --git a/core/web/presenters/bridges_test.go b/core/web/presenters/bridges_test.go
index f6ce3af756..746d361958 100644
--- a/core/web/presenters/bridges_test.go
+++ b/core/web/presenters/bridges_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/core/web/presenters/cosmos_chain.go b/core/web/presenters/cosmos_chain.go
index d65a110287..c3b006e5c7 100644
--- a/core/web/presenters/cosmos_chain.go
+++ b/core/web/presenters/cosmos_chain.go
@@ -1,7 +1,7 @@
package presenters
import (
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// CosmosChainResource is an Cosmos chain JSONAPI resource.
diff --git a/core/web/presenters/eth_key.go b/core/web/presenters/eth_key.go
index 9265442761..3d952dabed 100644
--- a/core/web/presenters/eth_key.go
+++ b/core/web/presenters/eth_key.go
@@ -3,7 +3,7 @@ package presenters
import (
"time"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -13,14 +13,14 @@ import (
// representation of the address plus its ETH & LINK balances
type ETHKeyResource struct {
JAID
- EVMChainID utils.Big `json:"evmChainID"`
- Address string `json:"address"`
- EthBalance *assets.Eth `json:"ethBalance"`
- LinkBalance *relayassets.Link `json:"linkBalance"`
- Disabled bool `json:"disabled"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- MaxGasPriceWei *utils.Big `json:"maxGasPriceWei"`
+ EVMChainID utils.Big `json:"evmChainID"`
+ Address string `json:"address"`
+ EthBalance *assets.Eth `json:"ethBalance"`
+ LinkBalance *commonassets.Link `json:"linkBalance"`
+ Disabled bool `json:"disabled"`
+ CreatedAt time.Time `json:"createdAt"`
+ UpdatedAt time.Time `json:"updatedAt"`
+ MaxGasPriceWei *utils.Big `json:"maxGasPriceWei"`
}
// GetName implements the api2go EntityNamer interface
@@ -63,7 +63,7 @@ func SetETHKeyEthBalance(ethBalance *assets.Eth) NewETHKeyOption {
}
}
-func SetETHKeyLinkBalance(linkBalance *relayassets.Link) NewETHKeyOption {
+func SetETHKeyLinkBalance(linkBalance *commonassets.Link) NewETHKeyOption {
return func(r *ETHKeyResource) {
r.LinkBalance = linkBalance
}
diff --git a/core/web/presenters/eth_key_test.go b/core/web/presenters/eth_key_test.go
index 0e68fbc90c..85d005cf61 100644
--- a/core/web/presenters/eth_key_test.go
+++ b/core/web/presenters/eth_key_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"time"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -40,12 +40,12 @@ func TestETHKeyResource(t *testing.T) {
r := NewETHKeyResource(key, state,
SetETHKeyEthBalance(assets.NewEth(1)),
- SetETHKeyLinkBalance(relayassets.NewLinkFromJuels(1)),
+ SetETHKeyLinkBalance(commonassets.NewLinkFromJuels(1)),
SetETHKeyMaxGasPriceWei(utils.NewBigI(12345)),
)
assert.Equal(t, assets.NewEth(1), r.EthBalance)
- assert.Equal(t, relayassets.NewLinkFromJuels(1), r.LinkBalance)
+ assert.Equal(t, commonassets.NewLinkFromJuels(1), r.LinkBalance)
assert.Equal(t, utils.NewBigI(12345), r.MaxGasPriceWei)
b, err := jsonapi.Marshal(r)
diff --git a/core/web/presenters/evm_chain.go b/core/web/presenters/evm_chain.go
index 25862875ee..8cc6da46a7 100644
--- a/core/web/presenters/evm_chain.go
+++ b/core/web/presenters/evm_chain.go
@@ -1,6 +1,6 @@
package presenters
-import "github.com/smartcontractkit/chainlink-relay/pkg/types"
+import "github.com/smartcontractkit/chainlink-common/pkg/types"
// EVMChainResource is an EVM chain JSONAPI resource.
type EVMChainResource struct {
diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go
index d9ec1844ae..dc5bf62333 100644
--- a/core/web/presenters/job.go
+++ b/core/web/presenters/job.go
@@ -7,7 +7,7 @@ import (
"github.com/lib/pq"
"gopkg.in/guregu/null.v4"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -44,7 +44,7 @@ const (
type DirectRequestSpec struct {
ContractAddress ethkey.EIP55Address `json:"contractAddress"`
MinIncomingConfirmations clnull.Uint32 `json:"minIncomingConfirmations"`
- MinContractPayment *relayassets.Link `json:"minContractPaymentLinkJuels"`
+ MinContractPayment *commonassets.Link `json:"minContractPaymentLinkJuels"`
Requesters models.AddressCollection `json:"requesters"`
Initiator string `json:"initiator"`
CreatedAt time.Time `json:"createdAt"`
@@ -81,7 +81,7 @@ type FluxMonitorSpec struct {
DrumbeatEnabled bool `json:"drumbeatEnabled"`
DrumbeatSchedule *string `json:"drumbeatSchedule"`
DrumbeatRandomDelay *string `json:"drumbeatRandomDelay"`
- MinPayment *relayassets.Link `json:"minPayment"`
+ MinPayment *commonassets.Link `json:"minPayment"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
EVMChainID *utils.Big `json:"evmChainID"`
diff --git a/core/web/presenters/job_test.go b/core/web/presenters/job_test.go
index 46c765a38b..7e997c899c 100644
--- a/core/web/presenters/job_test.go
+++ b/core/web/presenters/job_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
diff --git a/core/web/presenters/solana_chain.go b/core/web/presenters/solana_chain.go
index ba6cace7c3..f04d2b65d5 100644
--- a/core/web/presenters/solana_chain.go
+++ b/core/web/presenters/solana_chain.go
@@ -1,7 +1,7 @@
package presenters
import (
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// SolanaChainResource is an Solana chain JSONAPI resource.
diff --git a/core/web/presenters/starknet_chain.go b/core/web/presenters/starknet_chain.go
index 2a9e49e74c..ec1cd453a5 100644
--- a/core/web/presenters/starknet_chain.go
+++ b/core/web/presenters/starknet_chain.go
@@ -1,7 +1,7 @@
package presenters
import (
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// StarkNetChainResource is an StarkNet chain JSONAPI resource.
diff --git a/core/web/resolver/bridge_test.go b/core/web/resolver/bridge_test.go
index e708ac92a4..71ef4a2b34 100644
--- a/core/web/resolver/bridge_test.go
+++ b/core/web/resolver/bridge_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
)
diff --git a/core/web/resolver/chain.go b/core/web/resolver/chain.go
index 53f1016d72..32e9a8caac 100644
--- a/core/web/resolver/chain.go
+++ b/core/web/resolver/chain.go
@@ -3,7 +3,7 @@ package resolver
import (
"github.com/graph-gophers/graphql-go"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
// ChainResolver resolves the Chain type.
diff --git a/core/web/resolver/eth_key_test.go b/core/web/resolver/eth_key_test.go
index f8f417ca44..d75282e0fb 100644
--- a/core/web/resolver/eth_key_test.go
+++ b/core/web/resolver/eth_key_test.go
@@ -9,7 +9,7 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/mock"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
@@ -96,7 +96,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil)
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
- f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(relayassets.NewLinkFromJuels(12), nil)
+ f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(commonassets.NewLinkFromJuels(12), nil)
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
f.Mocks.balM.On("GetEthBalance", address).Return(assets.NewEth(1))
f.Mocks.chain.On("BalanceMonitor").Return(f.Mocks.balM)
@@ -301,7 +301,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
f.Mocks.keystore.On("Eth").Return(f.Mocks.ethKs)
- f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(relayassets.NewLinkFromJuels(12), gError)
+ f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(commonassets.NewLinkFromJuels(12), gError)
f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, nil)
f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
@@ -354,7 +354,7 @@ func TestResolver_ETHKeys(t *testing.T) {
f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil)
f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil)
f.Mocks.ethKs.On("GetAll").Return(keys, nil)
- f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(relayassets.NewLinkFromJuels(12), nil)
+ f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(commonassets.NewLinkFromJuels(12), nil)
f.Mocks.chain.On("Client").Return(f.Mocks.ethClient)
f.Mocks.chain.On("BalanceMonitor").Return(nil)
f.Mocks.chain.On("Config").Return(f.Mocks.scfg)
diff --git a/core/web/resolver/helpers.go b/core/web/resolver/helpers.go
index 2dc865674e..36080a8b54 100644
--- a/core/web/resolver/helpers.go
+++ b/core/web/resolver/helpers.go
@@ -8,7 +8,7 @@ import (
"github.com/graph-gophers/graphql-go"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/utils/stringutils"
)
diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go
index 52f914e0a8..990a6c0805 100644
--- a/core/web/resolver/mutation.go
+++ b/core/web/resolver/mutation.go
@@ -13,7 +13,7 @@ import (
"go.uber.org/zap/zapcore"
"gopkg.in/guregu/null.v4"
- "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/auth"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
diff --git a/core/web/resolver/node.go b/core/web/resolver/node.go
index 39a85e83b1..8e01b7056b 100644
--- a/core/web/resolver/node.go
+++ b/core/web/resolver/node.go
@@ -7,7 +7,7 @@ import (
"github.com/graph-gophers/graphql-go"
"github.com/pelletier/go-toml/v2"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
evmtoml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/web/loader"
diff --git a/core/web/resolver/node_test.go b/core/web/resolver/node_test.go
index 9f34b27420..24a31b986f 100644
--- a/core/web/resolver/node_test.go
+++ b/core/web/resolver/node_test.go
@@ -6,7 +6,7 @@ import (
gqlerrors "github.com/graph-gophers/graphql-go/errors"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
diff --git a/core/web/resolver/query.go b/core/web/resolver/query.go
index e9fd18cf19..da15b7f7c2 100644
--- a/core/web/resolver/query.go
+++ b/core/web/resolver/query.go
@@ -10,7 +10,7 @@ import (
"github.com/graph-gophers/graphql-go"
"github.com/pkg/errors"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go
index fd369088bb..4de66f1dcb 100644
--- a/core/web/resolver/spec_test.go
+++ b/core/web/resolver/spec_test.go
@@ -9,8 +9,8 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v4"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
@@ -97,7 +97,7 @@ func TestResolver_DirectRequestSpec(t *testing.T) {
CreatedAt: f.Timestamp(),
EVMChainID: utils.NewBigI(42),
MinIncomingConfirmations: clnull.NewUint32(1, true),
- MinContractPayment: relayassets.NewLinkFromJuels(1000),
+ MinContractPayment: commonassets.NewLinkFromJuels(1000),
Requesters: models.AddressCollection{requesterAddress},
},
}, nil)
@@ -164,7 +164,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) {
DrumbeatEnabled: false,
IdleTimerDisabled: false,
IdleTimerPeriod: time.Duration(1 * time.Hour),
- MinPayment: relayassets.NewLinkFromJuels(1000),
+ MinPayment: commonassets.NewLinkFromJuels(1000),
PollTimerDisabled: false,
PollTimerPeriod: time.Duration(1 * time.Minute),
},
@@ -233,7 +233,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) {
DrumbeatSchedule: "CRON_TZ=UTC 0 0 1 1 *",
IdleTimerDisabled: true,
IdleTimerPeriod: time.Duration(1 * time.Hour),
- MinPayment: relayassets.NewLinkFromJuels(1000),
+ MinPayment: commonassets.NewLinkFromJuels(1000),
PollTimerDisabled: true,
PollTimerPeriod: time.Duration(1 * time.Minute),
},
diff --git a/core/web/solana_chains_controller_test.go b/core/web/solana_chains_controller_test.go
index c4023f166b..1377cb65ab 100644
--- a/core/web/solana_chains_controller_test.go
+++ b/core/web/solana_chains_controller_test.go
@@ -11,8 +11,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- relaycfg "github.com/smartcontractkit/chainlink-relay/pkg/config"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
@@ -84,7 +84,7 @@ Nodes = []
ChainID: ptr(validId),
Chain: config.Chain{
SkipPreflight: ptr(false),
- TxTimeout: relaycfg.MustNewDuration(time.Hour),
+ TxTimeout: commoncfg.MustNewDuration(time.Hour),
},
})
@@ -114,7 +114,7 @@ func Test_SolanaChainsController_Index(t *testing.T) {
chainA := &solana.TOMLConfig{
ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))),
Chain: config.Chain{
- TxTimeout: relaycfg.MustNewDuration(time.Hour),
+ TxTimeout: commoncfg.MustNewDuration(time.Hour),
},
}
chainB := &solana.TOMLConfig{
diff --git a/go.mod b/go.mod
index 40803d504c..784d3ff78e 100644
--- a/go.mod
+++ b/go.mod
@@ -65,10 +65,10 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd
- github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05
- github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb
+ github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542
+ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1
+ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
diff --git a/go.sum b/go.sum
index 52975e722a..fb09e792d6 100644
--- a/go.sum
+++ b/go.sum
@@ -1463,14 +1463,14 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd h1:PRVJxNK67pQWufXuB1cxckH/xZkcQFDy8KjN9ZYqong=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd/go.mod h1:rOayi690YxLlkQy959PD8INhOAIAUi9LoN0G+J/CEf4=
-github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
-github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
-github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
-github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542/go.mod h1:EpvRoycRD+kniYlz+pCpRT5e+fmPm0mSD/vmND+0oMg=
+github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 h1:D7yb4kgNGVAiD5lFYqm/LW8d5jU66TXyYvSskDiW9yg=
+github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1/go.mod h1:UfW7/PZKon+iDEHtrHOfvMnS5GfYOW/SdMZ6P97rPEk=
+github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 h1:yxaHuDTtj2xxtsR8b+LJw8xDvyr6v/F6GP3InsP4wPI=
+github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
index f48d415792..fd15d51af4 100644
--- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
+++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/utils/conversions"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer"
@@ -869,7 +869,7 @@ func retreiveLoadTestMetrics(
func LogSubDetails(l zerolog.Logger, subscription vrf_coordinator_v2_5.GetSubscription, subID *big.Int, coordinator contracts.VRFCoordinatorV2_5) {
l.Debug().
Str("Coordinator", coordinator.Address()).
- Str("Link Balance", (*relayassets.Link)(subscription.Balance).Link()).
+ Str("Link Balance", (*commonassets.Link)(subscription.Balance).Link()).
Str("Native Token Balance", assets.FormatWei(subscription.NativeBalance)).
Str("Subscription ID", subID.String()).
Str("Subscription Owner", subscription.Owner.String()).
@@ -972,11 +972,11 @@ func LogFulfillmentDetailsLinkBilling(
randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled,
) {
l.Debug().
- Str("Consumer Balance Before Request (Link)", (*relayassets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()).
- Str("Consumer Balance After Request (Link)", (*relayassets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()).
+ Str("Consumer Balance Before Request (Link)", (*commonassets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()).
+ Str("Consumer Balance After Request (Link)", (*commonassets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()).
Bool("Fulfilment Status", consumerStatus.Fulfilled).
- Str("Paid by Consumer Contract (Link)", (*relayassets.Link)(consumerStatus.Paid).Link()).
- Str("Paid by Coordinator Sub (Link)", (*relayassets.Link)(randomWordsFulfilledEvent.Payment).Link()).
+ Str("Paid by Consumer Contract (Link)", (*commonassets.Link)(consumerStatus.Paid).Link()).
+ Str("Paid by Coordinator Sub (Link)", (*commonassets.Link)(randomWordsFulfilledEvent.Payment).Link()).
Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()).
Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()).
Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()).
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index aed5e0682c..3b1a5423df 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,7 +22,7 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
- github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd
+ github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
github.com/smartcontractkit/chainlink-testing-framework v1.19.1
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
@@ -387,9 +387,9 @@ require (
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 // indirect
- github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 // indirect
- github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 // indirect
+ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 // indirect
+ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
github.com/smartcontractkit/wsrpc v0.7.2 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 896ae8c6d2..427ad1421c 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2367,14 +2367,14 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255 h1:Pt6c7bJU9wIN6PQQnmN8UmYYH6lpfiQ6U/B8yEC2s5s=
-github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231109141932-cb1ea9020255/go.mod h1:EHppaccd/LTlTMI2o4dmBHe4BknEgEFFDjDGMNuGb3k=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd h1:PRVJxNK67pQWufXuB1cxckH/xZkcQFDy8KjN9ZYqong=
-github.com/smartcontractkit/chainlink-relay v0.1.7-0.20231115124244-8303409abccd/go.mod h1:rOayi690YxLlkQy959PD8INhOAIAUi9LoN0G+J/CEf4=
-github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05 h1:DaPSVnxe7oz1QJ+AVIhQWs1W3ubQvwvGo9NbHpMs1OQ=
-github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231023133638-72f4e799ab05/go.mod h1:o0Pn1pbaUluboaK6/yhf8xf7TiFCkyFl6WUOdwqamuU=
-github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb h1:HiluOfEVGOQTM6BTDImOqYdMZZ7qq7fkZ3TJdmItNr8=
-github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231024133459-1ef3a11319eb/go.mod h1:/30flFG4L/iCYAFeA3DUzR0xuHSxAMONiWTzyzvsNwo=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
+github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542/go.mod h1:EpvRoycRD+kniYlz+pCpRT5e+fmPm0mSD/vmND+0oMg=
+github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 h1:D7yb4kgNGVAiD5lFYqm/LW8d5jU66TXyYvSskDiW9yg=
+github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1/go.mod h1:UfW7/PZKon+iDEHtrHOfvMnS5GfYOW/SdMZ6P97rPEk=
+github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 h1:yxaHuDTtj2xxtsR8b+LJw8xDvyr6v/F6GP3InsP4wPI=
+github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
github.com/smartcontractkit/chainlink-testing-framework v1.19.1 h1:MdGM5jIrBi858Cv7qzfl1Qon93YW8InohAlDQqFoIb4=
github.com/smartcontractkit/chainlink-testing-framework v1.19.1/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss=
diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go
index 6da1d94371..ad85506a04 100644
--- a/integration-tests/types/config/node/core.go
+++ b/integration-tests/types/config/node/core.go
@@ -11,7 +11,7 @@ import (
"github.com/segmentio/ksuid"
- relayassets "github.com/smartcontractkit/chainlink-relay/pkg/assets"
+ commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
@@ -171,7 +171,7 @@ func SetChainConfig(
chainConfig = evmcfg.Chain{
AutoCreateKey: ptr.Ptr(true),
FinalityDepth: ptr.Ptr[uint32](1),
- MinContractPayment: relayassets.NewLinkFromJuels(0),
+ MinContractPayment: commonassets.NewLinkFromJuels(0),
}
}
cfg.EVM = evmcfg.EVMConfigs{
@@ -197,7 +197,7 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork) NodeConfigOpt {
Chain: evmcfg.Chain{
AutoCreateKey: ptr.Ptr(true),
FinalityDepth: ptr.Ptr[uint32](50),
- MinContractPayment: relayassets.NewLinkFromJuels(0),
+ MinContractPayment: commonassets.NewLinkFromJuels(0),
LogPollInterval: models.MustNewDuration(1 * time.Second),
HeadTracker: evmcfg.HeadTracker{
HistoryDepth: ptr.Ptr(uint32(100)),
diff --git a/plugins/cmd/chainlink-median/main.go b/plugins/cmd/chainlink-median/main.go
index 87815d24d9..e95bfbb221 100644
--- a/plugins/cmd/chainlink-median/main.go
+++ b/plugins/cmd/chainlink-median/main.go
@@ -3,7 +3,7 @@ package main
import (
"github.com/hashicorp/go-plugin"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median"
)
diff --git a/plugins/cmd/chainlink-medianpoc/main.go b/plugins/cmd/chainlink-medianpoc/main.go
index 325de6538f..eaef96d1b0 100644
--- a/plugins/cmd/chainlink-medianpoc/main.go
+++ b/plugins/cmd/chainlink-medianpoc/main.go
@@ -3,9 +3,9 @@ package main
import (
"github.com/hashicorp/go-plugin"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop/reportingplugins"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/plugins/medianpoc"
)
diff --git a/plugins/config.go b/plugins/config.go
index 938cfd0d00..01574d8209 100644
--- a/plugins/config.go
+++ b/plugins/config.go
@@ -3,7 +3,7 @@ package plugins
import (
"os/exec"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
)
// RegistrarConfig generates contains static configuration inher
diff --git a/plugins/loop_registry.go b/plugins/loop_registry.go
index f402fc6fa1..17ad7cba5a 100644
--- a/plugins/loop_registry.go
+++ b/plugins/loop_registry.go
@@ -5,8 +5,8 @@ import (
"sort"
"sync"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink/v2/core/config"
)
diff --git a/plugins/medianpoc/data_source.go b/plugins/medianpoc/data_source.go
index 7b20f1e5eb..92d4b04ba6 100644
--- a/plugins/medianpoc/data_source.go
+++ b/plugins/medianpoc/data_source.go
@@ -10,8 +10,8 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/plugins/medianpoc/data_source_test.go b/plugins/medianpoc/data_source_test.go
index e9a7945cee..5848705b7b 100644
--- a/plugins/medianpoc/data_source_test.go
+++ b/plugins/medianpoc/data_source_test.go
@@ -6,13 +6,14 @@ import (
"math/big"
"testing"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
)
type mockPipelineRunner struct {
diff --git a/plugins/medianpoc/plugin.go b/plugins/medianpoc/plugin.go
index ceea1eb84f..62b6acc043 100644
--- a/plugins/medianpoc/plugin.go
+++ b/plugins/medianpoc/plugin.go
@@ -9,11 +9,11 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/chainlink-relay/pkg/logger"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop"
- "github.com/smartcontractkit/chainlink-relay/pkg/loop/reportingplugins"
- "github.com/smartcontractkit/chainlink-relay/pkg/services"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop"
+ "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
diff --git a/plugins/medianpoc/plugin_test.go b/plugins/medianpoc/plugin_test.go
index 74a0695c6c..569fcb464b 100644
--- a/plugins/medianpoc/plugin_test.go
+++ b/plugins/medianpoc/plugin_test.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
- "github.com/smartcontractkit/chainlink-relay/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
From 3d25a9e6b858438035e46691cce6e192f6d3fe46 Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Fri, 17 Nov 2023 17:35:05 -0500
Subject: [PATCH 175/327] [TT-724] Fix P2Pv2 For Soak Tests (#11331)
* Fix P2Pv2 For Soak Tests
* Update default
* Tidy
* Fix all OCR1 Configs
* Tidy?
* Tweaked the right setting
---
.github/workflows/on-demand-ocr-soak-test.yml | 2 +-
integration-tests/chaos/ocr_chaos_test.go | 2 +-
integration-tests/config/config.go | 10 +++-------
integration-tests/performance/ocr_test.go | 8 ++------
integration-tests/soak/ocr_test.go | 11 +++++++----
integration-tests/testsetups/ocr.go | 2 +-
6 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml
index b17fdc6beb..567d9510de 100644
--- a/.github/workflows/on-demand-ocr-soak-test.yml
+++ b/.github/workflows/on-demand-ocr-soak-test.yml
@@ -54,7 +54,7 @@ on:
chainlinkVersion:
description: Container image version for the Chainlink nodes
required: true
- default: "1.11.0"
+ default: "2.7.0"
testDuration:
description: Duration of the test (time string)
required: false
diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go
index 5368997daa..a59a0a028c 100644
--- a/integration-tests/chaos/ocr_chaos_test.go
+++ b/integration-tests/chaos/ocr_chaos_test.go
@@ -52,7 +52,7 @@ var (
)
func TestMain(m *testing.M) {
- defaultOCRSettings["toml"] = networks.AddNetworksConfig(config.BaseOCRP2PV1Config, networks.MustGetSelectedNetworksFromEnv()[0])
+ defaultOCRSettings["toml"] = networks.AddNetworksConfig(config.BaseOCR1Config, networks.MustGetSelectedNetworksFromEnv()[0])
os.Exit(m.Run())
}
diff --git a/integration-tests/config/config.go b/integration-tests/config/config.go
index 1da8254e0e..6d00ceb32b 100644
--- a/integration-tests/config/config.go
+++ b/integration-tests/config/config.go
@@ -1,17 +1,13 @@
package config
var (
- BaseOCRP2PV1Config = `[OCR]
+ BaseOCR1Config = `[OCR]
Enabled = true
[P2P]
[P2P.V2]
-Enabled = false
-
-[P2P.V1]
-Enabled = true
-ListenIP = '0.0.0.0'
-ListenPort = 6690`
+AnnounceAddresses = ["0.0.0.0:6690"]
+ListenAddresses = ["0.0.0.0:6690"]`
BaseOCR2Config = `[Feature]
LogPoller = true
diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go
index 7f91f4321a..7e0ed0111d 100644
--- a/integration-tests/performance/ocr_test.go
+++ b/integration-tests/performance/ocr_test.go
@@ -103,13 +103,9 @@ Enabled = true
[P2P]
[P2P.V2]
-Enabled = false
+AnnounceAddresses = ["0.0.0.0:6690"]
+ListenAddresses = ["0.0.0.0:6690"]`
-[P2P]
-[P2P.V1]
-Enabled = true
-ListenIP = '0.0.0.0'
-ListenPort = 6690`
cd := chainlink.New(0, map[string]interface{}{
"replicas": 6,
"toml": networks.AddNetworksConfig(baseTOML, testNetwork),
diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go
index c7d4bc80f6..4f42ff803e 100644
--- a/integration-tests/soak/ocr_test.go
+++ b/integration-tests/soak/ocr_test.go
@@ -1,13 +1,16 @@
package soak
import (
+ "fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
+ "github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
+ "github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
)
@@ -16,10 +19,10 @@ func TestOCRSoak(t *testing.T) {
// Use this variable to pass in any custom EVM specific TOML values to your Chainlink nodes
customNetworkTOML := ``
// Uncomment below for debugging TOML issues on the node
- // network := networks.MustGetSelectedNetworksFromEnv()[0]
- // fmt.Println("Using Chainlink TOML\n---------------------")
- // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network))
- // fmt.Println("---------------------")
+ network := networks.MustGetSelectedNetworksFromEnv()[0]
+ fmt.Println("Using Chainlink TOML\n---------------------")
+ fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customNetworkTOML, network))
+ fmt.Println("---------------------")
ocrSoakTest, err := testsetups.NewOCRSoakTest(t, false)
require.NoError(t, err, "Error creating soak test")
diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go
index dfeb4bb916..a35d915ea9 100644
--- a/integration-tests/testsetups/ocr.go
+++ b/integration-tests/testsetups/ocr.go
@@ -142,7 +142,7 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) {
cd := chainlink.New(0, map[string]any{
"replicas": 6,
- "toml": networks.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customChainlinkNetworkTOML, network),
+ "toml": networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customChainlinkNetworkTOML, network),
"db": map[string]any{
"stateful": true, // stateful DB by default for soak tests
},
From 7e1b9cec1c453713779c3b2358050e95e4c30782 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Mon, 20 Nov 2023 10:47:36 +0100
Subject: [PATCH 176/327] bump packages (#11325)
---
contracts/package.json | 26 +--
contracts/pnpm-lock.yaml | 382 +++++++++++++++++++--------------------
2 files changed, 201 insertions(+), 207 deletions(-)
diff --git a/contracts/package.json b/contracts/package.json
index 6d0b7af6cc..2ceb1602dc 100644
--- a/contracts/package.json
+++ b/contracts/package.json
@@ -18,7 +18,7 @@
"prepublishOnly": "pnpm compile && ./scripts/prepublish_generate_abi_folder",
"publish-beta": "pnpm publish --tag beta",
"publish-prod": "npm dist-tag add @chainlink/contracts@0.8.0 latest",
- "solhint": "solhint --max-warnings 371 \"./src/v0.8/**/*.sol\""
+ "solhint": "solhint --max-warnings 369 \"./src/v0.8/**/*.sol\""
},
"files": [
"src/v0.8",
@@ -47,32 +47,32 @@
"@typechain/ethers-v5": "^7.2.0",
"@typechain/hardhat": "^7.0.0",
"@types/cbor": "5.0.1",
- "@types/chai": "^4.3.9",
- "@types/debug": "^4.1.10",
- "@types/deep-equal-in-any-order": "^1.0.2",
- "@types/mocha": "^10.0.3",
- "@types/node": "^16.18.58",
- "@typescript-eslint/eslint-plugin": "^6.8.0",
- "@typescript-eslint/parser": "^6.8.0",
+ "@types/chai": "^4.3.10",
+ "@types/debug": "^4.1.12",
+ "@types/deep-equal-in-any-order": "^1.0.3",
+ "@types/mocha": "^10.0.4",
+ "@types/node": "^16.18.61",
+ "@typescript-eslint/eslint-plugin": "^6.11.0",
+ "@typescript-eslint/parser": "^6.11.0",
"abi-to-sol": "^0.6.6",
"cbor": "^5.2.0",
"chai": "^4.3.10",
"debug": "^4.3.4",
- "eslint": "^8.51.0",
+ "eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"deep-equal-in-any-order": "^2.0.6",
"eslint-plugin-prettier": "^5.0.1",
"ethereum-waffle": "^3.4.4",
"ethers": "~5.7.2",
- "hardhat": "~2.18.1",
+ "hardhat": "~2.19.1",
"hardhat-abi-exporter": "^2.10.1",
"hardhat-contract-sizer": "^2.10.0",
"hardhat-gas-reporter": "^1.0.9",
"hardhat-ignore-warnings": "^0.2.6",
"istanbul": "^0.4.5",
"moment": "^2.29.4",
- "prettier": "^3.0.3",
- "prettier-plugin-solidity": "1.1.4-dev",
+ "prettier": "^3.1.0",
+ "prettier-plugin-solidity": "1.2.0",
"rlp": "^2.2.7",
"solhint": "^4.0.0",
"solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.0",
@@ -80,7 +80,7 @@
"solidity-coverage": "^0.8.5",
"ts-node": "^10.9.1",
"tslib": "^2.6.2",
- "typechain": "^8.2.0",
+ "typechain": "^8.2.1",
"typescript": "^5.2.2"
},
"dependencies": {
diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml
index ac4efd5f59..fbae71fb3d 100644
--- a/contracts/pnpm-lock.yaml
+++ b/contracts/pnpm-lock.yaml
@@ -39,52 +39,52 @@ devDependencies:
version: 5.7.0
'@nomicfoundation/hardhat-network-helpers':
specifier: ^1.0.9
- version: 1.0.9(hardhat@2.18.1)
+ version: 1.0.9(hardhat@2.19.1)
'@nomiclabs/hardhat-ethers':
specifier: ^2.2.3
- version: 2.2.3(ethers@5.7.2)(hardhat@2.18.1)
+ version: 2.2.3(ethers@5.7.2)(hardhat@2.19.1)
'@nomiclabs/hardhat-etherscan':
specifier: ^3.1.7
- version: 3.1.7(hardhat@2.18.1)
+ version: 3.1.7(hardhat@2.19.1)
'@nomiclabs/hardhat-waffle':
specifier: 2.0.6
- version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.18.1)
+ version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.1)
'@openzeppelin/hardhat-upgrades':
specifier: 1.28.0
- version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.18.1)
+ version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.1)
'@openzeppelin/test-helpers':
specifier: ^0.5.16
version: 0.5.16(bn.js@4.12.0)
'@typechain/ethers-v5':
specifier: ^7.2.0
- version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.2.0)(typescript@5.2.2)
+ version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2)
'@typechain/hardhat':
specifier: ^7.0.0
- version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.18.1)(typechain@8.2.0)
+ version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.1)(typechain@8.3.2)
'@types/cbor':
specifier: 5.0.1
version: 5.0.1
'@types/chai':
- specifier: ^4.3.9
- version: 4.3.9
+ specifier: ^4.3.10
+ version: 4.3.10
'@types/debug':
- specifier: ^4.1.10
- version: 4.1.10
+ specifier: ^4.1.12
+ version: 4.1.12
'@types/deep-equal-in-any-order':
- specifier: ^1.0.2
- version: 1.0.2
+ specifier: ^1.0.3
+ version: 1.0.3
'@types/mocha':
- specifier: ^10.0.3
- version: 10.0.3
+ specifier: ^10.0.4
+ version: 10.0.4
'@types/node':
- specifier: ^16.18.58
- version: 16.18.58
+ specifier: ^16.18.61
+ version: 16.18.61
'@typescript-eslint/eslint-plugin':
- specifier: ^6.8.0
- version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2)
+ specifier: ^6.11.0
+ version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser':
- specifier: ^6.8.0
- version: 6.8.0(eslint@8.51.0)(typescript@5.2.2)
+ specifier: ^6.11.0
+ version: 6.11.0(eslint@8.53.0)(typescript@5.2.2)
abi-to-sol:
specifier: ^0.6.6
version: 0.6.6
@@ -101,14 +101,14 @@ devDependencies:
specifier: ^2.0.6
version: 2.0.6
eslint:
- specifier: ^8.51.0
- version: 8.51.0
+ specifier: ^8.53.0
+ version: 8.53.0
eslint-config-prettier:
specifier: ^9.0.0
- version: 9.0.0(eslint@8.51.0)
+ version: 9.0.0(eslint@8.53.0)
eslint-plugin-prettier:
specifier: ^5.0.1
- version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.51.0)(prettier@3.0.3)
+ version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.53.0)(prettier@3.1.0)
ethereum-waffle:
specifier: ^3.4.4
version: 3.4.4(typescript@5.2.2)
@@ -116,17 +116,17 @@ devDependencies:
specifier: ~5.7.2
version: 5.7.2
hardhat:
- specifier: ~2.18.1
- version: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ specifier: ~2.19.1
+ version: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
hardhat-abi-exporter:
specifier: ^2.10.1
- version: 2.10.1(hardhat@2.18.1)
+ version: 2.10.1(hardhat@2.19.1)
hardhat-contract-sizer:
specifier: ^2.10.0
- version: 2.10.0(hardhat@2.18.1)
+ version: 2.10.0(hardhat@2.19.1)
hardhat-gas-reporter:
specifier: ^1.0.9
- version: 1.0.9(debug@4.3.4)(hardhat@2.18.1)
+ version: 1.0.9(debug@4.3.4)(hardhat@2.19.1)
hardhat-ignore-warnings:
specifier: ^0.2.6
version: 0.2.9
@@ -137,11 +137,11 @@ devDependencies:
specifier: ^2.29.4
version: 2.29.4
prettier:
- specifier: ^3.0.3
- version: 3.0.3
+ specifier: ^3.1.0
+ version: 3.1.0
prettier-plugin-solidity:
- specifier: 1.1.4-dev
- version: 1.1.4-dev(prettier@3.0.3)
+ specifier: 1.2.0
+ version: 1.2.0(prettier@3.1.0)
rlp:
specifier: ^2.2.7
version: 2.2.7
@@ -153,19 +153,19 @@ devDependencies:
version: github.com/smartcontractkit/chainlink-solhint-rules/cfc50b32f95b730304a50deb2e27e88d87115874
solhint-plugin-prettier:
specifier: ^0.1.0
- version: 0.1.0(prettier-plugin-solidity@1.1.4-dev)(prettier@3.0.3)
+ version: 0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.0)
solidity-coverage:
specifier: ^0.8.5
- version: 0.8.5(hardhat@2.18.1)
+ version: 0.8.5(hardhat@2.19.1)
ts-node:
specifier: ^10.9.1
- version: 10.9.1(@types/node@16.18.58)(typescript@5.2.2)
+ version: 10.9.1(@types/node@16.18.61)(typescript@5.2.2)
tslib:
specifier: ^2.6.2
version: 2.6.2
typechain:
- specifier: ^8.2.0
- version: 8.2.0(typescript@5.2.2)
+ specifier: ^8.2.1
+ version: 8.3.2(typescript@5.2.2)
typescript:
specifier: ^5.2.2
version: 5.2.2
@@ -324,13 +324,13 @@ packages:
deprecated: Please use @ensdomains/ens-contracts
dev: true
- /@eslint-community/eslint-utils@4.4.0(eslint@8.51.0):
+ /@eslint-community/eslint-utils@4.4.0(eslint@8.53.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
dependencies:
- eslint: 8.51.0
+ eslint: 8.53.0
eslint-visitor-keys: 3.4.3
dev: true
@@ -339,8 +339,8 @@ packages:
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
dev: true
- /@eslint/eslintrc@2.1.2:
- resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==}
+ /@eslint/eslintrc@2.1.3:
+ resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
@@ -356,8 +356,8 @@ packages:
- supports-color
dev: true
- /@eslint/js@8.51.0:
- resolution: {integrity: sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==}
+ /@eslint/js@8.53.0:
+ resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
@@ -789,11 +789,11 @@ packages:
'@ethersproject/properties': 5.7.0
'@ethersproject/strings': 5.7.0
- /@humanwhocodes/config-array@0.11.11:
- resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==}
+ /@humanwhocodes/config-array@0.11.13:
+ resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==}
engines: {node: '>=10.10.0'}
dependencies:
- '@humanwhocodes/object-schema': 1.2.1
+ '@humanwhocodes/object-schema': 2.0.1
debug: 4.3.4(supports-color@8.1.1)
minimatch: 3.1.2
transitivePeerDependencies:
@@ -805,8 +805,8 @@ packages:
engines: {node: '>=12.22'}
dev: true
- /@humanwhocodes/object-schema@1.2.1:
- resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
+ /@humanwhocodes/object-schema@2.0.1:
+ resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==}
dev: true
/@jridgewell/resolve-uri@3.1.1:
@@ -1037,13 +1037,13 @@ packages:
- utf-8-validate
dev: true
- /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.18.1):
+ /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.19.1):
resolution: {integrity: sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==}
peerDependencies:
hardhat: ^2.9.5
dependencies:
ethereumjs-util: 7.1.5
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
dev: true
/@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0:
@@ -1152,17 +1152,17 @@ packages:
'@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0
dev: true
- /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.18.1):
+ /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.1):
resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==}
peerDependencies:
ethers: ^5.0.0
hardhat: ^2.0.0
dependencies:
ethers: 5.7.2
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
dev: true
- /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.18.1):
+ /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.19.1):
resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==}
peerDependencies:
hardhat: ^2.0.4
@@ -1173,7 +1173,7 @@ packages:
chalk: 2.4.2
debug: 4.3.4(supports-color@8.1.1)
fs-extra: 7.0.1
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
lodash: 4.17.21
semver: 6.3.0
table: 6.8.1
@@ -1182,7 +1182,7 @@ packages:
- supports-color
dev: true
- /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.18.1):
+ /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.1):
resolution: {integrity: sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==}
peerDependencies:
'@nomiclabs/hardhat-ethers': ^2.0.0
@@ -1191,11 +1191,11 @@ packages:
ethers: ^5.0.0
hardhat: ^2.0.0
dependencies:
- '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.18.1)
+ '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.1)
'@types/sinon-chai': 3.2.8
ethereum-waffle: 3.4.4(typescript@5.2.2)
ethers: 5.7.2
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
dev: true
/@openzeppelin/contract-loader@0.6.3:
@@ -1226,7 +1226,7 @@ packages:
- encoding
dev: true
- /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.18.1):
+ /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.1):
resolution: {integrity: sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==}
hasBin: true
peerDependencies:
@@ -1239,15 +1239,15 @@ packages:
'@nomiclabs/harhdat-etherscan':
optional: true
dependencies:
- '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.18.1)
- '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.18.1)
+ '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.1)
+ '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.19.1)
'@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4)
'@openzeppelin/platform-deploy-client': 0.8.0(debug@4.3.4)
'@openzeppelin/upgrades-core': 1.30.1
chalk: 4.1.2
debug: 4.3.4(supports-color@8.1.1)
ethers: 5.7.2
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
proper-lockfile: 4.1.2
transitivePeerDependencies:
- encoding
@@ -1338,12 +1338,12 @@ packages:
config-chain: 1.1.13
dev: true
- /@prettier/sync@0.3.0(prettier@3.0.3):
+ /@prettier/sync@0.3.0(prettier@3.1.0):
resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==}
peerDependencies:
prettier: ^3.0.0
dependencies:
- prettier: 3.0.3
+ prettier: 3.1.0
dev: true
/@resolver-engine/core@0.3.3:
@@ -1506,8 +1506,8 @@ packages:
antlr4ts: 0.5.0-alpha.4
dev: true
- /@solidity-parser/parser@0.16.1:
- resolution: {integrity: sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==}
+ /@solidity-parser/parser@0.16.2:
+ resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==}
dependencies:
antlr4ts: 0.5.0-alpha.4
dev: true
@@ -1663,7 +1663,7 @@ packages:
typechain: 3.0.0(typescript@5.2.2)
dev: true
- /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.2.0)(typescript@5.2.2):
+ /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2):
resolution: {integrity: sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==}
peerDependencies:
'@ethersproject/abi': ^5.0.0
@@ -1679,11 +1679,11 @@ packages:
ethers: 5.7.2
lodash: 4.17.21
ts-essentials: 7.0.3(typescript@5.2.2)
- typechain: 8.2.0(typescript@5.2.2)
+ typechain: 8.3.2(typescript@5.2.2)
typescript: 5.2.2
dev: true
- /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.18.1)(typechain@8.2.0):
+ /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.1)(typechain@8.3.2):
resolution: {integrity: sha512-XB79i5ewg9Met7gMVGfgVkmypicbnI25T5clJBEooMoW2161p4zvKFpoS2O+lBppQyMrPIZkdvl2M3LMDayVcA==}
peerDependencies:
'@ethersproject/abi': ^5.4.7
@@ -1695,23 +1695,23 @@ packages:
dependencies:
'@ethersproject/abi': 5.7.0
'@ethersproject/providers': 5.7.2
- '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.2.0)(typescript@5.2.2)
+ '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2)
ethers: 5.7.2
fs-extra: 9.1.0
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
- typechain: 8.2.0(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
+ typechain: 8.3.2(typescript@5.2.2)
dev: true
/@types/bn.js@4.11.6:
resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/bn.js@5.1.1:
resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/cacheable-request@6.0.2:
@@ -1719,34 +1719,34 @@ packages:
dependencies:
'@types/http-cache-semantics': 4.0.1
'@types/keyv': 3.1.4
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
'@types/responselike': 1.0.0
dev: true
/@types/cbor@5.0.1:
resolution: {integrity: sha512-zVqJy2KzusZPLOgyGJDnOIbu3DxIGGqxYbEwtEEe4Z+la8jwIhOyb+GMrlHafs5tvKruwf8f8qOYP6zTvse/pw==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
- /@types/chai@4.3.9:
- resolution: {integrity: sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==}
+ /@types/chai@4.3.10:
+ resolution: {integrity: sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==}
dev: true
/@types/concat-stream@1.6.1:
resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
- /@types/debug@4.1.10:
- resolution: {integrity: sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==}
+ /@types/debug@4.1.12:
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
dependencies:
'@types/ms': 0.7.31
dev: true
- /@types/deep-equal-in-any-order@1.0.2:
- resolution: {integrity: sha512-IUjUMsroT9qb8d7ySAl5V+iT/7UsJDpIFspTLxBWxCLqeJwwptSvmjvDBEEaZt0qodMyUSoOQkLhqZAkqt6dLg==}
+ /@types/deep-equal-in-any-order@1.0.3:
+ resolution: {integrity: sha512-jT0O3hAILDKeKbdWJ9FZLD0Xdfhz7hMvfyFlRWpirjiEVr8G+GZ4kVIzPIqM6x6Rpp93TNPgOAed4XmvcuV6Qg==}
dev: true
/@types/events@3.0.0:
@@ -1756,7 +1756,7 @@ packages:
/@types/form-data@0.0.33:
resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/glob@7.1.1:
@@ -1764,7 +1764,7 @@ packages:
dependencies:
'@types/events': 3.0.0
'@types/minimatch': 3.0.3
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/http-cache-semantics@4.0.1:
@@ -1778,7 +1778,7 @@ packages:
/@types/keyv@3.1.4:
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/lru-cache@5.1.1:
@@ -1792,11 +1792,11 @@ packages:
/@types/mkdirp@0.5.2:
resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
- /@types/mocha@10.0.3:
- resolution: {integrity: sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==}
+ /@types/mocha@10.0.4:
+ resolution: {integrity: sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==}
dev: true
/@types/ms@0.7.31:
@@ -1806,7 +1806,7 @@ packages:
/@types/node-fetch@2.6.2:
resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
form-data: 3.0.1
dev: true
@@ -1818,8 +1818,8 @@ packages:
resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==}
dev: true
- /@types/node@16.18.58:
- resolution: {integrity: sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA==}
+ /@types/node@16.18.61:
+ resolution: {integrity: sha512-k0N7BqGhJoJzdh6MuQg1V1ragJiXTh8VUBAZTWjJ9cUq23SG0F0xavOwZbhiP4J3y20xd6jxKx+xNUhkMAi76Q==}
dev: true
/@types/node@8.10.66:
@@ -1829,7 +1829,7 @@ packages:
/@types/pbkdf2@3.1.0:
resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/prettier@2.7.1:
@@ -1843,26 +1843,26 @@ packages:
/@types/readable-stream@2.3.15:
resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
safe-buffer: 5.1.2
dev: true
/@types/resolve@0.0.8:
resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/responselike@1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/secp256k1@4.0.3:
resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==}
dependencies:
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
dev: true
/@types/semver@7.5.0:
@@ -1872,7 +1872,7 @@ packages:
/@types/sinon-chai@3.2.8:
resolution: {integrity: sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g==}
dependencies:
- '@types/chai': 4.3.9
+ '@types/chai': 4.3.10
'@types/sinon': 10.0.13
dev: true
@@ -1886,8 +1886,8 @@ packages:
resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==}
dev: true
- /@typescript-eslint/eslint-plugin@6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2):
- resolution: {integrity: sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==}
+ /@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2):
+ resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
@@ -1898,13 +1898,13 @@ packages:
optional: true
dependencies:
'@eslint-community/regexpp': 4.8.0
- '@typescript-eslint/parser': 6.8.0(eslint@8.51.0)(typescript@5.2.2)
- '@typescript-eslint/scope-manager': 6.8.0
- '@typescript-eslint/type-utils': 6.8.0(eslint@8.51.0)(typescript@5.2.2)
- '@typescript-eslint/utils': 6.8.0(eslint@8.51.0)(typescript@5.2.2)
- '@typescript-eslint/visitor-keys': 6.8.0
+ '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
+ '@typescript-eslint/scope-manager': 6.11.0
+ '@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
+ '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
+ '@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1)
- eslint: 8.51.0
+ eslint: 8.53.0
graphemer: 1.4.0
ignore: 5.2.4
natural-compare: 1.4.0
@@ -1915,8 +1915,8 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/parser@6.8.0(eslint@8.51.0)(typescript@5.2.2):
- resolution: {integrity: sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==}
+ /@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.2.2):
+ resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@@ -1925,27 +1925,27 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/scope-manager': 6.8.0
- '@typescript-eslint/types': 6.8.0
- '@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2)
- '@typescript-eslint/visitor-keys': 6.8.0
+ '@typescript-eslint/scope-manager': 6.11.0
+ '@typescript-eslint/types': 6.11.0
+ '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
+ '@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1)
- eslint: 8.51.0
+ eslint: 8.53.0
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
- /@typescript-eslint/scope-manager@6.8.0:
- resolution: {integrity: sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==}
+ /@typescript-eslint/scope-manager@6.11.0:
+ resolution: {integrity: sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
- '@typescript-eslint/types': 6.8.0
- '@typescript-eslint/visitor-keys': 6.8.0
+ '@typescript-eslint/types': 6.11.0
+ '@typescript-eslint/visitor-keys': 6.11.0
dev: true
- /@typescript-eslint/type-utils@6.8.0(eslint@8.51.0)(typescript@5.2.2):
- resolution: {integrity: sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==}
+ /@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
+ resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@@ -1954,23 +1954,23 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2)
- '@typescript-eslint/utils': 6.8.0(eslint@8.51.0)(typescript@5.2.2)
+ '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
+ '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
debug: 4.3.4(supports-color@8.1.1)
- eslint: 8.51.0
+ eslint: 8.53.0
ts-api-utils: 1.0.3(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
- /@typescript-eslint/types@6.8.0:
- resolution: {integrity: sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==}
+ /@typescript-eslint/types@6.11.0:
+ resolution: {integrity: sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
- /@typescript-eslint/typescript-estree@6.8.0(typescript@5.2.2):
- resolution: {integrity: sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==}
+ /@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2):
+ resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
@@ -1978,8 +1978,8 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/types': 6.8.0
- '@typescript-eslint/visitor-keys': 6.8.0
+ '@typescript-eslint/types': 6.11.0
+ '@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
@@ -1990,33 +1990,37 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/utils@6.8.0(eslint@8.51.0)(typescript@5.2.2):
- resolution: {integrity: sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==}
+ /@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
+ resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.0
- '@typescript-eslint/scope-manager': 6.8.0
- '@typescript-eslint/types': 6.8.0
- '@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2)
- eslint: 8.51.0
+ '@typescript-eslint/scope-manager': 6.11.0
+ '@typescript-eslint/types': 6.11.0
+ '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
+ eslint: 8.53.0
semver: 7.5.4
transitivePeerDependencies:
- supports-color
- typescript
dev: true
- /@typescript-eslint/visitor-keys@6.8.0:
- resolution: {integrity: sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==}
+ /@typescript-eslint/visitor-keys@6.11.0:
+ resolution: {integrity: sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
- '@typescript-eslint/types': 6.8.0
+ '@typescript-eslint/types': 6.11.0
eslint-visitor-keys: 3.4.3
dev: true
+ /@ungap/structured-clone@1.2.0:
+ resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ dev: true
+
/@yarnpkg/lockfile@1.1.0:
resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==}
dev: true
@@ -2042,7 +2046,7 @@ packages:
source-map-support: 0.5.21
optionalDependencies:
prettier: 2.8.8
- prettier-plugin-solidity: 1.1.3(prettier@2.8.8)
+ prettier-plugin-solidity: 1.2.0(prettier@2.8.8)
transitivePeerDependencies:
- supports-color
dev: true
@@ -4703,16 +4707,16 @@ packages:
source-map: 0.2.0
dev: true
- /eslint-config-prettier@9.0.0(eslint@8.51.0):
+ /eslint-config-prettier@9.0.0(eslint@8.53.0):
resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
dependencies:
- eslint: 8.51.0
+ eslint: 8.53.0
dev: true
- /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.51.0)(prettier@3.0.3):
+ /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.53.0)(prettier@3.1.0):
resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@@ -4726,9 +4730,9 @@ packages:
eslint-config-prettier:
optional: true
dependencies:
- eslint: 8.51.0
- eslint-config-prettier: 9.0.0(eslint@8.51.0)
- prettier: 3.0.3
+ eslint: 8.53.0
+ eslint-config-prettier: 9.0.0(eslint@8.53.0)
+ prettier: 3.1.0
prettier-linter-helpers: 1.0.0
synckit: 0.8.5
dev: true
@@ -4746,18 +4750,19 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
- /eslint@8.51.0:
- resolution: {integrity: sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==}
+ /eslint@8.53.0:
+ resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@eslint-community/regexpp': 4.8.0
- '@eslint/eslintrc': 2.1.2
- '@eslint/js': 8.51.0
- '@humanwhocodes/config-array': 0.11.11
+ '@eslint/eslintrc': 2.1.3
+ '@eslint/js': 8.53.0
+ '@humanwhocodes/config-array': 0.11.13
'@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
@@ -6206,7 +6211,7 @@ packages:
har-schema: 2.0.0
dev: true
- /hardhat-abi-exporter@2.10.1(hardhat@2.18.1):
+ /hardhat-abi-exporter@2.10.1(hardhat@2.19.1):
resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==}
engines: {node: '>=14.14.0'}
peerDependencies:
@@ -6214,28 +6219,28 @@ packages:
dependencies:
'@ethersproject/abi': 5.7.0
delete-empty: 3.0.0
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
dev: true
- /hardhat-contract-sizer@2.10.0(hardhat@2.18.1):
+ /hardhat-contract-sizer@2.10.0(hardhat@2.19.1):
resolution: {integrity: sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==}
peerDependencies:
hardhat: ^2.0.0
dependencies:
chalk: 4.1.2
cli-table3: 0.6.3
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
strip-ansi: 6.0.1
dev: true
- /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.18.1):
+ /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.19.1):
resolution: {integrity: sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==}
peerDependencies:
hardhat: ^2.0.2
dependencies:
array-uniq: 1.0.3
eth-gas-reporter: 0.2.27(debug@4.3.4)
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
sha1: 1.1.1
transitivePeerDependencies:
- '@codechecks/client'
@@ -6252,8 +6257,8 @@ packages:
solidity-comments: 0.0.2
dev: true
- /hardhat@2.18.1(ts-node@10.9.1)(typescript@5.2.2):
- resolution: {integrity: sha512-b55rW7Ka+fvJeg6oWuBTXoYQEUurevCCankjGNTwczwD3GnkhV9GEei7KUT+9IKmWx3lC+zyxlFxeDbg0gUoHw==}
+ /hardhat@2.19.1(ts-node@10.9.1)(typescript@5.2.2):
+ resolution: {integrity: sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw==}
hasBin: true
peerDependencies:
ts-node: '*'
@@ -6308,7 +6313,7 @@ packages:
solc: 0.7.3(debug@4.3.4)
source-map-support: 0.5.21
stacktrace-parser: 0.1.10
- ts-node: 10.9.1(@types/node@16.18.58)(typescript@5.2.2)
+ ts-node: 10.9.1(@types/node@16.18.61)(typescript@5.2.2)
tsort: 0.0.1
typescript: 5.2.2
undici: 5.19.1
@@ -8878,28 +8883,27 @@ packages:
fast-diff: 1.2.0
dev: true
- /prettier-plugin-solidity@1.1.3(prettier@2.8.8):
- resolution: {integrity: sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==}
- engines: {node: '>=12'}
- requiresBuild: true
+ /prettier-plugin-solidity@1.2.0(prettier@2.8.8):
+ resolution: {integrity: sha512-fgxcUZpVAP+LlRfy5JI5oaAkXGkmsje2VJ5krv/YMm+rcTZbIUwFguSw5f+WFuttMjpDm6wB4UL7WVkArEfiVA==}
+ engines: {node: '>=16'}
peerDependencies:
- prettier: '>=2.3.0 || >=3.0.0-alpha.0'
+ prettier: '>=2.3.0'
dependencies:
- '@solidity-parser/parser': 0.16.0
+ '@solidity-parser/parser': 0.16.2
prettier: 2.8.8
- semver: 7.5.0
+ semver: 7.5.4
solidity-comments-extractor: 0.0.7
dev: true
optional: true
- /prettier-plugin-solidity@1.1.4-dev(prettier@3.0.3):
- resolution: {integrity: sha512-SIDnHIPLN/Pod/dZoyJL07ViEcDxrXoT47ROQshpA/WFgyq/rRzLIc3oWkKfWiicHOD493Y/L1n9ds1GbwPoKQ==}
+ /prettier-plugin-solidity@1.2.0(prettier@3.1.0):
+ resolution: {integrity: sha512-fgxcUZpVAP+LlRfy5JI5oaAkXGkmsje2VJ5krv/YMm+rcTZbIUwFguSw5f+WFuttMjpDm6wB4UL7WVkArEfiVA==}
engines: {node: '>=16'}
peerDependencies:
prettier: '>=2.3.0'
dependencies:
- '@solidity-parser/parser': 0.16.1
- prettier: 3.0.3
+ '@solidity-parser/parser': 0.16.2
+ prettier: 3.1.0
semver: 7.5.4
solidity-comments-extractor: 0.0.7
dev: true
@@ -8910,8 +8914,8 @@ packages:
hasBin: true
dev: true
- /prettier@3.0.3:
- resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==}
+ /prettier@3.1.0:
+ resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==}
engines: {node: '>=14'}
hasBin: true
dev: true
@@ -9637,16 +9641,6 @@ packages:
lru-cache: 6.0.0
dev: true
- /semver@7.5.0:
- resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==}
- engines: {node: '>=10'}
- hasBin: true
- requiresBuild: true
- dependencies:
- lru-cache: 6.0.0
- dev: true
- optional: true
-
/semver@7.5.4:
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
engines: {node: '>=10'}
@@ -9953,16 +9947,16 @@ packages:
- debug
dev: true
- /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.1.4-dev)(prettier@3.0.3):
+ /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.0):
resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==}
peerDependencies:
prettier: ^3.0.0
prettier-plugin-solidity: ^1.0.0
dependencies:
- '@prettier/sync': 0.3.0(prettier@3.0.3)
- prettier: 3.0.3
+ '@prettier/sync': 0.3.0(prettier@3.1.0)
+ prettier: 3.1.0
prettier-linter-helpers: 1.0.0
- prettier-plugin-solidity: 1.1.4-dev(prettier@3.0.3)
+ prettier-plugin-solidity: 1.2.0(prettier@3.1.0)
dev: true
/solhint@4.0.0:
@@ -10107,7 +10101,7 @@ packages:
solidity-comments-win32-x64-msvc: 0.0.2
dev: true
- /solidity-coverage@0.8.5(hardhat@2.18.1):
+ /solidity-coverage@0.8.5(hardhat@2.19.1):
resolution: {integrity: sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==}
hasBin: true
peerDependencies:
@@ -10123,7 +10117,7 @@ packages:
ghost-testrpc: 0.0.2
global-modules: 2.0.0
globby: 10.0.2
- hardhat: 2.18.1(ts-node@10.9.1)(typescript@5.2.2)
+ hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2)
jsonschema: 1.4.0
lodash: 4.17.21
mocha: 10.2.0
@@ -10766,7 +10760,7 @@ packages:
ts-essentials: 1.0.4
dev: true
- /ts-node@10.9.1(@types/node@16.18.58)(typescript@5.2.2):
+ /ts-node@10.9.1(@types/node@16.18.61)(typescript@5.2.2):
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
peerDependencies:
@@ -10785,7 +10779,7 @@ packages:
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3
- '@types/node': 16.18.58
+ '@types/node': 16.18.61
acorn: 8.10.0
acorn-walk: 8.2.0
arg: 4.1.3
@@ -10893,8 +10887,8 @@ packages:
- typescript
dev: true
- /typechain@8.2.0(typescript@5.2.2):
- resolution: {integrity: sha512-tZqhqjxJ9xAS/Lh32jccTjMkpx7sTdUVVHAy5Bf0TIer5QFNYXotiX74oCvoVYjyxUKDK3MXHtMFzMyD3kE+jg==}
+ /typechain@8.3.2(typescript@5.2.2):
+ resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==}
hasBin: true
peerDependencies:
typescript: '>=4.3.0'
From e42562cc435d6136925383e2368e99dbd1663a59 Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Mon, 20 Nov 2023 14:26:13 +0100
Subject: [PATCH 177/327] fix solidity codeowners (#11300)
---
CODEOWNERS | 33 ++++++++++++++++-------
contracts/scripts/native_solc_compile_all | 2 +-
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/CODEOWNERS b/CODEOWNERS
index 5f33e68e51..bd2d0419cf 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -73,23 +73,38 @@ core/scripts/gateway @bolekk @pinebit
# Contracts
/contracts/ @se3000 @connorwstein @RensR
-/contracts/srv/v0.8/automation @smartcontractkit/keepers
+# First we match on project names to catch files like the compilation scripts,
+# gas snapshots and other files not places in the project directories.
+# This could give some false positives, so afterwards we match on the project directories
+# to ensure the entire directory is always owned by the correct team.
+
+/contracts/**/*shared* @RensR
/contracts/**/*keeper* @smartcontractkit/keepers
/contracts/**/*upkeep* @smartcontractkit/keepers
/contracts/**/*automation* @smartcontractkit/keepers
-/contracts/gas-snapshots/automation.gas-snapshot @smartcontractkit/keepers
-
-/contracts/src/v0.8/functions @smartcontractkit/functions
/contracts/**/*functions* @smartcontractkit/functions
-/contracts/gas-snapshots/functions.gas-snapshot @smartcontractkit/functions
+/contracts/**/*llo-feeds* @austinborn @Fletch153
+/contracts/**/*vrf* @smartcontractkit/vrf-team
+/contracts/**/*l2ep* @simsonraj
+/contracts/**/*operatorforwarder* @essamhassan
+/contracts/src/v0.8/automation @smartcontractkit/keepers
+/contracts/src/v0.8/functions @smartcontractkit/functions
+# TODO: interfaces folder, folder should be removed and files moved to the correct folders
+/contracts/src/v0.8/l2ep @simsonraj
/contracts/src/v0.8/llo-feeds @austinborn @Fletch153
-/contracts/gas-snapshots/llo-feeds.gas-snapshot @austinborn @Fletch153
-
+# TODO: mocks folder, folder should be removed and files moved to the correct folders
+/contracts/src/v0.8/operatorforwarder @essamhassan
+/contracts/src/v0.8/shared @RensR
+# TODO: tests folder, folder should be removed and files moved to the correct folders
+# TODO: transmission folder, owner should be found
/contracts/src/v0.8/vrf @smartcontractkit/vrf-team
-/contracts/**/*vrf* @smartcontractkit/vrf-team
-/contracts/src/v0.8/l2ep @simsonraj
+
+
+# At the end, match any files missed by the patterns above
+/contracts/scripts/native_solc_compile_all_events_mock @smartcontractkit/functions
+
# Tests
/integration-tests/ @smartcontractkit/test-tooling-team
diff --git a/contracts/scripts/native_solc_compile_all b/contracts/scripts/native_solc_compile_all
index a2f2f1a0bc..cf1226a2d5 100755
--- a/contracts/scripts/native_solc_compile_all
+++ b/contracts/scripts/native_solc_compile_all
@@ -12,7 +12,7 @@ python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt
# 6 and 7 are legacy contracts, for each other product we have a native_solc_compile_all_$product script
# These scripts can be run individually, or all together with this script.
# To add new CL products, simply write a native_solc_compile_all_$product script and add it to the list below.
-for product in 6 7 feeds functions llo-feeds transmission vrf automation operatorforwarder logpoller events_mock shared
+for product in 6 7 automation events_mock feeds functions llo-feeds logpoller operatorforwarder shared transmission vrf
do
$SCRIPTPATH/native_solc_compile_all_$product
done
From 7e0fa2313580c7497f3a956a4f690c85ede678bb Mon Sep 17 00:00:00 2001
From: Bolek <1416262+bolekk@users.noreply.github.com>
Date: Mon, 20 Nov 2023 07:14:46 -0800
Subject: [PATCH 178/327] [Functions] Rename a few secrets-specific objects to
more generic names (#11340)
These structs/functions are generic enough to be used for non-secrets related requests.
---
core/services/functions/connector_handler.go | 2 +-
.../gateway/handlers/functions/api.go | 10 +++----
.../handlers/functions/handler.functions.go | 28 +++++++++----------
.../functions/handler.functions_test.go | 4 +--
4 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go
index 343980afdd..76608b8ada 100644
--- a/core/services/functions/connector_handler.go
+++ b/core/services/functions/connector_handler.go
@@ -84,7 +84,7 @@ func (h *functionsConnectorHandler) HandleGatewayMessage(ctx context.Context, ga
case functions.MethodSecretsSet:
if balance, err := h.subscriptions.GetMaxUserBalance(fromAddr); err != nil || balance.Cmp(h.minimumBalance.ToInt()) < 0 {
h.lggr.Errorw("user subscription has insufficient balance", "id", gatewayId, "address", fromAddr, "balance", balance, "minBalance", h.minimumBalance)
- response := functions.SecretsResponseBase{
+ response := functions.ResponseBase{
Success: false,
ErrorMessage: "user subscription has insufficient balance",
}
diff --git a/core/services/gateway/handlers/functions/api.go b/core/services/gateway/handlers/functions/api.go
index 979cdb939b..202fa99e41 100644
--- a/core/services/gateway/handlers/functions/api.go
+++ b/core/services/gateway/handlers/functions/api.go
@@ -17,17 +17,17 @@ type SecretsSetRequest struct {
// SecretsListRequest has empty payload
-type SecretsResponseBase struct {
+type ResponseBase struct {
Success bool `json:"success"`
ErrorMessage string `json:"error_message,omitempty"`
}
type SecretsSetResponse struct {
- SecretsResponseBase
+ ResponseBase
}
type SecretsListResponse struct {
- SecretsResponseBase
+ ResponseBase
Rows []SecretsListRow `json:"rows,omitempty"`
}
@@ -38,7 +38,7 @@ type SecretsListRow struct {
}
// Gateway -> User response, which combines responses from several nodes
-type CombinedSecretsResponse struct {
- SecretsResponseBase
+type CombinedResponse struct {
+ ResponseBase
NodeResponses []*api.Message `json:"node_responses"`
}
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index 32a132c075..6cc4581a50 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -75,7 +75,7 @@ type functionsHandler struct {
handlerConfig FunctionsHandlerConfig
donConfig *config.DONConfig
don handlers.DON
- pendingRequests hc.RequestCache[PendingSecretsRequest]
+ pendingRequests hc.RequestCache[PendingRequest]
allowlist OnchainAllowlist
subscriptions OnchainSubscriptions
minimumBalance *assets.Link
@@ -85,7 +85,7 @@ type functionsHandler struct {
lggr logger.Logger
}
-type PendingSecretsRequest struct {
+type PendingRequest struct {
request *api.Message
responses map[string]*api.Message
successful []*api.Message
@@ -136,7 +136,7 @@ func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *con
return nil, err2
}
}
- pendingRequestsCache := hc.NewRequestCache[PendingSecretsRequest](time.Millisecond*time.Duration(cfg.RequestTimeoutMillis), cfg.MaxPendingRequests)
+ pendingRequestsCache := hc.NewRequestCache[PendingRequest](time.Millisecond*time.Duration(cfg.RequestTimeoutMillis), cfg.MaxPendingRequests)
return NewFunctionsHandler(cfg, donConfig, don, pendingRequestsCache, allowlist, subscriptions, cfg.MinimumSubscriptionBalance, userRateLimiter, nodeRateLimiter, lggr), nil
}
@@ -144,7 +144,7 @@ func NewFunctionsHandler(
cfg FunctionsHandlerConfig,
donConfig *config.DONConfig,
don handlers.DON,
- pendingRequestsCache hc.RequestCache[PendingSecretsRequest],
+ pendingRequestsCache hc.RequestCache[PendingRequest],
allowlist OnchainAllowlist,
subscriptions OnchainSubscriptions,
minimumBalance *assets.Link,
@@ -193,7 +193,7 @@ func (h *functionsHandler) HandleUserMessage(ctx context.Context, msg *api.Messa
}
switch msg.Body.Method {
case MethodSecretsSet, MethodSecretsList:
- return h.handleSecretsRequest(ctx, msg, callbackCh)
+ return h.handleRequest(ctx, msg, callbackCh)
default:
h.lggr.Debugw("unsupported method", "method", msg.Body.Method)
promHandlerError.WithLabelValues(h.donConfig.DonId, ErrUnsupportedMethod.Error()).Inc()
@@ -201,11 +201,11 @@ func (h *functionsHandler) HandleUserMessage(ctx context.Context, msg *api.Messa
}
}
-func (h *functionsHandler) handleSecretsRequest(ctx context.Context, msg *api.Message, callbackCh chan<- handlers.UserCallbackPayload) error {
- h.lggr.Debugw("handleSecretsRequest: processing message", "sender", msg.Body.Sender, "messageId", msg.Body.MessageId)
- err := h.pendingRequests.NewRequest(msg, callbackCh, &PendingSecretsRequest{request: msg, responses: make(map[string]*api.Message)})
+func (h *functionsHandler) handleRequest(ctx context.Context, msg *api.Message, callbackCh chan<- handlers.UserCallbackPayload) error {
+ h.lggr.Debugw("handleRequest: processing message", "sender", msg.Body.Sender, "messageId", msg.Body.MessageId)
+ err := h.pendingRequests.NewRequest(msg, callbackCh, &PendingRequest{request: msg, responses: make(map[string]*api.Message)})
if err != nil {
- h.lggr.Warnw("handleSecretsRequest: error adding new request", "sender", msg.Body.Sender, "err", err)
+ h.lggr.Warnw("handleRequest: error adding new request", "sender", msg.Body.Sender, "err", err)
promHandlerError.WithLabelValues(h.donConfig.DonId, err.Error()).Inc()
return err
}
@@ -213,7 +213,7 @@ func (h *functionsHandler) handleSecretsRequest(ctx context.Context, msg *api.Me
for _, member := range h.donConfig.Members {
err := h.don.SendToNode(ctx, member.Address, msg)
if err != nil {
- h.lggr.Debugw("handleSecretsRequest: failed to send to a node", "node", member.Address, "err", err)
+ h.lggr.Debugw("handleRequest: failed to send to a node", "node", member.Address, "err", err)
}
}
return nil
@@ -234,8 +234,8 @@ func (h *functionsHandler) HandleNodeMessage(ctx context.Context, msg *api.Messa
}
}
-// Conforms to ResponseProcessor[*PendingSecretsRequest]
-func (h *functionsHandler) processSecretsResponse(response *api.Message, responseData *PendingSecretsRequest) (*handlers.UserCallbackPayload, *PendingSecretsRequest, error) {
+// Conforms to ResponseProcessor[*PendingRequest]
+func (h *functionsHandler) processSecretsResponse(response *api.Message, responseData *PendingRequest) (*handlers.UserCallbackPayload, *PendingRequest, error) {
if _, exists := responseData.responses[response.Body.Sender]; exists {
return nil, nil, errors.New("duplicate response")
}
@@ -243,7 +243,7 @@ func (h *functionsHandler) processSecretsResponse(response *api.Message, respons
return nil, responseData, errors.New("invalid method")
}
responseData.responses[response.Body.Sender] = response
- var responsePayload SecretsResponseBase
+ var responsePayload ResponseBase
err := json.Unmarshal(response.Body.Payload, &responsePayload)
if err != nil {
responseData.errors = append(responseData.errors, response)
@@ -270,7 +270,7 @@ func (h *functionsHandler) processSecretsResponse(response *api.Message, respons
}
func newSecretsResponse(request *api.Message, success bool, responses []*api.Message) (*handlers.UserCallbackPayload, error) {
- payload := CombinedSecretsResponse{SecretsResponseBase: SecretsResponseBase{Success: success}, NodeResponses: responses}
+ payload := CombinedResponse{ResponseBase: ResponseBase{Success: success}, NodeResponses: responses}
payloadJson, err := json.Marshal(payload)
if err != nil {
return nil, err
diff --git a/core/services/gateway/handlers/functions/handler.functions_test.go b/core/services/gateway/handlers/functions/handler.functions_test.go
index 00334d3068..402823df17 100644
--- a/core/services/gateway/handlers/functions/handler.functions_test.go
+++ b/core/services/gateway/handlers/functions/handler.functions_test.go
@@ -47,7 +47,7 @@ func newFunctionsHandlerForATestDON(t *testing.T, nodes []gc.TestNode, requestTi
require.NoError(t, err)
nodeRateLimiter, err := hc.NewRateLimiter(hc.RateLimiterConfig{GlobalRPS: 100.0, GlobalBurst: 100, PerSenderRPS: 100.0, PerSenderBurst: 100})
require.NoError(t, err)
- pendingRequestsCache := hc.NewRequestCache[functions.PendingSecretsRequest](requestTimeout, 1000)
+ pendingRequestsCache := hc.NewRequestCache[functions.PendingRequest](requestTimeout, 1000)
handler := functions.NewFunctionsHandler(cfg, donConfig, don, pendingRequestsCache, allowlist, subscriptions, minBalance, userRateLimiter, nodeRateLimiter, logger.TestLogger(t))
return handler, don, allowlist, subscriptions
}
@@ -128,7 +128,7 @@ func TestFunctionsHandler_HandleUserMessage_SecretsSet(t *testing.T) {
response := <-callbachCh
require.Equal(t, api.NoError, response.ErrCode)
require.Equal(t, userRequestMsg.Body.MessageId, response.Msg.Body.MessageId)
- var payload functions.CombinedSecretsResponse
+ var payload functions.CombinedResponse
require.NoError(t, json.Unmarshal(response.Msg.Body.Payload, &payload))
require.Equal(t, test.expectedGatewayResult, payload.Success)
require.Equal(t, test.expectedNodeMessageCount, len(payload.NodeResponses))
From c9312c6120809c53418233fb5109d1217b427a8f Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Mon, 20 Nov 2023 09:21:42 -0600
Subject: [PATCH 179/327] core/utils: StopChan & StartStopOnce cleanup (#11341)
* core/utils: make StopChan an alias to common
* use services.StopChan; deprecate utils.StopChan
* use services.StateMachine instead of deprecated utils.StartStopOnce
---
common/client/multi_node.go | 4 +-
common/client/send_only_node.go | 3 +-
common/headtracker/head_broadcaster.go | 2 +-
common/headtracker/head_listener.go | 4 +-
common/headtracker/head_tracker.go | 2 +-
common/txmgr/broadcaster.go | 2 +-
common/txmgr/reaper.go | 8 +-
common/txmgr/txmgr.go | 4 +-
core/chains/evm/client/node.go | 2 +-
core/chains/evm/client/pool.go | 2 +-
core/chains/evm/client/send_only_node.go | 3 +-
core/chains/evm/gas/arbitrum_estimator.go | 2 +-
.../evm/gas/rollups/l1_gas_price_oracle.go | 2 +-
.../evm/gas/suggested_price_estimator.go | 2 +-
core/chains/evm/log/broadcaster.go | 2 +-
core/chains/evm/log/eth_subscriber.go | 4 +-
core/chains/evm/txmgr/broadcaster_test.go | 4 +-
core/chains/evm/txmgr/confirmer_test.go | 4 +-
core/logger/audit/audit_logger.go | 14 ++--
core/services/cron/cron.go | 5 +-
core/services/directrequest/delegate.go | 10 +--
core/services/fluxmonitorv2/flux_monitor.go | 8 +-
core/services/gateway/connectionmanager.go | 6 +-
core/services/gateway/connector/connector.go | 6 +-
.../gateway/handlers/functions/allowlist.go | 4 +-
.../handlers/functions/handler.functions.go | 5 +-
.../handlers/functions/subscriptions.go | 4 +-
core/services/job/spawner.go | 24 +++---
core/services/keeper/upkeep_executer.go | 4 +-
core/services/ocr/contract_tracker.go | 4 +-
core/services/ocr2/plugins/median/plugin.go | 6 +-
.../plugins/ocr2keeper/custom_telemetry.go | 7 +-
.../evm21/autotelemetry21/custom_telemetry.go | 7 +-
.../ocr2keeper/evm21/mercury/v02/request.go | 4 +-
.../ocr2keeper/evm21/mercury/v03/request.go | 4 +-
.../ocr2/plugins/ocr2keeper/evm21/registry.go | 5 +-
core/services/pipeline/runner.go | 2 +-
core/services/promreporter/prom_reporter.go | 2 +-
.../relay/evm/functions/logpoller_wrapper.go | 4 +-
.../relay/evm/mercury/persistence_manager.go | 4 +-
.../services/relay/evm/mercury/transmitter.go | 4 +-
.../relay/evm/mercury/wsrpc/client.go | 4 +-
.../telemetry_ingress_batch_worker.go | 8 +-
.../telemetry_ingress_client.go | 7 +-
core/services/vrf/v1/listener_v1.go | 2 +-
core/services/vrf/v2/listener_v2.go | 4 +-
core/services/webhook/delegate.go | 5 +-
core/utils/thread_control.go | 4 +-
core/utils/utils.go | 60 +++------------
core/utils/utils_example_test.go | 48 ------------
core/utils/utils_test.go | 73 -------------------
plugins/medianpoc/plugin.go | 5 +-
52 files changed, 138 insertions(+), 281 deletions(-)
delete mode 100644 core/utils/utils_example_test.go
diff --git a/common/client/multi_node.go b/common/client/multi_node.go
index acab47f083..48a4d37ad8 100644
--- a/common/client/multi_node.go
+++ b/common/client/multi_node.go
@@ -99,7 +99,7 @@ type multiNode[
activeMu sync.RWMutex
activeNode Node[CHAIN_ID, HEAD, RPC_CLIENT]
- chStop utils.StopChan
+ chStop services.StopChan
wg sync.WaitGroup
sendOnlyErrorParser func(err error) SendTxReturnCode
@@ -146,7 +146,7 @@ func NewMultiNode[
selectionMode: selectionMode,
noNewHeadsThreshold: noNewHeadsThreshold,
nodeSelector: nodeSelector,
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
leaseDuration: leaseDuration,
chainFamily: chainFamily,
sendOnlyErrorParser: sendOnlyErrorParser,
diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go
index 767fff5aee..904916122f 100644
--- a/common/client/send_only_node.go
+++ b/common/client/send_only_node.go
@@ -10,7 +10,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
//go:generate mockery --quiet --name sendOnlyClient --structname mockSendOnlyClient --filename "mock_send_only_client_test.go" --inpackage --case=underscore
@@ -59,7 +58,7 @@ type sendOnlyNode[
log logger.Logger
name string
chainID CHAIN_ID
- chStop utils.StopChan
+ chStop services.StopChan
wg sync.WaitGroup
}
diff --git a/common/headtracker/head_broadcaster.go b/common/headtracker/head_broadcaster.go
index 3efe64e1c3..62b2f47b68 100644
--- a/common/headtracker/head_broadcaster.go
+++ b/common/headtracker/head_broadcaster.go
@@ -31,7 +31,7 @@ type HeadBroadcaster[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] struct
callbacks callbackSet[H, BLOCK_HASH]
mailbox *utils.Mailbox[H]
mutex sync.Mutex
- chClose utils.StopChan
+ chClose services.StopChan
wgDone sync.WaitGroup
latest H
lastCallbackID int
diff --git a/common/headtracker/head_listener.go b/common/headtracker/head_listener.go
index ee4969497a..a3f262f4b7 100644
--- a/common/headtracker/head_listener.go
+++ b/common/headtracker/head_listener.go
@@ -9,6 +9,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -35,7 +37,7 @@ type HeadListener[
config htrktypes.Config
client htrktypes.Client[HTH, S, ID, BLOCK_HASH]
logger logger.Logger
- chStop utils.StopChan
+ chStop services.StopChan
chHeaders chan HTH
headSubscription types.Subscription
connected atomic.Bool
diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go
index bf63675128..810e749a2d 100644
--- a/common/headtracker/head_tracker.go
+++ b/common/headtracker/head_tracker.go
@@ -53,7 +53,7 @@ type HeadTracker[
backfillMB *utils.Mailbox[HTH]
broadcastMB *utils.Mailbox[HTH]
headListener types.HeadListener[HTH, BLOCK_HASH]
- chStop utils.StopChan
+ chStop services.StopChan
wgDone sync.WaitGroup
getNilHead func() HTH
}
diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go
index ba01fb9e2a..d9a72e367a 100644
--- a/common/txmgr/broadcaster.go
+++ b/common/txmgr/broadcaster.go
@@ -135,7 +135,7 @@ type Broadcaster[
// Each key has its own trigger
triggers map[ADDR]chan struct{}
- chStop utils.StopChan
+ chStop services.StopChan
wg sync.WaitGroup
initSync sync.Mutex
diff --git a/common/txmgr/reaper.go b/common/txmgr/reaper.go
index 96bc4860d7..7286efa3a8 100644
--- a/common/txmgr/reaper.go
+++ b/common/txmgr/reaper.go
@@ -5,6 +5,8 @@ import (
"sync/atomic"
"time"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -20,7 +22,7 @@ type Reaper[CHAIN_ID types.ID] struct {
log logger.Logger
latestBlockNum atomic.Int64
trigger chan struct{}
- chStop chan struct{}
+ chStop services.StopChan
chDone chan struct{}
}
@@ -34,7 +36,7 @@ func NewReaper[CHAIN_ID types.ID](lggr logger.Logger, store txmgrtypes.TxHistory
lggr.Named("Reaper"),
atomic.Int64{},
make(chan struct{}, 1),
- make(chan struct{}),
+ make(services.StopChan),
make(chan struct{}),
}
r.latestBlockNum.Store(-1)
@@ -97,7 +99,7 @@ func (r *Reaper[CHAIN_ID]) SetLatestBlockNum(latestBlockNum int64) {
// ReapTxes deletes old txes
func (r *Reaper[CHAIN_ID]) ReapTxes(headNum int64) error {
- ctx, cancel := utils.StopChan(r.chStop).NewCtx()
+ ctx, cancel := r.chStop.NewCtx()
defer cancel()
threshold := r.txConfig.ReaperThreshold()
if threshold == 0 {
diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go
index 24d2428f61..b49c2b72f1 100644
--- a/common/txmgr/txmgr.go
+++ b/common/txmgr/txmgr.go
@@ -90,7 +90,7 @@ type Txm[
reset chan reset
resumeCallback ResumeCallback
- chStop chan struct{}
+ chStop services.StopChan
chSubbed chan struct{}
wg sync.WaitGroup
@@ -228,7 +228,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Reset(addr
// - marks all pending and inflight transactions fatally errored (note: at this point all transactions are either confirmed or fatally errored)
// this must not be run while Broadcaster or Confirmer are running
func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) abandon(addr ADDR) (err error) {
- ctx, cancel := utils.StopChan(b.chStop).NewCtx()
+ ctx, cancel := services.StopChan(b.chStop).NewCtx()
defer cancel()
if err = b.txStore.Abandon(ctx, b.chainID, addr); err != nil {
return fmt.Errorf("abandon failed to update txes for key %s: %w", addr.String(), err)
diff --git a/core/chains/evm/client/node.go b/core/chains/evm/client/node.go
index b690720240..b3ce489cf5 100644
--- a/core/chains/evm/client/node.go
+++ b/core/chains/evm/client/node.go
@@ -1101,7 +1101,7 @@ func (n *node) makeQueryCtx(ctx context.Context) (context.Context, context.Cance
// 1. Passed in ctx cancels
// 2. Passed in channel is closed
// 3. Default timeout is reached (queryTimeout)
-func makeQueryCtx(ctx context.Context, ch utils.StopChan) (context.Context, context.CancelFunc) {
+func makeQueryCtx(ctx context.Context, ch services.StopChan) (context.Context, context.CancelFunc) {
var chCancel, timeoutCancel context.CancelFunc
ctx, chCancel = ch.Ctx(ctx)
ctx, timeoutCancel = context.WithTimeout(ctx, queryTimeout)
diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go
index 18f59b172d..289a402a1c 100644
--- a/core/chains/evm/client/pool.go
+++ b/core/chains/evm/client/pool.go
@@ -72,7 +72,7 @@ type Pool struct {
activeMu sync.RWMutex
activeNode Node
- chStop utils.StopChan
+ chStop services.StopChan
wg sync.WaitGroup
}
diff --git a/core/chains/evm/client/send_only_node.go b/core/chains/evm/client/send_only_node.go
index beb12dbc4d..02f04881c4 100644
--- a/core/chains/evm/client/send_only_node.go
+++ b/core/chains/evm/client/send_only_node.go
@@ -16,7 +16,6 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
//go:generate mockery --quiet --name SendOnlyNode --output ../mocks/ --case=underscore
@@ -69,7 +68,7 @@ type sendOnlyNode struct {
dialed bool
name string
chainID *big.Int
- chStop utils.StopChan
+ chStop services.StopChan
wg sync.WaitGroup
}
diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go
index c79202c731..480abfe721 100644
--- a/core/chains/evm/gas/arbitrum_estimator.go
+++ b/core/chains/evm/gas/arbitrum_estimator.go
@@ -48,7 +48,7 @@ type arbitrumEstimator struct {
chForceRefetch chan (chan struct{})
chInitialised chan struct{}
- chStop utils.StopChan
+ chStop services.StopChan
chDone chan struct{}
}
diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
index 88c61c4934..1a0fe8b8b2 100644
--- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
+++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go
@@ -38,7 +38,7 @@ type l1GasPriceOracle struct {
l1GasPrice *assets.Wei
chInitialised chan struct{}
- chStop utils.StopChan
+ chStop services.StopChan
chDone chan struct{}
}
diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go
index dadec6210c..cd5acbc694 100644
--- a/core/chains/evm/gas/suggested_price_estimator.go
+++ b/core/chains/evm/gas/suggested_price_estimator.go
@@ -40,7 +40,7 @@ type SuggestedPriceEstimator struct {
chForceRefetch chan (chan struct{})
chInitialised chan struct{}
- chStop utils.StopChan
+ chStop services.StopChan
chDone chan struct{}
}
diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go
index 11c282a4d2..d69fd696fd 100644
--- a/core/chains/evm/log/broadcaster.go
+++ b/core/chains/evm/log/broadcaster.go
@@ -110,7 +110,7 @@ type (
utils.DependentAwaiter
- chStop utils.StopChan
+ chStop services.StopChan
wgDone sync.WaitGroup
trackedAddressesCount atomic.Uint32
replayChannel chan replayRequest
diff --git a/core/chains/evm/log/eth_subscriber.go b/core/chains/evm/log/eth_subscriber.go
index cd1b18b474..b4d386140e 100644
--- a/core/chains/evm/log/eth_subscriber.go
+++ b/core/chains/evm/log/eth_subscriber.go
@@ -10,6 +10,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/null"
@@ -21,7 +23,7 @@ type (
ethClient evmclient.Client
config Config
logger logger.Logger
- chStop utils.StopChan
+ chStop services.StopChan
}
)
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 7967478e62..bf480c66af 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -112,10 +112,10 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) {
err = eb.Close()
require.NoError(t, err)
- // Can't start more than once (Broadcaster implements utils.StartStopOnce)
+ // Can't start more than once (Broadcaster uses services.StateMachine)
err = eb.Start(ctx)
require.Error(t, err)
- // Can't close more than once (Broadcaster implements utils.StartStopOnce)
+ // Can't close more than once (Broadcaster uses services.StateMachine)
err = eb.Close()
require.Error(t, err)
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index e17e7993cf..60d0648a54 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -157,10 +157,10 @@ func TestEthConfirmer_Lifecycle(t *testing.T) {
err = ec.Close()
require.NoError(t, err)
- // Can't start more than once (Confirmer implements utils.StartStopOnce)
+ // Can't start more than once (Confirmer uses services.StateMachine)
err = ec.Start(ctx)
require.Error(t, err)
- // Can't close more than once (Confirmer implements utils.StartStopOnce)
+ // Can't close more than once (Confirmer use services.StateMachine)
err = ec.Close()
require.Error(t, err)
diff --git a/core/logger/audit/audit_logger.go b/core/logger/audit/audit_logger.go
index 38afd77a28..ef66a063a5 100644
--- a/core/logger/audit/audit_logger.go
+++ b/core/logger/audit/audit_logger.go
@@ -4,6 +4,8 @@ import (
"bytes"
"context"
"encoding/json"
+ "errors"
+ "fmt"
"io"
"net"
"net/http"
@@ -11,13 +13,11 @@ import (
"os"
"time"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
-
- "github.com/pkg/errors"
)
const bufferCapacity = 2048
@@ -26,7 +26,7 @@ const webRequestTimeout = 10
type Data = map[string]any
type AuditLogger interface {
- services.ServiceCtx
+ services.Service
Audit(eventID EventID, data Data)
}
@@ -47,7 +47,7 @@ type AuditLoggerService struct {
loggingClient HTTPAuditLoggerInterface // Abstract type for sending logs onward
loggingChannel chan wrappedAuditLog
- chStop utils.StopChan
+ chStop services.StopChan
chDone chan struct{}
}
@@ -72,7 +72,7 @@ func NewAuditLogger(logger logger.Logger, config config.AuditLogger) (AuditLogge
hostname, err := os.Hostname()
if err != nil {
- return nil, errors.Errorf("initialization error - unable to get hostname: %s", err)
+ return nil, fmt.Errorf("initialization error - unable to get hostname: %w", err)
}
forwardToUrl, err := config.ForwardToUrl()
diff --git a/core/services/cron/cron.go b/core/services/cron/cron.go
index e89dd1ceab..500192554f 100644
--- a/core/services/cron/cron.go
+++ b/core/services/cron/cron.go
@@ -6,10 +6,11 @@ import (
"github.com/robfig/cron/v3"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// Cron runs a cron jobSpec from a CronSpec
@@ -18,7 +19,7 @@ type Cron struct {
logger logger.Logger
jobSpec job.Job
pipelineRunner pipeline.Runner
- chStop utils.StopChan
+ chStop services.StopChan
}
// NewCronFromJobSpec instantiates a job that executes on a predefined schedule.
diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go
index 9da84fd3ee..687e1cea67 100644
--- a/core/services/directrequest/delegate.go
+++ b/core/services/directrequest/delegate.go
@@ -129,7 +129,7 @@ type listener struct {
pipelineORM pipeline.ORM
mailMon *utils.MailboxMonitor
job job.Job
- runs sync.Map // map[string]utils.StopChan
+ runs sync.Map // map[string]services.StopChan
shutdownWaitGroup sync.WaitGroup
mbOracleRequests *utils.Mailbox[log.Broadcast]
mbOracleCancelRequests *utils.Mailbox[log.Broadcast]
@@ -178,7 +178,7 @@ func (l *listener) Start(context.Context) error {
func (l *listener) Close() error {
return l.StopOnce("DirectRequestListener", func() error {
l.runs.Range(func(key, runCloserChannelIf interface{}) bool {
- runCloserChannel := runCloserChannelIf.(utils.StopChan)
+ runCloserChannel := runCloserChannelIf.(services.StopChan)
close(runCloserChannel)
return true
})
@@ -338,10 +338,10 @@ func (l *listener) handleOracleRequest(request *operator_wrapper.OperatorOracleR
meta := make(map[string]interface{})
meta["oracleRequest"] = oracleRequestToMap(request)
- runCloserChannel := make(utils.StopChan)
+ runCloserChannel := make(services.StopChan)
runCloserChannelIf, loaded := l.runs.LoadOrStore(formatRequestId(request.RequestId), runCloserChannel)
if loaded {
- runCloserChannel = runCloserChannelIf.(utils.StopChan)
+ runCloserChannel = runCloserChannelIf.(services.StopChan)
}
ctx, cancel := runCloserChannel.NewCtx()
defer cancel()
@@ -398,7 +398,7 @@ func (l *listener) allowRequester(requester common.Address) bool {
func (l *listener) handleCancelOracleRequest(request *operator_wrapper.OperatorCancelOracleRequest, lb log.Broadcast) {
runCloserChannelIf, loaded := l.runs.LoadAndDelete(formatRequestId(request.RequestId))
if loaded {
- close(runCloserChannelIf.(utils.StopChan))
+ close(runCloserChannelIf.(services.StopChan))
}
l.markLogConsumed(lb)
}
diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go
index ea853d879d..79dd44c801 100644
--- a/core/services/fluxmonitorv2/flux_monitor.go
+++ b/core/services/fluxmonitorv2/flux_monitor.go
@@ -83,7 +83,7 @@ type FluxMonitor struct {
backlog *utils.BoundedPriorityQueue[log.Broadcast]
chProcessLogs chan struct{}
- chStop chan struct{}
+ chStop services.StopChan
waitOnStop chan struct{}
}
@@ -137,7 +137,7 @@ func NewFluxMonitor(
PriorityFlagChangedLog: 2,
}),
chProcessLogs: make(chan struct{}, 1),
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
waitOnStop: make(chan struct{}),
}
@@ -588,7 +588,7 @@ func (fm *FluxMonitor) respondToAnswerUpdatedLog(log flux_aggregator_wrapper.Flu
// need to poll and submit an answer to the contract regardless of the deviation.
func (fm *FluxMonitor) respondToNewRoundLog(log flux_aggregator_wrapper.FluxAggregatorNewRound, lb log.Broadcast) {
started := time.Now()
- ctx, cancel := utils.StopChan(fm.chStop).NewCtx()
+ ctx, cancel := fm.chStop.NewCtx()
defer cancel()
newRoundLogger := fm.logger.With(
@@ -814,7 +814,7 @@ func (fm *FluxMonitor) checkEligibilityAndAggregatorFunding(roundState flux_aggr
func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker *DeviationChecker, broadcast log.Broadcast) {
started := time.Now()
- ctx, cancel := utils.StopChan(fm.chStop).NewCtx()
+ ctx, cancel := fm.chStop.NewCtx()
defer cancel()
l := fm.logger.With(
diff --git a/core/services/gateway/connectionmanager.go b/core/services/gateway/connectionmanager.go
index ce4a54f4c2..9f88b51e7b 100644
--- a/core/services/gateway/connectionmanager.go
+++ b/core/services/gateway/connectionmanager.go
@@ -72,7 +72,7 @@ type donConnectionManager struct {
handler handlers.Handler
codec api.Codec
closeWait sync.WaitGroup
- shutdownCh chan struct{}
+ shutdownCh services.StopChan
lggr logger.Logger
}
@@ -271,7 +271,7 @@ func (m *donConnectionManager) SendToNode(ctx context.Context, nodeAddress strin
}
func (m *donConnectionManager) readLoop(nodeAddress string, nodeState *nodeState) {
- ctx, _ := utils.StopChan(m.shutdownCh).NewCtx()
+ ctx, _ := m.shutdownCh.NewCtx()
for {
select {
case <-m.shutdownCh:
@@ -296,7 +296,7 @@ func (m *donConnectionManager) readLoop(nodeAddress string, nodeState *nodeState
}
func (m *donConnectionManager) heartbeatLoop(intervalSec uint32) {
- ctx, _ := utils.StopChan(m.shutdownCh).NewCtx()
+ ctx, _ := m.shutdownCh.NewCtx()
defer m.closeWait.Done()
if intervalSec == 0 {
diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go
index 0694e9ad15..27db8fd44b 100644
--- a/core/services/gateway/connector/connector.go
+++ b/core/services/gateway/connector/connector.go
@@ -57,7 +57,7 @@ type gatewayConnector struct {
gateways map[string]*gatewayState
urlToId map[string]string
closeWait sync.WaitGroup
- shutdownCh chan struct{}
+ shutdownCh services.StopChan
lggr logger.Logger
}
@@ -143,7 +143,7 @@ func (c *gatewayConnector) SendToGateway(ctx context.Context, gatewayId string,
}
func (c *gatewayConnector) readLoop(gatewayState *gatewayState) {
- ctx, cancel := utils.StopChan(c.shutdownCh).NewCtx()
+ ctx, cancel := c.shutdownCh.NewCtx()
defer cancel()
for {
@@ -168,7 +168,7 @@ func (c *gatewayConnector) readLoop(gatewayState *gatewayState) {
func (c *gatewayConnector) reconnectLoop(gatewayState *gatewayState) {
redialBackoff := utils.NewRedialBackoff()
- ctx, cancel := utils.StopChan(c.shutdownCh).NewCtx()
+ ctx, cancel := c.shutdownCh.NewCtx()
defer cancel()
for {
diff --git a/core/services/gateway/handlers/functions/allowlist.go b/core/services/gateway/handlers/functions/allowlist.go
index 3ba9a65d57..0a18d6e6d8 100644
--- a/core/services/gateway/handlers/functions/allowlist.go
+++ b/core/services/gateway/handlers/functions/allowlist.go
@@ -55,7 +55,7 @@ type onchainAllowlist struct {
blockConfirmations *big.Int
lggr logger.Logger
closeWait sync.WaitGroup
- stopCh utils.StopChan
+ stopCh services.StopChan
}
func NewOnchainAllowlist(client evmclient.Client, config OnchainAllowlistConfig, lggr logger.Logger) (OnchainAllowlist, error) {
@@ -78,7 +78,7 @@ func NewOnchainAllowlist(client evmclient.Client, config OnchainAllowlistConfig,
contractV1: contractV1,
blockConfirmations: big.NewInt(int64(config.BlockConfirmations)),
lggr: lggr.Named("OnchainAllowlist"),
- stopCh: make(utils.StopChan),
+ stopCh: make(services.StopChan),
}
emptyMap := make(map[common.Address]struct{})
allowlist.allowlist.Store(&emptyMap)
diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go
index 6cc4581a50..3269caa2d6 100644
--- a/core/services/gateway/handlers/functions/handler.functions.go
+++ b/core/services/gateway/handlers/functions/handler.functions.go
@@ -21,7 +21,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/config"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers"
hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
var (
@@ -81,7 +80,7 @@ type functionsHandler struct {
minimumBalance *assets.Link
userRateLimiter *hc.RateLimiter
nodeRateLimiter *hc.RateLimiter
- chStop utils.StopChan
+ chStop services.StopChan
lggr logger.Logger
}
@@ -161,7 +160,7 @@ func NewFunctionsHandler(
minimumBalance: minimumBalance,
userRateLimiter: userRateLimiter,
nodeRateLimiter: nodeRateLimiter,
- chStop: make(utils.StopChan),
+ chStop: make(services.StopChan),
lggr: lggr,
}
}
diff --git a/core/services/gateway/handlers/functions/subscriptions.go b/core/services/gateway/handlers/functions/subscriptions.go
index 7a59e05731..ebffbbdd20 100644
--- a/core/services/gateway/handlers/functions/subscriptions.go
+++ b/core/services/gateway/handlers/functions/subscriptions.go
@@ -49,7 +49,7 @@ type onchainSubscriptions struct {
lggr logger.Logger
closeWait sync.WaitGroup
rwMutex sync.RWMutex
- stopCh utils.StopChan
+ stopCh services.StopChan
}
func NewOnchainSubscriptions(client evmclient.Client, config OnchainSubscriptionsConfig, lggr logger.Logger) (OnchainSubscriptions, error) {
@@ -70,7 +70,7 @@ func NewOnchainSubscriptions(client evmclient.Client, config OnchainSubscription
router: router,
blockConfirmations: big.NewInt(int64(config.BlockConfirmations)),
lggr: lggr.Named("OnchainSubscriptions"),
- stopCh: make(utils.StopChan),
+ stopCh: make(services.StopChan),
}, nil
}
diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go
index 5656011e14..5ed017b874 100644
--- a/core/services/job/spawner.go
+++ b/core/services/job/spawner.go
@@ -11,10 +11,9 @@ import (
"github.com/jmoiron/sqlx"
- commonservices "github.com/smartcontractkit/chainlink-common/pkg/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -26,7 +25,7 @@ type (
// services that perform the work described by job specs. Each active job spec
// has 1 or more of these services associated with it.
Spawner interface {
- services.ServiceCtx
+ services.Service
// CreateJob creates a new job and starts services.
// All services must start without errors for the job to be active.
@@ -42,18 +41,23 @@ type (
StartService(ctx context.Context, spec Job, qopts ...pg.QOpt) error
}
+ Checker interface {
+ Register(service services.HealthReporter) error
+ Unregister(name string) error
+ }
+
spawner struct {
- commonservices.StateMachine
+ services.StateMachine
orm ORM
config Config
- checker services.Checker
+ checker Checker
jobTypeDelegates map[Type]Delegate
activeJobs map[int32]activeJob
activeJobsMu sync.RWMutex
q pg.Q
lggr logger.Logger
- chStop utils.StopChan
+ chStop services.StopChan
lbDependentAwaiters []utils.DependentAwaiter
}
@@ -86,7 +90,7 @@ type (
var _ Spawner = (*spawner)(nil)
-func NewSpawner(orm ORM, config Config, checker services.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, db *sqlx.DB, lggr logger.Logger, lbDependentAwaiters []utils.DependentAwaiter) *spawner {
namedLogger := lggr.Named("JobSpawner")
s := &spawner{
orm: orm,
@@ -96,7 +100,7 @@ func NewSpawner(orm ORM, config Config, checker services.Checker, jobTypeDelegat
q: pg.NewQ(db, namedLogger, config),
lggr: namedLogger,
activeJobs: make(map[int32]activeJob),
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
lbDependentAwaiters: lbDependentAwaiters,
}
return s
@@ -170,7 +174,7 @@ func (js *spawner) stopService(jobID int32) {
for i := len(aj.services) - 1; i >= 0; i-- {
service := aj.services[i]
sLggr := lggr.With("subservice", i, "serviceType", reflect.TypeOf(service))
- if c, ok := service.(commonservices.HealthReporter); ok {
+ if c, ok := service.(services.HealthReporter); ok {
if err := js.checker.Unregister(c.Name()); err != nil {
sLggr.Warnw("Failed to unregister service from health checker", "err", err)
}
@@ -230,7 +234,7 @@ func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) e
lggr.Criticalw("Error starting service for job", "err", err)
return err
}
- if c, ok := srv.(commonservices.HealthReporter); ok {
+ if c, ok := srv.(services.HealthReporter); ok {
err = js.checker.Register(c)
if err != nil {
lggr.Errorw("Error registering service with health checker", "err", err)
diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go
index ece6f85b06..84349ba2dc 100644
--- a/core/services/keeper/upkeep_executer.go
+++ b/core/services/keeper/upkeep_executer.go
@@ -55,7 +55,7 @@ type UpkeepExecuterConfig interface {
// UpkeepExecuter implements the logic to communicate with KeeperRegistry
type UpkeepExecuter struct {
services.StateMachine
- chStop utils.StopChan
+ chStop services.StopChan
ethClient evmclient.Client
config UpkeepExecuterConfig
executionQueue chan struct{}
@@ -83,7 +83,7 @@ func NewUpkeepExecuter(
effectiveKeeperAddress common.Address,
) *UpkeepExecuter {
return &UpkeepExecuter{
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
ethClient: ethClient,
executionQueue: make(chan struct{}, executionQueueSize),
headBroadcaster: headBroadcaster,
diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go
index 5fecbe8628..4f79bcfc31 100644
--- a/core/services/ocr/contract_tracker.go
+++ b/core/services/ocr/contract_tracker.go
@@ -74,7 +74,7 @@ type (
unsubscribeHeads func()
// Start/Stop lifecycle
- chStop utils.StopChan
+ chStop services.StopChan
wg sync.WaitGroup
unsubscribeLogs func()
@@ -134,7 +134,7 @@ func NewOCRContractTracker(
cfg: cfg,
mailMon: mailMon,
headBroadcaster: headBroadcaster,
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
latestRoundRequested: offchainaggregator.OffchainAggregatorRoundRequested{},
configsMB: utils.NewMailbox[ocrtypes.ContractConfig](configMailboxSanityLimit),
chConfigs: make(chan ocrtypes.ContractConfig),
diff --git a/core/services/ocr2/plugins/median/plugin.go b/core/services/ocr2/plugins/median/plugin.go
index 4f83c4b5dd..11197f0917 100644
--- a/core/services/ocr2/plugins/median/plugin.go
+++ b/core/services/ocr2/plugins/median/plugin.go
@@ -10,17 +10,15 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink-common/pkg/types"
-
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type Plugin struct {
loop.Plugin
- stop utils.StopChan
+ stop services.StopChan
}
func NewPlugin(lggr logger.Logger) *Plugin {
- return &Plugin{Plugin: loop.Plugin{Logger: lggr}, stop: make(utils.StopChan)}
+ return &Plugin{Plugin: loop.Plugin{Logger: lggr}, stop: make(services.StopChan)}
}
func (p *Plugin) NewMedianFactory(ctx context.Context, provider types.MedianProvider, dataSource, juelsPerFeeCoin median.DataSource, errorLog loop.ErrorLog) (loop.ReportingPluginFactory, error) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
index 0f03ae5bd0..6d52c0e8d2 100644
--- a/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
@@ -5,12 +5,15 @@ import (
"encoding/hex"
"time"
+ "google.golang.org/protobuf/proto"
+
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "google.golang.org/protobuf/proto"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
@@ -19,7 +22,7 @@ import (
)
type AutomationCustomTelemetryService struct {
- utils.StartStopOnce
+ services.StateMachine
monitoringEndpoint commontypes.MonitoringEndpoint
blockSubscriber *evm21.BlockSubscriber
blockSubChanID int
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
index 93f35ce0d2..0cf0bbef5c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
@@ -5,12 +5,15 @@ import (
"encoding/hex"
"time"
+ "google.golang.org/protobuf/proto"
+
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "google.golang.org/protobuf/proto"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
@@ -19,7 +22,7 @@ import (
)
type AutomationCustomTelemetryService struct {
- utils.StartStopOnce
+ services.StateMachine
monitoringEndpoint commontypes.MonitoringEndpoint
blockSubscriber *evm21.BlockSubscriber
blockSubChanID int
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go
index 55436937d1..4ce7893a0b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/request.go
@@ -14,6 +14,8 @@ import (
"github.com/avast/retry-go/v4"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -34,7 +36,7 @@ type MercuryV02Response struct {
}
type client struct {
- utils.StartStopOnce
+ services.StateMachine
mercuryConfig mercury.MercuryConfigProvider
httpClient mercury.HttpClient
threadCtrl utils.ThreadControl
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go
index 3697dca53c..1c60788974 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/request.go
@@ -14,6 +14,8 @@ import (
"github.com/avast/retry-go/v4"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -43,7 +45,7 @@ type MercuryV03Report struct {
}
type client struct {
- utils.StartStopOnce
+ services.StateMachine
mercuryConfig mercury.MercuryConfigProvider
httpClient mercury.HttpClient
threadCtrl utils.ThreadControl
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
index 252d2d91c7..afb1a7cf6c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
@@ -17,7 +17,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/multierr"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
@@ -31,6 +31,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -166,7 +167,7 @@ func (c *MercuryConfig) SetPluginRetry(k string, v interface{}, d time.Duration)
}
type EvmRegistry struct {
- utils.StartStopOnce
+ services.StateMachine
threadCtrl utils.ThreadControl
lggr logger.Logger
poller logpoller.LogPoller
diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go
index edb1d337af..388f7358ef 100644
--- a/core/services/pipeline/runner.go
+++ b/core/services/pipeline/runner.go
@@ -68,7 +68,7 @@ type runner struct {
// test helper
runFinished func(*Run)
- chStop utils.StopChan
+ chStop services.StopChan
wgDone sync.WaitGroup
}
diff --git a/core/services/promreporter/prom_reporter.go b/core/services/promreporter/prom_reporter.go
index 2306640bea..d115b1022c 100644
--- a/core/services/promreporter/prom_reporter.go
+++ b/core/services/promreporter/prom_reporter.go
@@ -27,7 +27,7 @@ type (
lggr logger.Logger
backend PrometheusBackend
newHeads *utils.Mailbox[*evmtypes.Head]
- chStop utils.StopChan
+ chStop services.StopChan
wgDone sync.WaitGroup
reportPeriod time.Duration
}
diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go
index 230185d0ad..95f45022ab 100644
--- a/core/services/relay/evm/functions/logpoller_wrapper.go
+++ b/core/services/relay/evm/functions/logpoller_wrapper.go
@@ -39,7 +39,7 @@ type logPollerWrapper struct {
detectedResponses detectedEvents
mu sync.Mutex
closeWait sync.WaitGroup
- stopCh utils.StopChan
+ stopCh services.StopChan
lggr logger.Logger
}
@@ -106,7 +106,7 @@ func NewLogPollerWrapper(routerContractAddress common.Address, pluginConfig conf
logPoller: logPoller,
client: client,
subscribers: make(map[string]evmRelayTypes.RouteUpdateSubscriber),
- stopCh: make(utils.StopChan),
+ stopCh: make(services.StopChan),
lggr: lggr,
}, nil
}
diff --git a/core/services/relay/evm/mercury/persistence_manager.go b/core/services/relay/evm/mercury/persistence_manager.go
index 69dfce9c16..779e275f15 100644
--- a/core/services/relay/evm/mercury/persistence_manager.go
+++ b/core/services/relay/evm/mercury/persistence_manager.go
@@ -24,7 +24,7 @@ type PersistenceManager struct {
orm ORM
once services.StateMachine
- stopCh utils.StopChan
+ stopCh services.StopChan
wg sync.WaitGroup
deleteMu sync.Mutex
@@ -41,7 +41,7 @@ func NewPersistenceManager(lggr logger.Logger, orm ORM, jobID int32, maxTransmit
return &PersistenceManager{
lggr: lggr.Named("MercuryPersistenceManager"),
orm: orm,
- stopCh: make(chan struct{}),
+ stopCh: make(services.StopChan),
jobID: jobID,
maxTransmitQueueSize: maxTransmitQueueSize,
flushDeletesFrequency: flushDeletesFrequency,
diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go
index 73aa10243f..d5346ad28c 100644
--- a/core/services/relay/evm/mercury/transmitter.go
+++ b/core/services/relay/evm/mercury/transmitter.go
@@ -115,7 +115,7 @@ type mercuryTransmitter struct {
jobID int32
fromAccount string
- stopCh utils.StopChan
+ stopCh services.StopChan
queue *TransmitQueue
wg sync.WaitGroup
@@ -161,7 +161,7 @@ func NewTransmitter(lggr logger.Logger, cfgTracker ConfigTracker, rpcClient wsrp
feedID,
jobID,
fmt.Sprintf("%x", fromAccount),
- make(chan (struct{})),
+ make(services.StopChan),
nil,
sync.WaitGroup{},
make(chan *pb.TransmitRequest, maxDeleteQueueSize),
diff --git a/core/services/relay/evm/mercury/wsrpc/client.go b/core/services/relay/evm/mercury/wsrpc/client.go
index c4db80a58d..c04c00074a 100644
--- a/core/services/relay/evm/mercury/wsrpc/client.go
+++ b/core/services/relay/evm/mercury/wsrpc/client.go
@@ -84,7 +84,7 @@ type client struct {
consecutiveTimeoutCnt atomic.Int32
wg sync.WaitGroup
- chStop utils.StopChan
+ chStop services.StopChan
chResetTransport chan struct{}
timeoutCountMetric prometheus.Counter
@@ -106,7 +106,7 @@ func newClient(lggr logger.Logger, clientPrivKey csakey.KeyV2, serverPubKey []by
serverURL: serverURL,
logger: lggr.Named("WSRPC").With("mercuryServerURL", serverURL),
chResetTransport: make(chan struct{}, 1),
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
timeoutCountMetric: timeoutCount.WithLabelValues(serverURL),
dialCountMetric: dialCount.WithLabelValues(serverURL),
dialSuccessCountMetric: dialSuccessCount.WithLabelValues(serverURL),
diff --git a/core/services/synchronization/telemetry_ingress_batch_worker.go b/core/services/synchronization/telemetry_ingress_batch_worker.go
index 141eb30c81..e7ea659581 100644
--- a/core/services/synchronization/telemetry_ingress_batch_worker.go
+++ b/core/services/synchronization/telemetry_ingress_batch_worker.go
@@ -6,23 +6,23 @@ import (
"sync/atomic"
"time"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
// telemetryIngressBatchWorker pushes telemetry in batches to the ingress server via wsrpc.
// A worker is created per ContractID.
type telemetryIngressBatchWorker struct {
- services.ServiceCtx
+ services.Service
telemMaxBatchSize uint
telemSendInterval time.Duration
telemSendTimeout time.Duration
telemClient telemPb.TelemClient
wgDone *sync.WaitGroup
- chDone utils.StopChan
+ chDone services.StopChan
chTelemetry chan TelemPayload
contractID string
telemType TelemetryType
diff --git a/core/services/synchronization/telemetry_ingress_client.go b/core/services/synchronization/telemetry_ingress_client.go
index b889b3fc97..b566199fdc 100644
--- a/core/services/synchronization/telemetry_ingress_client.go
+++ b/core/services/synchronization/telemetry_ingress_client.go
@@ -15,7 +15,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type NoopTelemetryIngressClient struct{}
@@ -46,7 +45,7 @@ type telemetryIngressClient struct {
lggr logger.Logger
wgDone sync.WaitGroup
- chDone chan struct{}
+ chDone services.StopChan
dropMessageCount atomic.Uint32
chTelemetry chan TelemPayload
}
@@ -61,7 +60,7 @@ func NewTelemetryIngressClient(url *url.URL, serverPubKeyHex string, ks keystore
logging: logging,
lggr: lggr.Named("TelemetryIngressClient"),
chTelemetry: make(chan TelemPayload, telemBufferSize),
- chDone: make(chan struct{}),
+ chDone: make(services.StopChan),
}
}
@@ -132,7 +131,7 @@ func (tc *telemetryIngressClient) connect(ctx context.Context, clientPrivKey []b
func (tc *telemetryIngressClient) handleTelemetry() {
go func() {
- ctx, cancel := utils.StopChan(tc.chDone).NewCtx()
+ ctx, cancel := tc.chDone.NewCtx()
defer cancel()
for {
select {
diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go
index 566e5ac9bd..3e958801cd 100644
--- a/core/services/vrf/v1/listener_v1.go
+++ b/core/services/vrf/v1/listener_v1.go
@@ -58,7 +58,7 @@ type Listener struct {
GethKs vrfcommon.GethKeyStore
MailMon *utils.MailboxMonitor
ReqLogs *utils.Mailbox[log.Broadcast]
- ChStop utils.StopChan
+ ChStop services.StopChan
WaitOnStop chan struct{}
NewHead chan struct{}
LatestHead uint64
diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go
index 5b73ac9e24..7f23e02277 100644
--- a/core/services/vrf/v2/listener_v2.go
+++ b/core/services/vrf/v2/listener_v2.go
@@ -128,7 +128,7 @@ func New(
q: q,
gethks: gethks,
reqLogs: reqLogs,
- chStop: make(chan struct{}),
+ chStop: make(services.StopChan),
reqAdded: reqAdded,
blockNumberToReqID: pairing.New(),
latestHeadMu: sync.RWMutex{},
@@ -183,7 +183,7 @@ type listenerV2 struct {
q pg.Q
gethks keystore.Eth
reqLogs *utils.Mailbox[log.Broadcast]
- chStop utils.StopChan
+ chStop services.StopChan
// We can keep these pending logs in memory because we
// only mark them confirmed once we send a corresponding fulfillment transaction.
// So on node restart in the middle of processing, the lb will resend them.
diff --git a/core/services/webhook/delegate.go b/core/services/webhook/delegate.go
index f5a8d553f2..237245b81c 100644
--- a/core/services/webhook/delegate.go
+++ b/core/services/webhook/delegate.go
@@ -8,11 +8,12 @@ import (
"github.com/pkg/errors"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
+
"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/services/pipeline"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
type (
@@ -111,7 +112,7 @@ func newWebhookJobRunner(runner pipeline.Runner, lggr logger.Logger) *webhookJob
type registeredJob struct {
job.Job
- chRemove utils.StopChan
+ chRemove services.StopChan
}
func (r *webhookJobRunner) addSpec(spec job.Job) error {
diff --git a/core/utils/thread_control.go b/core/utils/thread_control.go
index 8f7fff4249..52cda82797 100644
--- a/core/utils/thread_control.go
+++ b/core/utils/thread_control.go
@@ -3,6 +3,8 @@ package utils
import (
"context"
"sync"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
var _ ThreadControl = &threadControl{}
@@ -25,7 +27,7 @@ func NewThreadControl() *threadControl {
type threadControl struct {
threadsWG sync.WaitGroup
- stop StopChan
+ stop services.StopChan
}
func (tc *threadControl) Go(fn func(context.Context)) {
diff --git a/core/utils/utils.go b/core/utils/utils.go
index a2e418fe04..69597fb9e4 100644
--- a/core/utils/utils.go
+++ b/core/utils/utils.go
@@ -399,68 +399,28 @@ func WaitGroupChan(wg *sync.WaitGroup) <-chan struct{} {
}
// WithCloseChan wraps a context so that it is canceled if the passed in channel is closed.
-// Deprecated: Call StopChan.Ctx directly
+// Deprecated: Call [services.StopChan.Ctx] directly
func WithCloseChan(parentCtx context.Context, chStop chan struct{}) (context.Context, context.CancelFunc) {
- return StopChan(chStop).Ctx(parentCtx)
+ return services.StopChan(chStop).Ctx(parentCtx)
}
// ContextFromChan creates a context that finishes when the provided channel receives or is closed.
-// Deprecated: Call StopChan.NewCtx directly.
+// Deprecated: Call [services.StopChan.NewCtx] directly.
func ContextFromChan(chStop chan struct{}) (context.Context, context.CancelFunc) {
- return StopChan(chStop).NewCtx()
+ return services.StopChan(chStop).NewCtx()
}
// ContextFromChanWithTimeout creates a context with a timeout that finishes when the provided channel receives or is closed.
-// Deprecated: Call StopChan.CtxCancel directly
+// Deprecated: Call [services.StopChan.CtxCancel] directly
func ContextFromChanWithTimeout(chStop chan struct{}, timeout time.Duration) (context.Context, context.CancelFunc) {
- return StopChan(chStop).CtxCancel(context.WithTimeout(context.Background(), timeout))
+ return services.StopChan(chStop).CtxCancel(context.WithTimeout(context.Background(), timeout))
}
-// A StopChan signals when some work should stop.
-type StopChan chan struct{}
+// Deprecated: use services.StopChan
+type StopChan = services.StopChan
-// NewCtx returns a background [context.Context] that is cancelled when StopChan is closed.
-func (s StopChan) NewCtx() (context.Context, context.CancelFunc) {
- return StopRChan((<-chan struct{})(s)).NewCtx()
-}
-
-// Ctx cancels a [context.Context] when StopChan is closed.
-func (s StopChan) Ctx(ctx context.Context) (context.Context, context.CancelFunc) {
- return StopRChan((<-chan struct{})(s)).Ctx(ctx)
-}
-
-// CtxCancel cancels a [context.Context] when StopChan is closed.
-// Returns ctx and cancel unmodified, for convenience.
-func (s StopChan) CtxCancel(ctx context.Context, cancel context.CancelFunc) (context.Context, context.CancelFunc) {
- return StopRChan((<-chan struct{})(s)).CtxCancel(ctx, cancel)
-}
-
-// A StopRChan signals when some work should stop.
-// This version is receive-only.
-type StopRChan <-chan struct{}
-
-// NewCtx returns a background [context.Context] that is cancelled when StopChan is closed.
-func (s StopRChan) NewCtx() (context.Context, context.CancelFunc) {
- return s.Ctx(context.Background())
-}
-
-// Ctx cancels a [context.Context] when StopChan is closed.
-func (s StopRChan) Ctx(ctx context.Context) (context.Context, context.CancelFunc) {
- return s.CtxCancel(context.WithCancel(ctx))
-}
-
-// CtxCancel cancels a [context.Context] when StopChan is closed.
-// Returns ctx and cancel unmodified, for convenience.
-func (s StopRChan) CtxCancel(ctx context.Context, cancel context.CancelFunc) (context.Context, context.CancelFunc) {
- go func() {
- select {
- case <-s:
- cancel()
- case <-ctx.Done():
- }
- }()
- return ctx, cancel
-}
+// Deprecated: use services.StopRChan
+type StopRChan = services.StopRChan
// DependentAwaiter contains Dependent funcs
type DependentAwaiter interface {
diff --git a/core/utils/utils_example_test.go b/core/utils/utils_example_test.go
deleted file mode 100644
index 0ca9d0be88..0000000000
--- a/core/utils/utils_example_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package utils
-
-import (
- "context"
- "sync"
- "time"
-)
-
-func ExampleStopChan() {
- stopCh := make(StopChan)
-
- work := func(context.Context) {}
-
- a := func(ctx context.Context, done func()) {
- defer done()
- ctx, cancel := stopCh.Ctx(ctx)
- defer cancel()
- work(ctx)
- }
-
- b := func(ctx context.Context, done func()) {
- defer done()
- ctx, cancel := stopCh.CtxCancel(context.WithTimeout(ctx, time.Second))
- defer cancel()
- work(ctx)
- }
-
- c := func(ctx context.Context, done func()) {
- defer done()
- ctx, cancel := stopCh.CtxCancel(context.WithDeadline(ctx, time.Now().Add(5*time.Second)))
- defer cancel()
- work(ctx)
- }
-
- ctx, cancel := stopCh.NewCtx()
- defer cancel()
-
- var wg sync.WaitGroup
- wg.Add(3)
- go a(ctx, wg.Done)
- go b(ctx, wg.Done)
- go c(ctx, wg.Done)
-
- time.AfterFunc(time.Second, func() { close(stopCh) })
-
- wg.Wait()
- // Output:
-}
diff --git a/core/utils/utils_test.go b/core/utils/utils_test.go
index 04802feb3a..e11c01a8e4 100644
--- a/core/utils/utils_test.go
+++ b/core/utils/utils_test.go
@@ -374,79 +374,6 @@ func Test_WithJitter(t *testing.T) {
}
}
-func Test_StartStopOnce_StopWaitsForStartToFinish(t *testing.T) {
- t.Parallel()
-
- once := utils.StartStopOnce{}
-
- ch := make(chan int, 3)
-
- ready := make(chan bool)
-
- go func() {
- assert.NoError(t, once.StartOnce("slow service", func() (err error) {
- ch <- 1
- ready <- true
- <-time.After(time.Millisecond * 500) // wait for StopOnce to happen
- ch <- 2
-
- return nil
- }))
- }()
-
- go func() {
- <-ready // try stopping halfway through startup
- assert.NoError(t, once.StopOnce("slow service", func() (err error) {
- ch <- 3
-
- return nil
- }))
- }()
-
- require.Equal(t, 1, <-ch)
- require.Equal(t, 2, <-ch)
- require.Equal(t, 3, <-ch)
-}
-
-func Test_StartStopOnce_MultipleStartNoBlock(t *testing.T) {
- t.Parallel()
-
- once := utils.StartStopOnce{}
-
- ch := make(chan int, 3)
-
- ready := make(chan bool)
- next := make(chan bool)
-
- go func() {
- ch <- 1
- assert.NoError(t, once.StartOnce("slow service", func() (err error) {
- ready <- true
- <-next // continue after the other StartOnce call fails
-
- return nil
- }))
- <-next
- ch <- 2
-
- }()
-
- go func() {
- <-ready // try starting halfway through startup
- assert.Error(t, once.StartOnce("slow service", func() (err error) {
- return nil
- }))
- next <- true
- ch <- 3
- next <- true
-
- }()
-
- require.Equal(t, 1, <-ch)
- require.Equal(t, 3, <-ch) // 3 arrives before 2 because it returns immediately
- require.Equal(t, 2, <-ch)
-}
-
func TestAllEqual(t *testing.T) {
t.Parallel()
diff --git a/plugins/medianpoc/plugin.go b/plugins/medianpoc/plugin.go
index 62b6acc043..af4ec41ab8 100644
--- a/plugins/medianpoc/plugin.go
+++ b/plugins/medianpoc/plugin.go
@@ -14,20 +14,19 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink-common/pkg/types"
- "github.com/smartcontractkit/chainlink/v2/core/utils"
)
func NewPlugin(lggr logger.Logger) *Plugin {
return &Plugin{
Plugin: loop.Plugin{Logger: lggr},
MedianProviderServer: reportingplugins.MedianProviderServer{},
- stop: make(utils.StopChan),
+ stop: make(services.StopChan),
}
}
type Plugin struct {
loop.Plugin
- stop utils.StopChan
+ stop services.StopChan
reportingplugins.MedianProviderServer
}
From f7949c5994b8c653072ea49747cce84dfe886df4 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Mon, 20 Nov 2023 18:13:50 -0600
Subject: [PATCH 180/327] replace context.Background() (#11334)
---
.../dashboard/cmd/dashboard_deploy.go | 4 +-
.../chainlink-cluster/dashboard/dashboard.go | 3 +-
common/client/send_only_node_lifecycle.go | 7 +-
.../evm/client/send_only_node_lifecycle.go | 7 +-
core/chains/evm/gas/models_test.go | 4 +-
core/chains/evm/logpoller/log_poller.go | 11 +-
.../evm/logpoller/log_poller_internal_test.go | 147 ++++++++----------
core/chains/evm/logpoller/log_poller_test.go | 10 +-
core/chains/evm/txmgr/evm_tx_store.go | 18 ++-
core/cmd/ocr2vrf_configure_commands.go | 30 ++--
core/internal/cltest/cltest.go | 2 +-
core/internal/testutils/pgtest/txdb_test.go | 4 +-
core/services/blockhashstore/bhs_test.go | 8 +-
core/services/feeds/service.go | 2 +-
.../gateway/handlers/handler.dummy_test.go | 9 +-
core/services/job/job_orm_test.go | 2 +-
core/services/job/mocks/orm.go | 18 +--
core/services/job/orm.go | 6 +-
core/services/keystore/starknet_test.go | 8 +-
.../generic/pipeline_runner_adapter_test.go | 9 +-
.../plugins/generic/telemetry_adapter_test.go | 7 +-
.../ocr2/plugins/mercury/helpers_test.go | 4 +-
.../plugins/ocr2keeper/evm20/registry_test.go | 7 +-
.../ocr2keeper/evm21/block_subscriber_test.go | 6 +-
.../evm21/logprovider/block_time_test.go | 5 +-
.../evm21/logprovider/integration_test.go | 13 +-
.../logprovider/provider_life_cycle_test.go | 11 +-
.../evm21/logprovider/provider_test.go | 7 +-
.../evm21/logprovider/recoverer_test.go | 11 +-
.../evm21/mercury/streams/streams_test.go | 9 +-
.../evm21/mercury/v02/v02_request_test.go | 6 +-
.../evm21/mercury/v03/v03_request_test.go | 6 +-
.../ocr2keeper/evm21/payload_builder_test.go | 6 +-
.../evm21/registry_check_pipeline_test.go | 12 +-
.../evm21/transmit/event_provider_test.go | 8 +-
.../evm21/upkeepstate/store_test.go | 13 +-
.../plugins/ocr2keeper/integration_21_test.go | 5 +-
.../plugins/ocr2keeper/integration_test.go | 5 +-
.../internal/ocr2vrf_integration_test.go | 8 +-
.../ocr2/plugins/promwrapper/plugin_test.go | 16 +-
.../evm/mercury/persistence_manager_test.go | 10 +-
.../relay/evm/mercury/v1/data_source_test.go | 4 +-
.../relay/grpc_provider_server_test.go | 4 +-
core/services/relay/relay_test.go | 5 +-
core/services/telemetry/manager_test.go | 3 +-
.../services/transmission/integration_test.go | 3 +-
core/services/vrf/v2/integration_v2_test.go | 10 +-
core/web/jobs_controller.go | 2 +-
.../automationv2_1/automationv2_1_test.go | 12 +-
plugins/medianpoc/data_source_test.go | 7 +-
plugins/medianpoc/plugin_test.go | 4 +-
51 files changed, 269 insertions(+), 269 deletions(-)
diff --git a/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go b/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go
index c752794f53..170ffa0288 100644
--- a/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go
+++ b/charts/chainlink-cluster/dashboard/cmd/dashboard_deploy.go
@@ -1,12 +1,14 @@
package main
import (
+ "context"
"os"
"github.com/smartcontractkit/chainlink/v2/dashboard/dashboard"
)
func main() {
+ ctx := context.Background()
name := os.Getenv("DASHBOARD_NAME")
if name == "" {
panic("DASHBOARD_NAME must be provided")
@@ -36,7 +38,7 @@ func main() {
if err != nil {
panic(err)
}
- if err := db.Deploy(); err != nil {
+ if err := db.Deploy(ctx); err != nil {
panic(err)
}
}
diff --git a/charts/chainlink-cluster/dashboard/dashboard.go b/charts/chainlink-cluster/dashboard/dashboard.go
index 7918b996dd..293cded2b0 100644
--- a/charts/chainlink-cluster/dashboard/dashboard.go
+++ b/charts/chainlink-cluster/dashboard/dashboard.go
@@ -378,8 +378,7 @@ func (m *CLClusterDashboard) generate() error {
}
// Deploy deploys the dashboard to Grafana
-func (m *CLClusterDashboard) Deploy() error {
- ctx := context.Background()
+func (m *CLClusterDashboard) Deploy(ctx context.Context) error {
client := grabana.NewClient(&http.Client{}, m.GrafanaURL, grabana.WithAPIToken(m.GrafanaToken))
folder, err := client.FindOrCreateFolder(ctx, m.Folder)
if err != nil {
diff --git a/common/client/send_only_node_lifecycle.go b/common/client/send_only_node_lifecycle.go
index 0f663eab30..4d5b102b5b 100644
--- a/common/client/send_only_node_lifecycle.go
+++ b/common/client/send_only_node_lifecycle.go
@@ -1,7 +1,6 @@
package client
import (
- "context"
"fmt"
"time"
@@ -14,15 +13,17 @@ import (
// It will continue checking until success and then exit permanently.
func (s *sendOnlyNode[CHAIN_ID, RPC]) verifyLoop() {
defer s.wg.Done()
+ ctx, cancel := s.chStop.NewCtx()
+ defer cancel()
backoff := utils.NewRedialBackoff()
for {
select {
- case <-s.chStop:
+ case <-ctx.Done():
return
case <-time.After(backoff.Duration()):
}
- chainID, err := s.rpc.ChainID(context.Background())
+ chainID, err := s.rpc.ChainID(ctx)
if err != nil {
ok := s.IfStarted(func() {
if changed := s.setState(nodeStateUnreachable); changed {
diff --git a/core/chains/evm/client/send_only_node_lifecycle.go b/core/chains/evm/client/send_only_node_lifecycle.go
index 509be53c8a..9d704e4938 100644
--- a/core/chains/evm/client/send_only_node_lifecycle.go
+++ b/core/chains/evm/client/send_only_node_lifecycle.go
@@ -1,7 +1,6 @@
package client
import (
- "context"
"fmt"
"time"
@@ -14,12 +13,14 @@ import (
// It will continue checking until success and then exit permanently.
func (s *sendOnlyNode) verifyLoop() {
defer s.wg.Done()
+ ctx, cancel := s.chStop.NewCtx()
+ defer cancel()
backoff := utils.NewRedialBackoff()
for {
select {
case <-time.After(backoff.Duration()):
- chainID, err := s.sender.ChainID(context.Background())
+ chainID, err := s.sender.ChainID(ctx)
if err != nil {
ok := s.IfStarted(func() {
if changed := s.setState(NodeStateUnreachable); changed {
@@ -60,7 +61,7 @@ func (s *sendOnlyNode) verifyLoop() {
s.log.Infow("Sendonly RPC Node is online", "nodeState", s.state)
return
}
- case <-s.chStop:
+ case <-ctx.Done():
return
}
}
diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go
index 8ac94a2269..a2dce58ee3 100644
--- a/core/chains/evm/gas/models_test.go
+++ b/core/chains/evm/gas/models_test.go
@@ -1,7 +1,6 @@
package gas_test
import (
- "context"
"math/big"
"testing"
@@ -14,11 +13,12 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
)
func TestWrappedEvmEstimator(t *testing.T) {
t.Parallel()
- ctx := context.Background()
+ ctx := testutils.Context(t)
// fee values
gasLimit := uint32(10)
diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go
index 6676b694b0..bb93db4037 100644
--- a/core/chains/evm/logpoller/log_poller.go
+++ b/core/chains/evm/logpoller/log_poller.go
@@ -130,8 +130,10 @@ type logPoller struct {
// support chain, polygon, which has 2s block times, we need RPCs roughly with <= 500ms latency
func NewLogPoller(orm ORM, ec Client, lggr logger.Logger, pollPeriod time.Duration,
useFinalityTag bool, finalityDepth int64, backfillBatchSize int64, rpcBatchSize int64, keepFinalizedBlocksDepth int64) *logPoller {
-
+ ctx, cancel := context.WithCancel(context.Background())
return &logPoller{
+ ctx: ctx,
+ cancel: cancel,
ec: ec,
orm: orm,
lggr: lggr.Named("LogPoller"),
@@ -371,18 +373,15 @@ func (lp *logPoller) recvReplayComplete() {
func (lp *logPoller) ReplayAsync(fromBlock int64) {
lp.wg.Add(1)
go func() {
- if err := lp.Replay(context.Background(), fromBlock); err != nil {
+ if err := lp.Replay(lp.ctx, fromBlock); err != nil {
lp.lggr.Error(err)
}
lp.wg.Done()
}()
}
-func (lp *logPoller) Start(parentCtx context.Context) error {
+func (lp *logPoller) Start(context.Context) error {
return lp.StartOnce("LogPoller", func() error {
- ctx, cancel := context.WithCancel(parentCtx)
- lp.ctx = ctx
- lp.cancel = cancel
lp.wg.Add(1)
go lp.run()
return nil
diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go
index c0d081582f..2ef276802b 100644
--- a/core/chains/evm/logpoller/log_poller_internal_test.go
+++ b/core/chains/evm/logpoller/log_poller_internal_test.go
@@ -20,6 +20,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
@@ -233,7 +234,6 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) {
func TestLogPoller_Replay(t *testing.T) {
t.Parallel()
addr := common.HexToAddress("0x2ab9a2dc53736b361b72d900cdf9f78f9406fbbc")
- tctx := testutils.Context(t)
lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.ErrorLevel)
chainID := testutils.FixtureChainID
@@ -259,48 +259,39 @@ func TestLogPoller_Replay(t *testing.T) {
lp := NewLogPoller(orm, ec, lggr, time.Hour, false, 3, 3, 3, 20)
// process 1 log in block 3
- lp.PollAndSaveLogs(tctx, 4)
+ lp.PollAndSaveLogs(testutils.Context(t), 4)
latest, err := lp.LatestBlock()
require.NoError(t, err)
require.Equal(t, int64(4), latest.BlockNumber)
t.Run("abort before replayStart received", func(t *testing.T) {
// Replay() should abort immediately if caller's context is cancelled before request signal is read
- ctx, cancel := context.WithCancel(tctx)
+ ctx, cancel := context.WithCancel(testutils.Context(t))
cancel()
err = lp.Replay(ctx, 3)
assert.ErrorIs(t, err, ErrReplayRequestAborted)
})
- recvStartReplay := func(parentCtx context.Context, block int64, withTimeout bool) {
- var err error
- var ctx context.Context
- var cancel context.CancelFunc
- if withTimeout {
- ctx, cancel = context.WithTimeout(parentCtx, testutils.WaitTimeout(t))
- } else {
- ctx, cancel = context.WithCancel(parentCtx)
- }
- defer cancel()
+ recvStartReplay := func(ctx context.Context, block int64) {
select {
case fromBlock := <-lp.replayStart:
assert.Equal(t, block, fromBlock)
case <-ctx.Done():
- err = ctx.Err()
+ assert.NoError(t, ctx.Err(), "Timed out waiting to receive replay request from lp.replayStart")
}
- assert.NoError(t, err, "Timed out waiting to receive replay request from lp.replayStart")
}
// Replay() should return error code received from replayComplete
t.Run("returns error code on replay complete", func(t *testing.T) {
+ ctx := testutils.Context(t)
anyErr := errors.New("any error")
done := make(chan struct{})
go func() {
defer close(done)
- recvStartReplay(tctx, 1, true)
+ recvStartReplay(ctx, 1)
lp.replayComplete <- anyErr
}()
- assert.ErrorIs(t, lp.Replay(tctx, 1), anyErr)
+ assert.ErrorIs(t, lp.Replay(ctx, 1), anyErr)
<-done
})
@@ -310,7 +301,7 @@ func TestLogPoller_Replay(t *testing.T) {
done := make(chan struct{})
go func() {
defer close(done)
- recvStartReplay(ctx, 4, false)
+ recvStartReplay(ctx, 4)
cancel()
}()
assert.ErrorIs(t, lp.Replay(ctx, 4), ErrReplayInProgress)
@@ -323,29 +314,33 @@ func TestLogPoller_Replay(t *testing.T) {
t.Run("client abort doesnt hang run loop", func(t *testing.T) {
lp.backupPollerNextBlock = 0
- timeLeft := testutils.WaitTimeout(t)
- timeout := time.After(timeLeft)
- ctx, cancel := context.WithCancel(tctx)
+ ctx := testutils.Context(t)
- var wg sync.WaitGroup
pass := make(chan struct{})
cancelled := make(chan struct{})
+ rctx, rcancel := context.WithCancel(testutils.Context(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) {
wg.Add(1)
go func() {
defer wg.Done()
- assert.ErrorIs(t, lp.Replay(ctx, 4), ErrReplayInProgress)
+ assert.ErrorIs(t, lp.Replay(rctx, 4), ErrReplayInProgress)
close(cancelled)
}()
})
ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) {
- cancel()
+ rcancel()
wg.Add(1)
go func() {
defer wg.Done()
- lp.replayStart <- 4
- close(pass)
+ select {
+ case lp.replayStart <- 4:
+ close(pass)
+ case <-ctx.Done():
+ return
+ }
}()
// We cannot return until we're sure that Replay() received the cancellation signal,
// otherwise replayComplete<- might be sent first
@@ -354,24 +349,13 @@ 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
- lp.ctx, lp.cancel = context.WithCancel(tctx)
- lp.wg.Add(1)
- defer func() {
- select {
- case <-lp.replayStart:
- default:
- }
- wg.Wait()
- lp.cancel()
- lp.wg.Wait()
- }()
+ t.Cleanup(lp.reset)
+ require.NoError(t, lp.Start(ctx))
+ t.Cleanup(func() { assert.NoError(t, lp.Close()) })
- go func() {
- lp.run()
- }()
select {
- case <-timeout:
- assert.Failf(t, "lp.run() got stuck--failed to respond to second replay event within %s", timeLeft.String())
+ case <-ctx.Done():
+ t.Errorf("timed out waiting for lp.run() to respond to second replay event")
case <-pass:
}
})
@@ -383,13 +367,18 @@ func TestLogPoller_Replay(t *testing.T) {
t.Run("shutdown during replay", func(t *testing.T) {
lp.backupPollerNextBlock = 0
- safeToExit := make(chan struct{})
pass := make(chan struct{})
+ done := make(chan struct{})
+ defer func() { <-done }()
+ ctx := testutils.Context(t)
ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) {
go func() {
- lp.replayStart <- 4
- close(safeToExit)
+ defer close(done)
+ select {
+ case lp.replayStart <- 4:
+ case <-ctx.Done():
+ }
}()
})
ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) {
@@ -398,71 +387,57 @@ 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
- timeLeft := testutils.WaitTimeout(t)
- timeout := time.After(timeLeft)
- require.NoError(t, lp.Start(tctx))
-
- defer func() {
- select {
- case <-lp.replayStart: // unblock replayStart<- goroutine if it's stuck
- default:
- }
- <-safeToExit
- lp.Close()
- }()
+ t.Cleanup(lp.reset)
+ require.NoError(t, lp.Start(ctx))
+ t.Cleanup(func() { assert.NoError(t, lp.Close()) })
select {
- case <-timeout:
- assert.Failf(t, "lp.run() failed to respond to shutdown event during replay within %s", timeLeft.String())
+ case <-ctx.Done():
+ t.Error("timed out waiting for lp.run() to respond to shutdown event during replay")
case <-pass:
}
})
// ReplayAsync should return as soon as replayStart is received
t.Run("ReplayAsync success", func(t *testing.T) {
- lp.ctx, lp.cancel = context.WithTimeout(tctx, testutils.WaitTimeout(t))
- defer func() {
- lp.replayComplete <- nil
- lp.cancel()
- lp.wg.Wait()
- }()
+ t.Cleanup(lp.reset)
+ require.NoError(t, lp.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, lp.Close()) })
- done := make(chan struct{})
- go func() {
- lp.ReplayAsync(1)
- close(done)
- }()
- recvStartReplay(tctx, 1, true)
- <-done
+ lp.ReplayAsync(1)
+
+ recvStartReplay(testutils.Context(t), 1)
})
t.Run("ReplayAsync error", func(t *testing.T) {
- timeLeft := testutils.WaitTimeout(t)
- lp.ctx, lp.cancel = context.WithTimeout(tctx, timeLeft)
- defer func() {
- lp.cancel()
- lp.wg.Wait()
- }()
+ t.Cleanup(lp.reset)
+ require.NoError(t, lp.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, lp.Close()) })
+
anyErr := errors.New("async error")
observedLogs.TakeAll()
lp.ReplayAsync(4)
- recvStartReplay(tctx, 4, true)
+ recvStartReplay(testutils.Context(t), 4)
select {
case lp.replayComplete <- anyErr:
time.Sleep(2 * time.Second)
case <-lp.ctx.Done():
- assert.Failf(t, "failed to receive replayComplete signal within %s", timeLeft.String())
+ t.Error("timed out waiting to send replaceComplete")
}
require.Equal(t, 1, observedLogs.Len())
assert.Equal(t, observedLogs.All()[0].Message, anyErr.Error())
})
}
+func (lp *logPoller) reset() {
+ lp.StateMachine = services.StateMachine{}
+ lp.ctx, lp.cancel = context.WithCancel(context.Background())
+}
+
func Test_latestBlockAndFinalityDepth(t *testing.T) {
- tctx := testutils.Context(t)
- lggr, _ := logger.TestLoggerObserved(t, zapcore.ErrorLevel)
+ lggr := logger.TestLogger(t)
chainID := testutils.FixtureChainID
db := pgtest.NewSqlxDB(t)
orm := NewORM(chainID, db, lggr, pgtest.NewQConfig(true))
@@ -474,7 +449,7 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) {
ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(&head, nil)
lp := NewLogPoller(orm, ec, lggr, time.Hour, false, finalityDepth, 3, 3, 20)
- latestBlock, lastFinalizedBlockNumber, err := lp.latestBlocks(tctx)
+ latestBlock, lastFinalizedBlockNumber, err := lp.latestBlocks(testutils.Context(t))
require.NoError(t, err)
require.Equal(t, latestBlock.Number, head.Number)
require.Equal(t, finalityDepth, latestBlock.Number-lastFinalizedBlockNumber)
@@ -499,7 +474,7 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) {
lp := NewLogPoller(orm, ec, lggr, time.Hour, true, 3, 3, 3, 20)
- latestBlock, lastFinalizedBlockNumber, err := lp.latestBlocks(tctx)
+ latestBlock, lastFinalizedBlockNumber, err := lp.latestBlocks(testutils.Context(t))
require.NoError(t, err)
require.Equal(t, expectedLatestBlockNumber, latestBlock.Number)
require.Equal(t, expectedLastFinalizedBlockNumber, lastFinalizedBlockNumber)
@@ -516,7 +491,7 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) {
})
lp := NewLogPoller(orm, ec, lggr, time.Hour, true, 3, 3, 3, 20)
- _, _, err := lp.latestBlocks(tctx)
+ _, _, err := lp.latestBlocks(testutils.Context(t))
require.Error(t, err)
})
@@ -525,7 +500,7 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) {
ec.On("BatchCallContext", mock.Anything, mock.Anything).Return(fmt.Errorf("some error"))
lp := NewLogPoller(orm, ec, lggr, time.Hour, true, 3, 3, 3, 20)
- _, _, err := lp.latestBlocks(tctx)
+ _, _, err := lp.latestBlocks(testutils.Context(t))
require.Error(t, err)
})
})
diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go
index 5f013ca914..94589f505a 100644
--- a/core/chains/evm/logpoller/log_poller_test.go
+++ b/core/chains/evm/logpoller/log_poller_test.go
@@ -626,19 +626,19 @@ func TestLogPoller_BlockTimestamps(t *testing.T) {
require.Len(t, gethLogs, 2)
lb, _ := th.LogPoller.LatestBlock(pg.WithParentCtx(testutils.Context(t)))
- th.PollAndSaveLogs(context.Background(), lb.BlockNumber+1)
+ th.PollAndSaveLogs(ctx, lb.BlockNumber+1)
lg1, err := th.LogPoller.Logs(0, 20, EmitterABI.Events["Log1"].ID, th.EmitterAddress1,
- pg.WithParentCtx(testutils.Context(t)))
+ pg.WithParentCtx(ctx))
require.NoError(t, err)
lg2, err := th.LogPoller.Logs(0, 20, EmitterABI.Events["Log2"].ID, th.EmitterAddress2,
- pg.WithParentCtx(testutils.Context(t)))
+ pg.WithParentCtx(ctx))
require.NoError(t, err)
// Logs should have correct timestamps
- b, _ := th.Client.BlockByHash(context.Background(), lg1[0].BlockHash)
+ 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)
- b2, _ := th.Client.BlockByHash(context.Background(), lg2[0].BlockHash)
+ b2, _ := th.Client.BlockByHash(ctx, lg2[0].BlockHash)
assert.Equal(t, int64(b2.Time()), lg2[0].BlockTimestamp.UTC().Unix(), time2)
}
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 9262c85a83..0e08d32b77 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -1107,11 +1107,9 @@ ORDER BY nonce ASC
return etxs, pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed")
}
-func saveAttemptWithNewState(q pg.Queryer, timeout time.Duration, logger logger.Logger, attempt TxAttempt, broadcastAt time.Time) error {
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
+func saveAttemptWithNewState(ctx context.Context, q pg.Queryer, logger logger.Logger, attempt TxAttempt, broadcastAt time.Time) error {
var dbAttempt DbEthTxAttempt
dbAttempt.FromTxAttempt(&attempt)
- defer cancel()
return pg.SqlxTransaction(ctx, q, logger, func(tx pg.Queryer) 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
@@ -1133,15 +1131,19 @@ func (o *evmTxStore) SaveInsufficientFundsAttempt(ctx context.Context, timeout t
return errors.New("expected state to be either in_progress or insufficient_eth")
}
attempt.State = txmgrtypes.TxAttemptInsufficientFunds
- return pkgerrors.Wrap(saveAttemptWithNewState(qq, timeout, o.logger, *attempt, broadcastAt), "saveInsufficientEthAttempt failed")
+ ctx, cancel = context.WithTimeout(ctx, timeout)
+ defer cancel()
+ return pkgerrors.Wrap(saveAttemptWithNewState(ctx, qq, o.logger, *attempt, broadcastAt), "saveInsufficientEthAttempt failed")
}
-func saveSentAttempt(q pg.Queryer, timeout time.Duration, logger logger.Logger, attempt *TxAttempt, broadcastAt time.Time) error {
+func saveSentAttempt(ctx context.Context, q pg.Queryer, timeout time.Duration, logger logger.Logger, attempt *TxAttempt, broadcastAt time.Time) error {
if attempt.State != txmgrtypes.TxAttemptInProgress {
return errors.New("expected state to be in_progress")
}
attempt.State = txmgrtypes.TxAttemptBroadcast
- return pkgerrors.Wrap(saveAttemptWithNewState(q, timeout, logger, *attempt, broadcastAt), "saveSentAttempt failed")
+ ctx, cancel := context.WithTimeout(ctx, timeout)
+ defer cancel()
+ return pkgerrors.Wrap(saveAttemptWithNewState(ctx, q, logger, *attempt, broadcastAt), "saveSentAttempt failed")
}
func (o *evmTxStore) SaveSentAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt, broadcastAt time.Time) error {
@@ -1149,7 +1151,7 @@ func (o *evmTxStore) SaveSentAttempt(ctx context.Context, timeout time.Duration,
ctx, cancel = o.mergeContexts(ctx)
defer cancel()
qq := o.q.WithOpts(pg.WithParentCtx(ctx))
- return saveSentAttempt(qq, timeout, o.logger, attempt, broadcastAt)
+ return saveSentAttempt(ctx, qq, timeout, o.logger, attempt, broadcastAt)
}
func (o *evmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt, broadcastAt time.Time) error {
@@ -1158,7 +1160,7 @@ func (o *evmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, tim
defer cancel()
qq := o.q.WithOpts(pg.WithParentCtx(ctx))
err := qq.Transaction(func(tx pg.Queryer) error {
- if err := saveSentAttempt(tx, timeout, o.logger, attempt, broadcastAt); err != nil {
+ if err := saveSentAttempt(ctx, tx, timeout, o.logger, attempt, broadcastAt); err != nil {
return err
}
if _, err := tx.Exec(`UPDATE evm.txes SET state = 'confirmed_missing_receipt' WHERE id = $1`, attempt.TxID); err != nil {
diff --git a/core/cmd/ocr2vrf_configure_commands.go b/core/cmd/ocr2vrf_configure_commands.go
index bb4cef4708..cf014d5e5d 100644
--- a/core/cmd/ocr2vrf_configure_commands.go
+++ b/core/cmd/ocr2vrf_configure_commands.go
@@ -126,6 +126,7 @@ chainID = %d
const forwarderAdditionalEOACount = 4
func (s *Shell) ConfigureOCR2VRFNode(c *cli.Context, owner *bind.TransactOpts, ec *ethclient.Client) (*SetupOCR2VRFNodePayload, error) {
+ ctx := s.ctx()
lggr := logger.Sugared(s.Logger.Named("ConfigureOCR2VRFNode"))
lggr.Infow(
fmt.Sprintf("Configuring Chainlink Node for job type %s %s at commit %s", c.String("job-type"), static.Version, static.Sha),
@@ -156,15 +157,13 @@ func (s *Shell) ConfigureOCR2VRFNode(c *cli.Context, owner *bind.TransactOpts, e
cfg := s.Config
ldb := pg.NewLockedDB(cfg.AppID(), cfg.Database(), cfg.Database().Lock(), lggr)
- rootCtx, cancel := context.WithCancel(context.Background())
- defer cancel()
- if err = ldb.Open(rootCtx); err != nil {
+ if err = ldb.Open(ctx); err != nil {
return nil, s.errorOut(errors.Wrap(err, "opening db"))
}
defer lggr.ErrorIfFn(ldb.Close, "Error closing db")
- app, err := s.AppFactory.NewApplication(rootCtx, s.Config, lggr, ldb.DB())
+ app, err := s.AppFactory.NewApplication(ctx, s.Config, lggr, ldb.DB())
if err != nil {
return nil, s.errorOut(errors.Wrap(err, "fatal error instantiating application"))
}
@@ -179,7 +178,7 @@ func (s *Shell) ConfigureOCR2VRFNode(c *cli.Context, owner *bind.TransactOpts, e
}
// Start application.
- err = app.Start(rootCtx)
+ err = app.Start(ctx)
if err != nil {
return nil, s.errorOut(err)
}
@@ -243,10 +242,10 @@ func (s *Shell) ConfigureOCR2VRFNode(c *cli.Context, owner *bind.TransactOpts, e
if c.Bool("isBootstrapper") {
// Set up bootstrapper job if bootstrapper.
- err = createBootstrapperJob(lggr, c, app)
+ err = createBootstrapperJob(ctx, lggr, c, app)
} else if c.String("job-type") == "DKG" {
// Set up DKG job.
- err = createDKGJob(lggr, app, dkgTemplateArgs{
+ err = createDKGJob(ctx, lggr, app, dkgTemplateArgs{
contractID: c.String("contractID"),
ocrKeyBundleID: ocr2.ID(),
p2pv2BootstrapperPeerID: peerID,
@@ -260,7 +259,7 @@ func (s *Shell) ConfigureOCR2VRFNode(c *cli.Context, owner *bind.TransactOpts, e
})
} else if c.String("job-type") == "OCR2VRF" {
// Set up OCR2VRF job.
- err = createOCR2VRFJob(lggr, app, ocr2vrfTemplateArgs{
+ err = createOCR2VRFJob(ctx, lggr, app, ocr2vrfTemplateArgs{
dkgTemplateArgs: dkgTemplateArgs{
contractID: c.String("dkg-address"),
ocrKeyBundleID: ocr2.ID(),
@@ -320,12 +319,13 @@ func (s *Shell) appendForwarders(chainID int64, ks keystore.Eth, sendingKeys []s
}
func (s *Shell) authorizeForwarder(c *cli.Context, db *sqlx.DB, lggr logger.Logger, chainID int64, ec *ethclient.Client, owner *bind.TransactOpts, sendingKeysAddresses []common.Address) error {
+ ctx := s.ctx()
// Replace the transmitter ID with the forwarder address.
forwarderAddress := c.String("forwarder-address")
// We have to set the authorized senders on-chain here, otherwise the job spawner will fail as the
// forwarder will not be recognized.
- ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second)
+ ctx, cancel := context.WithTimeout(ctx, 300*time.Second)
defer cancel()
f, err := authorized_forwarder.NewAuthorizedForwarder(common.HexToAddress(forwarderAddress), ec)
if err != nil {
@@ -400,7 +400,7 @@ func setupKeystore(cli *Shell, app chainlink.Application, keyStore keystore.Mast
return nil
}
-func createBootstrapperJob(lggr logger.Logger, c *cli.Context, app chainlink.Application) error {
+func createBootstrapperJob(ctx context.Context, lggr logger.Logger, c *cli.Context, app chainlink.Application) error {
sp := fmt.Sprintf(BootstrapTemplate,
c.Int64("chainID"),
c.String("contractID"),
@@ -418,7 +418,7 @@ func createBootstrapperJob(lggr logger.Logger, c *cli.Context, app chainlink.App
}
jb.BootstrapSpec = &os
- err = app.AddJobV2(context.Background(), &jb)
+ err = app.AddJobV2(ctx, &jb)
if err != nil {
return errors.Wrap(err, "failed to add job")
}
@@ -430,7 +430,7 @@ func createBootstrapperJob(lggr logger.Logger, c *cli.Context, app chainlink.App
return nil
}
-func createDKGJob(lggr logger.Logger, app chainlink.Application, args dkgTemplateArgs) error {
+func createDKGJob(ctx context.Context, lggr logger.Logger, app chainlink.Application, args dkgTemplateArgs) error {
sp := fmt.Sprintf(DKGTemplate,
args.contractID,
args.ocrKeyBundleID,
@@ -455,7 +455,7 @@ func createDKGJob(lggr logger.Logger, app chainlink.Application, args dkgTemplat
}
jb.OCR2OracleSpec = &os
- err = app.AddJobV2(context.Background(), &jb)
+ err = app.AddJobV2(ctx, &jb)
if err != nil {
return errors.Wrap(err, "failed to add job")
}
@@ -464,7 +464,7 @@ func createDKGJob(lggr logger.Logger, app chainlink.Application, args dkgTemplat
return nil
}
-func createOCR2VRFJob(lggr logger.Logger, app chainlink.Application, args ocr2vrfTemplateArgs) error {
+func createOCR2VRFJob(ctx context.Context, lggr logger.Logger, app chainlink.Application, args ocr2vrfTemplateArgs) error {
var sendingKeysString = fmt.Sprintf(`"%s"`, args.sendingKeys[0])
for x := 1; x < len(args.sendingKeys); x++ {
sendingKeysString = fmt.Sprintf(`%s,"%s"`, sendingKeysString, args.sendingKeys[x])
@@ -498,7 +498,7 @@ func createOCR2VRFJob(lggr logger.Logger, app chainlink.Application, args ocr2vr
}
jb.OCR2OracleSpec = &os
- err = app.AddJobV2(context.Background(), &jb)
+ err = app.AddJobV2(ctx, &jb)
if err != nil {
return errors.Wrap(err, "failed to add job")
}
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index 02aa2de0cc..cf3f4f5c07 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -1076,7 +1076,7 @@ type TransactionReceipter interface {
func RequireTxSuccessful(t testing.TB, client TransactionReceipter, txHash common.Hash) *types.Receipt {
t.Helper()
- r, err := client.TransactionReceipt(context.Background(), txHash)
+ r, err := client.TransactionReceipt(testutils.Context(t), txHash)
require.NoError(t, err)
require.NotNil(t, r)
require.Equal(t, uint64(1), r.Status)
diff --git a/core/internal/testutils/pgtest/txdb_test.go b/core/internal/testutils/pgtest/txdb_test.go
index c1aeef4b8c..37339bf28b 100644
--- a/core/internal/testutils/pgtest/txdb_test.go
+++ b/core/internal/testutils/pgtest/txdb_test.go
@@ -8,6 +8,8 @@ import (
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
)
func TestTxDBDriver(t *testing.T) {
@@ -35,7 +37,7 @@ func TestTxDBDriver(t *testing.T) {
ensureValuesPresent(t, db)
t.Run("Cancel of tx's context does not trigger rollback of driver's tx", func(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := context.WithCancel(testutils.Context(t))
_, err := db.BeginTx(ctx, nil)
assert.NoError(t, err)
cancel()
diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go
index 5c501a62ac..44205ec7b8 100644
--- a/core/services/blockhashstore/bhs_test.go
+++ b/core/services/blockhashstore/bhs_test.go
@@ -1,7 +1,6 @@
package blockhashstore_test
import (
- "context"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -12,6 +11,7 @@ import (
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store"
"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/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
@@ -66,9 +66,11 @@ func TestStoreRotatesFromAddresses(t *testing.T) {
return tx.FromAddress.String() == k2.Address.String()
})).Once().Return(txmgr.Tx{}, nil)
+ ctx := testutils.Context(t)
+
// store 2 blocks
- err = bhs.Store(context.Background(), 1)
+ err = bhs.Store(ctx, 1)
require.NoError(t, err)
- err = bhs.Store(context.Background(), 2)
+ err = bhs.Store(ctx, 2)
require.NoError(t, err)
}
diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go
index da19a33abc..32a8432f87 100644
--- a/core/services/feeds/service.go
+++ b/core/services/feeds/service.go
@@ -186,7 +186,7 @@ func (s *service) RegisterManager(ctx context.Context, params RegisterManagerPar
}
var id int64
- q := s.q.WithOpts(pg.WithParentCtx(context.Background()))
+ q := s.q.WithOpts(pg.WithParentCtx(ctx))
err = q.Transaction(func(tx pg.Queryer) error {
var txerr error
diff --git a/core/services/gateway/handlers/handler.dummy_test.go b/core/services/gateway/handlers/handler.dummy_test.go
index c2c7a7a12a..c3f23935e6 100644
--- a/core/services/gateway/handlers/handler.dummy_test.go
+++ b/core/services/gateway/handlers/handler.dummy_test.go
@@ -6,6 +6,7 @@ import (
"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/services/gateway/api"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/config"
@@ -41,15 +42,17 @@ func TestDummyHandler_BasicFlow(t *testing.T) {
require.NoError(t, err)
connMgr.SetHandler(handler)
+ ctx := testutils.Context(t)
+
// User request
msg := api.Message{Body: api.MessageBody{MessageId: "1234"}}
callbackCh := make(chan handlers.UserCallbackPayload, 1)
- require.NoError(t, handler.HandleUserMessage(context.Background(), &msg, callbackCh))
+ require.NoError(t, handler.HandleUserMessage(ctx, &msg, callbackCh))
require.Equal(t, 2, connMgr.sendCounter)
// Responses from both nodes
- require.NoError(t, handler.HandleNodeMessage(context.Background(), &msg, "addr_1"))
- require.NoError(t, handler.HandleNodeMessage(context.Background(), &msg, "addr_2"))
+ require.NoError(t, handler.HandleNodeMessage(ctx, &msg, "addr_1"))
+ require.NoError(t, handler.HandleNodeMessage(ctx, &msg, "addr_2"))
response := <-callbackCh
require.Equal(t, "1234", response.Msg.Body.MessageId)
}
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index 87ee15873d..21035140f5 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -1615,7 +1615,7 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) {
jb, err = orm.FindJobWithoutSpecErrors(jobSpec.ID)
require.NoError(t, err)
- jbWithErrors, err := orm.FindJobTx(jobSpec.ID)
+ jbWithErrors, err := orm.FindJobTx(testutils.Context(t), jobSpec.ID)
require.NoError(t, err)
assert.Equal(t, len(jb.JobSpecErrors), 0)
diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go
index 3d858f8132..9e18573f4e 100644
--- a/core/services/job/mocks/orm.go
+++ b/core/services/job/mocks/orm.go
@@ -247,23 +247,23 @@ func (_m *ORM) FindJobIDsWithBridge(name string) ([]int32, error) {
return r0, r1
}
-// FindJobTx provides a mock function with given fields: id
-func (_m *ORM) FindJobTx(id int32) (job.Job, error) {
- ret := _m.Called(id)
+// FindJobTx provides a mock function with given fields: ctx, id
+func (_m *ORM) FindJobTx(ctx context.Context, id int32) (job.Job, error) {
+ ret := _m.Called(ctx, id)
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)
}
diff --git a/core/services/job/orm.go b/core/services/job/orm.go
index ba102c6bb8..c5f533c3d2 100644
--- a/core/services/job/orm.go
+++ b/core/services/job/orm.go
@@ -49,7 +49,7 @@ type ORM interface {
InsertJob(job *Job, qopts ...pg.QOpt) error
CreateJob(jb *Job, qopts ...pg.QOpt) error
FindJobs(offset, limit int) ([]Job, int, error)
- FindJobTx(id int32) (Job, 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 ethkey.EIP55Address, evmChainID *utils.Big, qopts ...pg.QOpt) (int32, error)
@@ -782,8 +782,8 @@ func LoadConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracleSp
return LoadConfigVarsLocalOCR(evmOcrCfg, os, ocrCfg), nil
}
-func (o *orm) FindJobTx(id int32) (Job, error) {
- ctx, cancel := context.WithTimeout(context.Background(), o.cfg.DefaultQueryTimeout())
+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)
}
diff --git a/core/services/keystore/starknet_test.go b/core/services/keystore/starknet_test.go
index df9516f871..7fc5718bac 100644
--- a/core/services/keystore/starknet_test.go
+++ b/core/services/keystore/starknet_test.go
@@ -1,7 +1,6 @@
package keystore_test
import (
- "context"
"fmt"
"math/big"
"testing"
@@ -13,6 +12,7 @@ import (
"github.com/smartcontractkit/caigo"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
@@ -121,13 +121,13 @@ func TestStarknetSigner(t *testing.T) {
// on existing sender id
t.Run("key exists", func(t *testing.T) {
baseKs.On("Get", starknetSenderAddr).Return(starkKey, nil)
- signed, err := lk.Sign(context.Background(), starknetSenderAddr, nil)
+ signed, err := lk.Sign(testutils.Context(t), starknetSenderAddr, nil)
require.Nil(t, signed)
require.NoError(t, err)
})
t.Run("key doesn't exists", func(t *testing.T) {
baseKs.On("Get", mock.Anything).Return(starkkey.Key{}, fmt.Errorf("key doesn't exist"))
- signed, err := lk.Sign(context.Background(), "not an address", nil)
+ signed, err := lk.Sign(testutils.Context(t), "not an address", nil)
require.Nil(t, signed)
require.Error(t, err)
})
@@ -140,7 +140,7 @@ func TestStarknetSigner(t *testing.T) {
baseKs.On("Get", starknetSenderAddr).Return(starkKey, nil)
hash, err := caigo.Curve.PedersenHash([]*big.Int{big.NewInt(42)})
require.NoError(t, err)
- r, s, err := adapter.Sign(context.Background(), starknetSenderAddr, hash)
+ r, s, err := adapter.Sign(testutils.Context(t), starknetSenderAddr, hash)
require.NoError(t, err)
require.NotNil(t, r)
require.NotNil(t, s)
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 f70e0dd443..c2060a9290 100644
--- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go
@@ -14,6 +14,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/bridges"
+ "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"
@@ -53,7 +54,7 @@ func TestAdapter_Integration(t *testing.T) {
http.DefaultClient,
)
pra := generic.NewPipelineRunnerAdapter(logger, job.Job{}, pr)
- results, err := pra.ExecuteRun(context.Background(), spec, types.Vars{Vars: map[string]interface{}{"val": 1}}, types.Options{})
+ results, err := pra.ExecuteRun(testutils.Context(t), spec, types.Vars{Vars: map[string]interface{}{"val": 1}}, types.Options{})
require.NoError(t, err)
finalResult := results[0].Value.(decimal.Decimal)
@@ -85,7 +86,7 @@ func TestAdapter_AddsDefaultVars(t *testing.T) {
jobID, externalJobID, name := int32(100), uuid.New(), null.StringFrom("job-name")
pra := generic.NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name}, mpr)
- _, err := pra.ExecuteRun(context.Background(), spec, types.Vars{}, types.Options{})
+ _, err := pra.ExecuteRun(testutils.Context(t), spec, types.Vars{}, types.Options{})
require.NoError(t, err)
gotName, err := mpr.vars.Get("jb.name")
@@ -107,8 +108,8 @@ func TestPipelineRunnerAdapter_SetsVarsOnSpec(t *testing.T) {
jobID, externalJobID, name, jobType := int32(100), uuid.New(), null.StringFrom("job-name"), job.Type("generic")
pra := generic.NewPipelineRunnerAdapter(logger, job.Job{ID: jobID, ExternalJobID: externalJobID, Name: name, Type: jobType}, mpr)
- maxDuration := time.Duration(100 * time.Second)
- _, err := pra.ExecuteRun(context.Background(), spec, types.Vars{}, types.Options{MaxTaskDuration: maxDuration})
+ maxDuration := 100 * time.Second
+ _, err := pra.ExecuteRun(testutils.Context(t), spec, types.Vars{}, types.Options{MaxTaskDuration: maxDuration})
require.NoError(t, err)
assert.Equal(t, jobID, mpr.spec.JobID)
diff --git a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
index e137343f2b..24f422bf0c 100644
--- a/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
+++ b/core/services/ocr2/plugins/generic/telemetry_adapter_test.go
@@ -1,13 +1,14 @@
package generic_test
import (
- "context"
"testing"
- "github.com/smartcontractkit/libocr/commontypes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/libocr/commontypes"
+
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/generic"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization"
)
@@ -88,7 +89,7 @@ func TestTelemetryAdapter(t *testing.T) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- err := ta.Send(context.Background(), test.networkID, test.chainID, test.contractID, test.telemetryType, test.payload)
+ err := ta.Send(testutils.Context(t), test.networkID, test.chainID, test.contractID, test.telemetryType, test.payload)
if test.errorMsg != "" {
assert.ErrorContains(t, err, test.errorMsg)
} else {
diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go
index 588f772120..ed59213840 100644
--- a/core/services/ocr2/plugins/mercury/helpers_test.go
+++ b/core/services/ocr2/plugins/mercury/helpers_test.go
@@ -138,14 +138,14 @@ func (node *Node) AddJob(t *testing.T, spec string) {
c := node.App.GetConfig()
job, err := validate.ValidatedOracleSpecToml(c.OCR2(), c.Insecure(), spec)
require.NoError(t, err)
- err = node.App.AddJobV2(context.Background(), &job)
+ err = node.App.AddJobV2(testutils.Context(t), &job)
require.NoError(t, err)
}
func (node *Node) AddBootstrapJob(t *testing.T, spec string) {
job, err := ocrbootstrap.ValidatedBootstrapSpecToml(spec)
require.NoError(t, err)
- err = node.App.AddJobV2(context.Background(), &job)
+ err = node.App.AddJobV2(testutils.Context(t), &job)
require.NoError(t, err)
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
index 8662bfd047..340bd92357 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
@@ -1,21 +1,22 @@
package evm
import (
- "context"
"fmt"
"math/big"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -54,7 +55,7 @@ func TestGetActiveUpkeepKeys(t *testing.T) {
active: actives,
}
- keys, err := rg.GetActiveUpkeepIDs(context.Background())
+ keys, err := rg.GetActiveUpkeepIDs(testutils.Context(t))
if test.ExpectedErr != nil {
assert.ErrorIs(t, err, test.ExpectedErr)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
index 004b5fac6c..afb9d4a091 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
@@ -1,16 +1,16 @@
package evm
import (
- "context"
"fmt"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -304,7 +304,7 @@ func TestBlockSubscriber_Start(t *testing.T) {
bs := NewBlockSubscriber(hb, lp, finality, lggr)
bs.blockHistorySize = historySize
bs.blockSize = blockSize
- err := bs.Start(context.Background())
+ err := bs.Start(testutils.Context(t))
assert.Nil(t, err)
h97 := evmtypes.Head{
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go
index 7009cfaa9b..683ba37894 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time_test.go
@@ -1,7 +1,6 @@
package logprovider
import (
- "context"
"fmt"
"testing"
"time"
@@ -11,6 +10,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
)
func TestBlockTimeResolver_BlockTime(t *testing.T) {
@@ -63,8 +63,7 @@ func TestBlockTimeResolver_BlockTime(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
lp := new(lpmocks.LogPoller)
resolver := newBlockTimeResolver(lp)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index 0df774d5df..c7db01d878 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -614,10 +614,11 @@ func deployUpkeepCounter(
backend *backends.SimulatedBackend,
account *bind.TransactOpts,
logProvider logprovider.LogEventProvider,
-) ([]*big.Int, []common.Address, []*log_upkeep_counter_wrapper.LogUpkeepCounter) {
- var ids []*big.Int
- var contracts []*log_upkeep_counter_wrapper.LogUpkeepCounter
- var contractsAddrs []common.Address
+) (
+ ids []*big.Int,
+ contractsAddrs []common.Address,
+ contracts []*log_upkeep_counter_wrapper.LogUpkeepCounter,
+) {
for i := 0; i < n; i++ {
upkeepAddr, _, upkeepContract, err := log_upkeep_counter_wrapper.DeployLogUpkeepCounter(
account, backend,
@@ -633,7 +634,7 @@ func deployUpkeepCounter(
upkeepID := ocr2keepers.UpkeepIdentifier(append(common.LeftPadBytes([]byte{1}, 16), upkeepAddr[:16]...))
id := upkeepID.BigInt()
ids = append(ids, id)
- b, err := ethClient.BlockByHash(context.Background(), backend.Commit())
+ b, err := ethClient.BlockByHash(ctx, backend.Commit())
require.NoError(t, err)
bn := b.Number()
err = logProvider.RegisterFilter(ctx, logprovider.FilterOptions{
@@ -643,7 +644,7 @@ func deployUpkeepCounter(
})
require.NoError(t, err)
}
- return ids, contractsAddrs, contracts
+ return
}
func newPlainLogTriggerConfig(upkeepAddr common.Address) logprovider.LogTriggerConfig {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
index 03395cb5b5..b28b45fcb4 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
@@ -1,19 +1,20 @@
package logprovider
import (
- "context"
"fmt"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
)
@@ -103,8 +104,7 @@ func TestLogEventProvider_LifeCycle(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
if tc.mockPoller {
lp := new(mocks.LogPoller)
@@ -144,8 +144,7 @@ func TestLogEventProvider_LifeCycle(t *testing.T) {
}
func TestEventLogProvider_RefreshActiveUpkeeps(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
mp := new(mocks.LogPoller)
mp.On("RegisterFilter", mock.Anything).Return(nil)
mp.On("UnregisterFilter", mock.Anything).Return(nil)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
index a8e33ba23b..c6ebb1c51a 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
@@ -16,6 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"golang.org/x/time/rate"
@@ -174,8 +175,7 @@ func TestLogEventProvider_ScheduleReadJobs(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
readInterval := 10 * time.Millisecond
opts := NewOptions(200)
@@ -239,8 +239,7 @@ func TestLogEventProvider_ScheduleReadJobs(t *testing.T) {
}
func TestLogEventProvider_ReadLogs(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
mp := new(mocks.LogPoller)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
index c882a22bc1..77b0eec545 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
@@ -11,11 +11,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
@@ -29,8 +30,7 @@ import (
)
func TestLogRecoverer_GetRecoverables(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
lp := &lpmocks.LogPoller{}
lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: 100}, nil)
r := NewLogRecoverer(logger.TestLogger(t), lp, nil, nil, nil, nil, NewOptions(200))
@@ -213,8 +213,7 @@ func TestLogRecoverer_Clean(t *testing.T) {
}
func TestLogRecoverer_Recover(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
tests := []struct {
name string
@@ -1079,7 +1078,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
recoverer.states = tc.stateReader
}
- b, err := recoverer.GetProposalData(context.Background(), tc.proposal)
+ b, err := recoverer.GetProposalData(testutils.Context(t), tc.proposal)
if tc.expectErr {
assert.Error(t, err)
assert.Equal(t, tc.wantErr.Error(), err.Error())
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
index 194d74febb..0653796f41 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
@@ -2,7 +2,6 @@ package streams
import (
"bytes"
- "context"
"encoding/json"
"fmt"
"io"
@@ -20,11 +19,13 @@ import (
"github.com/stretchr/testify/assert"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/mock"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
v02 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02"
v03 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03"
@@ -257,7 +258,7 @@ func TestStreams_CheckCallback(t *testing.T) {
}).Once()
s.client = client
- state, retryable, _, err := s.checkCallback(context.Background(), tt.values, tt.lookup)
+ state, retryable, _, err := s.checkCallback(testutils.Context(t), tt.values, tt.lookup)
tt.wantErr(t, err, fmt.Sprintf("Error asserion failed: %v", tt.name))
assert.Equal(t, tt.state, state)
assert.Equal(t, tt.retryable, retryable)
@@ -719,7 +720,7 @@ func TestStreams_StreamsLookup(t *testing.T) {
}).Once()
}
- got := s.Lookup(context.Background(), tt.input)
+ got := s.Lookup(testutils.Context(t), tt.input)
assert.Equal(t, tt.expectedResults, got, tt.name)
})
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go
index 17ef8515fd..2aecc0df77 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02/v02_request_test.go
@@ -2,7 +2,6 @@ package v02
import (
"bytes"
- "context"
"encoding/json"
"errors"
"io"
@@ -16,6 +15,7 @@ import (
"github.com/patrickmn/go-cache"
"github.com/stretchr/testify/mock"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -258,7 +258,7 @@ func TestV02_SingleFeedRequest(t *testing.T) {
c.httpClient = hc
ch := make(chan mercury.MercuryData, 1)
- c.singleFeedRequest(context.Background(), ch, tt.index, tt.lookup)
+ c.singleFeedRequest(testutils.Context(t), ch, tt.index, tt.lookup)
m := <-ch
assert.Equal(t, tt.index, m.Index)
@@ -450,7 +450,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) {
}
c.httpClient = hc
- state, reason, values, retryable, retryInterval, reqErr := c.DoRequest(context.Background(), tt.lookup, tt.pluginRetryKey)
+ state, reason, values, retryable, retryInterval, reqErr := c.DoRequest(testutils.Context(t), tt.lookup, tt.pluginRetryKey)
assert.Equal(t, tt.expectedValues, values)
assert.Equal(t, tt.expectedRetryable, retryable)
if retryable {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go
index bef2cdac58..049448f8f7 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03/v03_request_test.go
@@ -2,7 +2,6 @@ package v03
import (
"bytes"
- "context"
"encoding/json"
"io"
"math/big"
@@ -14,6 +13,7 @@ import (
"github.com/patrickmn/go-cache"
"github.com/stretchr/testify/mock"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
@@ -162,7 +162,7 @@ func TestV03_DoMercuryRequestV03(t *testing.T) {
}
c.httpClient = hc
- state, reason, values, retryable, retryInterval, reqErr := c.DoRequest(context.Background(), tt.lookup, tt.pluginRetryKey)
+ state, reason, values, retryable, retryInterval, reqErr := c.DoRequest(testutils.Context(t), tt.lookup, tt.pluginRetryKey)
assert.Equal(t, tt.expectedValues, values)
assert.Equal(t, tt.expectedRetryable, retryable)
@@ -514,7 +514,7 @@ func TestV03_MultiFeedRequest(t *testing.T) {
c.httpClient = hc
ch := make(chan mercury.MercuryData, 1)
- c.multiFeedsRequest(context.Background(), ch, tt.lookup)
+ c.multiFeedsRequest(testutils.Context(t), ch, tt.lookup)
m := <-ch
assert.Equal(t, 0, m.Index)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go
index e75084ff96..e68e316ae3 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go
@@ -6,9 +6,11 @@ import (
"testing"
"github.com/pkg/errors"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
+ "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider"
@@ -191,7 +193,7 @@ func TestNewPayloadBuilder(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
lggr, _ := logger.NewLogger()
builder := NewPayloadBuilder(tc.activeList, tc.recoverer, lggr)
- payloads, err := builder.BuildPayloads(context.Background(), tc.proposals...)
+ payloads, err := builder.BuildPayloads(testutils.Context(t), tc.proposals...)
assert.NoError(t, err)
assert.Equal(t, tc.wantPayloads, payloads)
})
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
index 2e39892e47..d4e38637d8 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
@@ -18,13 +18,15 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
@@ -205,7 +207,7 @@ func TestRegistry_VerifyCheckBlock(t *testing.T) {
e.client = client
}
- state, retryable := e.verifyCheckBlock(context.Background(), tc.checkBlock, tc.upkeepId, tc.checkHash)
+ state, retryable := e.verifyCheckBlock(testutils.Context(t), tc.checkBlock, tc.upkeepId, tc.checkHash)
assert.Equal(t, tc.state, state)
assert.Equal(t, tc.retryable, retryable)
})
@@ -350,7 +352,7 @@ func TestRegistry_VerifyLogExists(t *testing.T) {
e := &EvmRegistry{
lggr: lggr,
bs: bs,
- ctx: context.Background(),
+ ctx: testutils.Context(t),
}
if tc.makeEthCall {
@@ -530,7 +532,7 @@ func TestRegistry_CheckUpkeeps(t *testing.T) {
}
e.client = client
- results, err := e.checkUpkeeps(context.Background(), tc.inputs)
+ results, err := e.checkUpkeeps(testutils.Context(t), tc.inputs)
assert.Equal(t, tc.results, results)
assert.Equal(t, tc.err, err)
})
@@ -651,7 +653,7 @@ func TestRegistry_SimulatePerformUpkeeps(t *testing.T) {
}).Once()
e.client = client
- results, err := e.simulatePerformUpkeeps(context.Background(), tc.inputs)
+ results, err := e.simulatePerformUpkeeps(testutils.Context(t), tc.inputs)
assert.Equal(t, tc.results, results)
assert.Equal(t, tc.err, err)
})
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
index 58e95bc423..a33056977a 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
@@ -1,29 +1,29 @@
package transmit
import (
- "context"
"math/big"
"runtime"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
)
func TestTransmitEventProvider_Sanity(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := testutils.Context(t)
lp := new(mocks.LogPoller)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go
index 8e2e77f7fb..579d875792 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go
@@ -357,7 +357,7 @@ func TestUpkeepStateStore_SetSelectIntegration(t *testing.T) {
})
for _, insert := range test.storedValues {
- require.NoError(t, store.SetUpkeepState(context.Background(), insert.result, insert.state), "storing states should not produce an error")
+ require.NoError(t, store.SetUpkeepState(ctx, insert.result, insert.state), "storing states should not produce an error")
}
tickerCh <- time.Now()
@@ -408,7 +408,7 @@ func TestUpkeepStateStore_emptyDB(t *testing.T) {
scanner := &mockScanner{}
store := NewUpkeepStateStore(orm, lggr, scanner)
- states, err := store.SelectByWorkIDs(context.Background(), []string{"0x1", "0x2", "0x3", "0x4"}...)
+ states, err := store.SelectByWorkIDs(testutils.Context(t), []string{"0x1", "0x2", "0x3", "0x4"}...)
assert.NoError(t, err)
assert.Equal(t, []ocr2keepers.UpkeepState{
ocr2keepers.UnknownState,
@@ -454,6 +454,7 @@ func TestUpkeepStateStore_Upsert(t *testing.T) {
}
func TestUpkeepStateStore_Service(t *testing.T) {
+ ctx := testutils.Context(t)
orm := &mockORM{
onDelete: func(tm time.Time) {
@@ -466,10 +467,10 @@ func TestUpkeepStateStore_Service(t *testing.T) {
store.retention = 500 * time.Millisecond
store.cleanCadence = 100 * time.Millisecond
- assert.NoError(t, store.Start(context.Background()), "no error from starting service")
+ assert.NoError(t, store.Start(ctx), "no error from starting service")
// add a value to set up the test
- require.NoError(t, store.SetUpkeepState(context.Background(), ocr2keepers.CheckResult{
+ require.NoError(t, store.SetUpkeepState(ctx, ocr2keepers.CheckResult{
Eligible: false,
WorkID: "0x2",
Trigger: ocr2keepers.Trigger{
@@ -481,7 +482,7 @@ func TestUpkeepStateStore_Service(t *testing.T) {
time.Sleep(110 * time.Millisecond)
// select from store to ensure values still exist
- values, err := store.SelectByWorkIDs(context.Background(), "0x2")
+ values, err := store.SelectByWorkIDs(ctx, "0x2")
require.NoError(t, err, "no error from selecting states")
require.Equal(t, []ocr2keepers.UpkeepState{ocr2keepers.Ineligible}, values, "selected values should match expected")
@@ -489,7 +490,7 @@ func TestUpkeepStateStore_Service(t *testing.T) {
time.Sleep(700 * time.Millisecond)
// select from store to ensure cached values were removed
- values, err = store.SelectByWorkIDs(context.Background(), "0x2")
+ values, err = store.SelectByWorkIDs(ctx, "0x2")
require.NoError(t, err, "no error from selecting states")
require.Equal(t, []ocr2keepers.UpkeepState{ocr2keepers.UnknownState}, values, "selected values should match expected")
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
index 109a644ca0..d2f35a3e37 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
@@ -890,6 +890,7 @@ func (c *feedLookupUpkeepController) EnableMercury(
MercuryEnabled: true,
})
+ ctx := testutils.Context(t)
for _, id := range c.upkeepIds {
if _, err := registry.SetUpkeepPrivilegeConfig(registryOwner, id, adminBytes); err != nil {
require.NoError(t, err)
@@ -900,7 +901,7 @@ func (c *feedLookupUpkeepController) EnableMercury(
callOpts := &bind.CallOpts{
Pending: true,
From: registryOwner.From,
- Context: context.Background(),
+ Context: ctx,
}
bts, err := registry.GetUpkeepPrivilegeConfig(callOpts, id)
@@ -989,7 +990,7 @@ func (c *feedLookupUpkeepController) EmitEvents(
backend.Commit()
// verify event was emitted
- block, _ := backend.BlockByHash(context.Background(), backend.Commit())
+ block, _ := backend.BlockByHash(ctx, backend.Commit())
t.Logf("block number after emit event: %d", block.NumberU64())
iter, _ := c.protocol.FilterLimitOrderExecuted(
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
index a2184d92ae..3eda886796 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
@@ -1,7 +1,6 @@
package ocr2keeper_test
import (
- "context"
"crypto/rand"
"encoding/hex"
"encoding/json"
@@ -171,14 +170,14 @@ func (node *Node) AddJob(t *testing.T, spec string) {
c := node.App.GetConfig()
jb, err := validate.ValidatedOracleSpecToml(c.OCR2(), c.Insecure(), spec)
require.NoError(t, err)
- err = node.App.AddJobV2(context.Background(), &jb)
+ err = node.App.AddJobV2(testutils.Context(t), &jb)
require.NoError(t, err)
}
func (node *Node) AddBootstrapJob(t *testing.T, spec string) {
jb, err := ocrbootstrap.ValidatedBootstrapSpecToml(spec)
require.NoError(t, err)
- err = node.App.AddJobV2(context.Background(), &jb)
+ err = node.App.AddJobV2(testutils.Context(t), &jb)
require.NoError(t, err)
}
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 57d13a69ec..38d7acf7e9 100644
--- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
@@ -1,7 +1,6 @@
package internal_test
import (
- "context"
"crypto/rand"
"encoding/hex"
"errors"
@@ -336,6 +335,7 @@ func TestIntegration_OCR2VRF(t *testing.T) {
}
func runOCR2VRFTest(t *testing.T, useForwarders bool) {
+ ctx := testutils.Context(t)
keyID := randomKeyID(t)
uni := setupOCR2VRFContracts(t, 5, keyID, false)
@@ -409,7 +409,7 @@ func runOCR2VRFTest(t *testing.T, useForwarders bool) {
}
}()
- blockBeforeConfig, err := uni.backend.BlockByNumber(context.Background(), nil)
+ blockBeforeConfig, err := uni.backend.BlockByNumber(ctx, nil)
require.NoError(t, err)
t.Log("Setting DKG config before block:", blockBeforeConfig.Number().String())
@@ -447,7 +447,7 @@ fromBlock = %d
t.Log("Creating bootstrap job:", bootstrapJobSpec)
ocrJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(bootstrapJobSpec)
require.NoError(t, err)
- err = bootstrapNode.app.AddJobV2(context.Background(), &ocrJob)
+ err = bootstrapNode.app.AddJobV2(ctx, &ocrJob)
require.NoError(t, err)
t.Log("Creating OCR2VRF jobs")
@@ -499,7 +499,7 @@ linkEthFeedAddress = "%s"
t.Log("Creating OCR2VRF job with spec:", jobSpec)
ocrJob2, err2 := validate.ValidatedOracleSpecToml(apps[i].Config.OCR2(), apps[i].Config.Insecure(), jobSpec)
require.NoError(t, err2)
- err2 = apps[i].AddJobV2(context.Background(), &ocrJob2)
+ err2 = apps[i].AddJobV2(ctx, &ocrJob2)
require.NoError(t, err2)
}
diff --git a/core/services/ocr2/plugins/promwrapper/plugin_test.go b/core/services/ocr2/plugins/promwrapper/plugin_test.go
index 5c12c18f85..b4de7f027f 100644
--- a/core/services/ocr2/plugins/promwrapper/plugin_test.go
+++ b/core/services/ocr2/plugins/promwrapper/plugin_test.go
@@ -8,10 +8,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/promwrapper/mocks"
)
@@ -194,14 +196,16 @@ func TestPlugin_GetLatencies(t *testing.T) {
).(*promPlugin)
require.NotEqual(t, nil, promPlugin)
+ ctx := testutils.Context(t)
+
// Run OCR methods.
- _, err := promPlugin.Query(context.Background(), reportTimestamp)
+ _, err := promPlugin.Query(ctx, reportTimestamp)
require.NoError(t, err)
_, ok := promPlugin.queryEndTimes.Load(reportTimestamp)
require.Equal(t, true, ok)
time.Sleep(qToOLatency)
- _, err = promPlugin.Observation(context.Background(), reportTimestamp, nil)
+ _, err = promPlugin.Observation(ctx, reportTimestamp, nil)
require.NoError(t, err)
_, ok = promPlugin.queryEndTimes.Load(reportTimestamp)
require.Equal(t, false, ok)
@@ -209,7 +213,7 @@ func TestPlugin_GetLatencies(t *testing.T) {
require.Equal(t, true, ok)
time.Sleep(oToRLatency)
- _, _, err = promPlugin.Report(context.Background(), reportTimestamp, nil, nil)
+ _, _, err = promPlugin.Report(ctx, reportTimestamp, nil, nil)
require.NoError(t, err)
_, ok = promPlugin.observationEndTimes.Load(reportTimestamp)
require.Equal(t, false, ok)
@@ -217,7 +221,7 @@ func TestPlugin_GetLatencies(t *testing.T) {
require.Equal(t, true, ok)
time.Sleep(rToALatency)
- _, err = promPlugin.ShouldAcceptFinalizedReport(context.Background(), reportTimestamp, nil)
+ _, err = promPlugin.ShouldAcceptFinalizedReport(ctx, reportTimestamp, nil)
require.NoError(t, err)
_, ok = promPlugin.reportEndTimes.Load(reportTimestamp)
require.Equal(t, false, ok)
@@ -225,7 +229,7 @@ func TestPlugin_GetLatencies(t *testing.T) {
require.Equal(t, true, ok)
time.Sleep(aToTLatency)
- _, err = promPlugin.ShouldTransmitAcceptedReport(context.Background(), reportTimestamp, nil)
+ _, err = promPlugin.ShouldTransmitAcceptedReport(ctx, reportTimestamp, nil)
require.NoError(t, err)
_, ok = promPlugin.acceptFinalizedReportEndTimes.Load(reportTimestamp)
require.Equal(t, false, ok)
diff --git a/core/services/relay/evm/mercury/persistence_manager_test.go b/core/services/relay/evm/mercury/persistence_manager_test.go
index dbdb977725..755d64a5a2 100644
--- a/core/services/relay/evm/mercury/persistence_manager_test.go
+++ b/core/services/relay/evm/mercury/persistence_manager_test.go
@@ -1,18 +1,18 @@
package mercury
import (
- "context"
"testing"
"time"
"github.com/cometbft/cometbft/libs/rand"
"github.com/jmoiron/sqlx"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -30,7 +30,7 @@ func TestPersistenceManager(t *testing.T) {
jobID1 := rand.Int32()
jobID2 := jobID1 + 1
- ctx := context.Background()
+ ctx := testutils.Context(t)
db := pgtest.NewSqlxDB(t)
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
@@ -69,7 +69,7 @@ func TestPersistenceManager(t *testing.T) {
}
func TestPersistenceManagerAsyncDelete(t *testing.T) {
- ctx := context.Background()
+ ctx := testutils.Context(t)
jobID := rand.Int32()
db := pgtest.NewSqlxDB(t)
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
@@ -120,7 +120,7 @@ func TestPersistenceManagerPrune(t *testing.T) {
pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`)
pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`)
- ctx := context.Background()
+ ctx := testutils.Context(t)
reports := make([][]byte, 25)
for i := 0; i < 25; i++ {
diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go
index 635658d786..6eb9f430c6 100644
--- a/core/services/relay/evm/mercury/v1/data_source_test.go
+++ b/core/services/relay/evm/mercury/v1/data_source_test.go
@@ -432,7 +432,7 @@ func TestMercury_SetLatestBlocks(t *testing.T) {
ds.chainReader = evm.NewChainReader(headTracker)
obs := relaymercuryv1.Observation{}
- err := ds.setLatestBlocks(context.Background(), &obs)
+ err := ds.setLatestBlocks(testutils.Context(t), &obs)
assert.NoError(t, err)
assert.Equal(t, h.Number, obs.CurrentBlockNum.Val)
@@ -450,7 +450,7 @@ func TestMercury_SetLatestBlocks(t *testing.T) {
ds.chainReader = evm.NewChainReader(headTracker)
obs := relaymercuryv1.Observation{}
- err := ds.setLatestBlocks(context.Background(), &obs)
+ err := ds.setLatestBlocks(testutils.Context(t), &obs)
assert.NoError(t, err)
assert.Zero(t, obs.CurrentBlockNum.Val)
diff --git a/core/services/relay/grpc_provider_server_test.go b/core/services/relay/grpc_provider_server_test.go
index fafe20ef12..6aff32f5e3 100644
--- a/core/services/relay/grpc_provider_server_test.go
+++ b/core/services/relay/grpc_provider_server_test.go
@@ -1,19 +1,19 @@
package relay
import (
- "context"
"testing"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-common/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
func TestProviderServer(t *testing.T) {
r := &mockRelayer{}
sa := NewServerAdapter(r, mockRelayerExt{})
- mp, _ := sa.NewPluginProvider(context.Background(), types.RelayArgs{ProviderType: string(types.Median)}, types.PluginArgs{})
+ mp, _ := sa.NewPluginProvider(testutils.Context(t), types.RelayArgs{ProviderType: string(types.Median)}, types.PluginArgs{})
lggr := logger.TestLogger(t)
_, err := NewProviderServer(mp, "unsupported-type", lggr)
diff --git a/core/services/relay/relay_test.go b/core/services/relay/relay_test.go
index fc9e273e30..18a7b1b44e 100644
--- a/core/services/relay/relay_test.go
+++ b/core/services/relay/relay_test.go
@@ -1,7 +1,6 @@
package relay
import (
- "context"
"testing"
"github.com/stretchr/testify/assert"
@@ -11,6 +10,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink-common/pkg/types"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
)
func TestIdentifier_UnmarshalString(t *testing.T) {
@@ -160,9 +160,10 @@ func TestRelayerServerAdapter(t *testing.T) {
},
}
+ ctx := testutils.Context(t)
for _, tc := range testCases {
pp, err := sa.NewPluginProvider(
- context.Background(),
+ ctx,
types.RelayArgs{ProviderType: tc.ProviderType},
types.PluginArgs{},
)
diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go
index d24fb348b7..31f7ea74c1 100644
--- a/core/services/telemetry/manager_test.go
+++ b/core/services/telemetry/manager_test.go
@@ -1,7 +1,6 @@
package telemetry
import (
- "context"
"fmt"
"math/big"
"net/url"
@@ -190,7 +189,7 @@ func TestNewManager(t *testing.T) {
require.Equal(t, "TelemetryManager", m.Name())
- require.Nil(t, m.Start(context.Background()))
+ require.Nil(t, m.Start(testutils.Context(t)))
testutils.WaitForLogMessageCount(t, logObs, "error connecting error while dialing dial tcp", 3)
hr := m.HealthReport()
diff --git a/core/services/transmission/integration_test.go b/core/services/transmission/integration_test.go
index 58521dcdf8..c8c6137cad 100644
--- a/core/services/transmission/integration_test.go
+++ b/core/services/transmission/integration_test.go
@@ -1,7 +1,6 @@
package transmission_test
import (
- "context"
"math/big"
"testing"
@@ -398,7 +397,7 @@ func Test4337WithLinkTokenVRFRequestAndPaymaster(t *testing.T) {
)
require.NoError(t, err)
backend.Commit()
- _, err = bind.WaitMined(context.Background(), backend, tx)
+ _, err = bind.WaitMined(testutils.Context(t), backend, tx)
require.NoError(t, err)
// Generate encoded paymaster data to fund the VRF consumer.
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index 15121ba306..6880fa1799 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -1,7 +1,6 @@
package v2_test
import (
- "context"
"encoding/hex"
"encoding/json"
"fmt"
@@ -422,21 +421,22 @@ func deployOldCoordinator(
common.Address,
*vrf_coordinator_v2.VRFCoordinatorV2,
) {
+ ctx := testutils.Context(t)
bytecode := hexutil.MustDecode("0x60e06040523480156200001157600080fd5b506040516200608c3803806200608c8339810160408190526200003491620001b1565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e8565b5050506001600160601b0319606093841b811660805290831b811660a052911b1660c052620001fb565b6001600160a01b038116331415620001435760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001ac57600080fd5b919050565b600080600060608486031215620001c757600080fd5b620001d28462000194565b9250620001e26020850162000194565b9150620001f26040850162000194565b90509250925092565b60805160601c60a05160601c60c05160601c615e2762000265600039600081816105260152613bd901526000818161061d015261402401526000818161036d01528181611599015281816125960152818161302c0152818161318201526138360152615e276000f3fe608060405234801561001057600080fd5b506004361061025b5760003560e01c80636f64f03f11610145578063ad178361116100bd578063d2f9f9a71161008c578063e72f6e3011610071578063e72f6e30146106fa578063e82ad7d41461070d578063f2fde38b1461073057600080fd5b8063d2f9f9a7146106d4578063d7ae1d30146106e757600080fd5b8063ad17836114610618578063af198b971461063f578063c3f909d41461066f578063caf70c4a146106c157600080fd5b80638da5cb5b11610114578063a21a23e4116100f9578063a21a23e4146105da578063a47c7696146105e2578063a4c0ed361461060557600080fd5b80638da5cb5b146105a95780639f87fad7146105c757600080fd5b80636f64f03f146105685780637341c10c1461057b57806379ba50971461058e578063823597401461059657600080fd5b8063356dac71116101d85780635fbbc0d2116101a757806366316d8d1161018c57806366316d8d1461050e578063689c45171461052157806369bcdb7d1461054857600080fd5b80635fbbc0d21461040057806364d51a2a1461050657600080fd5b8063356dac71146103b457806340d6bb82146103bc5780634cb48a54146103da5780635d3b1d30146103ed57600080fd5b806308821d581161022f57806315c48b841161021457806315c48b841461030e578063181f5a77146103295780631b6b6d231461036857600080fd5b806308821d58146102cf57806312b58349146102e257600080fd5b80620122911461026057806302bcc5b61461028057806304c357cb1461029557806306bfa637146102a8575b600080fd5b610268610743565b60405161027793929190615964565b60405180910390f35b61029361028e366004615792565b6107bf565b005b6102936102a33660046157ad565b61086b565b60055467ffffffffffffffff165b60405167ffffffffffffffff9091168152602001610277565b6102936102dd3660046154a3565b610a60565b6005546801000000000000000090046bffffffffffffffffffffffff165b604051908152602001610277565b61031660c881565b60405161ffff9091168152602001610277565b604080518082018252601681527f565246436f6f7264696e61746f72563220312e302e30000000000000000000006020820152905161027791906158f1565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610277565b600a54610300565b6103c56101f481565b60405163ffffffff9091168152602001610277565b6102936103e836600461563c565b610c3f565b6103006103fb366004615516565b611036565b600c546040805163ffffffff80841682526401000000008404811660208301526801000000000000000084048116928201929092526c010000000000000000000000008304821660608201527001000000000000000000000000000000008304909116608082015262ffffff740100000000000000000000000000000000000000008304811660a0830152770100000000000000000000000000000000000000000000008304811660c08301527a0100000000000000000000000000000000000000000000000000008304811660e08301527d01000000000000000000000000000000000000000000000000000000000090920490911661010082015261012001610277565b610316606481565b61029361051c36600461545b565b611444565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b610300610556366004615779565b60009081526009602052604090205490565b6102936105763660046153a0565b6116ad565b6102936105893660046157ad565b6117f7565b610293611a85565b6102936105a4366004615792565b611b82565b60005473ffffffffffffffffffffffffffffffffffffffff1661038f565b6102936105d53660046157ad565b611d7c565b6102b66121fd565b6105f56105f0366004615792565b6123ed565b6040516102779493929190615b02565b6102936106133660046153d4565b612537565b61038f7f000000000000000000000000000000000000000000000000000000000000000081565b61065261064d366004615574565b6127a8565b6040516bffffffffffffffffffffffff9091168152602001610277565b600b546040805161ffff8316815263ffffffff6201000084048116602083015267010000000000000084048116928201929092526b010000000000000000000000909204166060820152608001610277565b6103006106cf3660046154bf565b612c6d565b6103c56106e2366004615792565b612c9d565b6102936106f53660046157ad565b612e92565b610293610708366004615385565b612ff3565b61072061071b366004615792565b613257565b6040519015158152602001610277565b61029361073e366004615385565b6134ae565b600b546007805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff169391928391908301828280156107ad57602002820191906000526020600020905b815481526020019060010190808311610799575b50505050509050925092509250909192565b6107c76134bf565b67ffffffffffffffff811660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1661082d576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526003602052604090205461086890829073ffffffffffffffffffffffffffffffffffffffff16613542565b50565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff16806108d4576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821614610940576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b600b546601000000000000900460ff1615610987576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff841660009081526003602052604090206001015473ffffffffffffffffffffffffffffffffffffffff848116911614610a5a5767ffffffffffffffff841660008181526003602090815260409182902060010180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091558251338152918201527f69436ea6df009049404f564eff6622cd00522b0bd6a89efd9e52a355c4a879be91015b60405180910390a25b50505050565b610a686134bf565b604080518082018252600091610a97919084906002908390839080828437600092019190915250612c6d915050565b60008181526006602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1680610af9576040517f77f5b84c00000000000000000000000000000000000000000000000000000000815260048101839052602401610937565b600082815260066020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b600754811015610be9578260078281548110610b4c57610b4c615dbc565b90600052602060002001541415610bd7576007805460009190610b7190600190615c76565b81548110610b8157610b81615dbc565b906000526020600020015490508060078381548110610ba257610ba2615dbc565b6000918252602090912001556007805480610bbf57610bbf615d8d565b60019003818190600052602060002001600090559055505b80610be181615cba565b915050610b2e565b508073ffffffffffffffffffffffffffffffffffffffff167f72be339577868f868798bac2c93e52d6f034fef4689a9848996c14ebb7416c0d83604051610c3291815260200190565b60405180910390a2505050565b610c476134bf565b60c861ffff87161115610c9a576040517fa738697600000000000000000000000000000000000000000000000000000000815261ffff871660048201819052602482015260c86044820152606401610937565b60008213610cd7576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101839052602401610937565b6040805160a0808201835261ffff891680835263ffffffff89811660208086018290526000868801528a831660608088018290528b85166080988901819052600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001690971762010000909502949094177fffffffffffffffffffffffffffffffffff000000000000000000ffffffffffff166701000000000000009092027fffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffff16919091176b010000000000000000000000909302929092179093558651600c80549489015189890151938a0151978a0151968a015160c08b015160e08c01516101008d01519588167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009099169890981764010000000093881693909302929092177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1668010000000000000000958716959095027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16949094176c0100000000000000000000000098861698909802979097177fffffffffffffffffff00000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000096909416959095027fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff16929092177401000000000000000000000000000000000000000062ffffff92831602177fffffff000000000000ffffffffffffffffffffffffffffffffffffffffffffff1677010000000000000000000000000000000000000000000000958216959095027fffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffff16949094177a01000000000000000000000000000000000000000000000000000092851692909202919091177cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167d0100000000000000000000000000000000000000000000000000000000009390911692909202919091178155600a84905590517fc21e3bd2e0b339d2848f0dd956947a88966c242c0c0c582a33137a5c1ceb5cb2916110269189918991899189918991906159c3565b60405180910390a1505050505050565b600b546000906601000000000000900460ff1615611080576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff851660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff166110e6576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260026020908152604080832067ffffffffffffffff808a1685529252909120541680611156576040517ff0019fe600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152336024820152604401610937565b600b5461ffff9081169086161080611172575060c861ffff8616115b156111c257600b546040517fa738697600000000000000000000000000000000000000000000000000000000815261ffff8088166004830152909116602482015260c86044820152606401610937565b600b5463ffffffff620100009091048116908516111561122957600b546040517ff5d7e01e00000000000000000000000000000000000000000000000000000000815263ffffffff8087166004830152620100009092049091166024820152604401610937565b6101f463ffffffff8416111561127b576040517f47386bec00000000000000000000000000000000000000000000000000000000815263ffffffff841660048201526101f46024820152604401610937565b6000611288826001615bd2565b6040805160208082018c9052338284015267ffffffffffffffff808c16606084015284166080808401919091528351808403909101815260a08301845280519082012060c083018d905260e080840182905284518085039091018152610100909301909352815191012091925060009182916040805160208101849052439181019190915267ffffffffffffffff8c16606082015263ffffffff808b166080830152891660a08201523360c0820152919350915060e001604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160209182012060008681526009835283902055848352820183905261ffff8a169082015263ffffffff808916606083015287166080820152339067ffffffffffffffff8b16908c907f63373d1c4696214b898952999c9aaec57dac1ee2723cec59bea6888f489a97729060a00160405180910390a45033600090815260026020908152604080832067ffffffffffffffff808d16855292529091208054919093167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009091161790915591505095945050505050565b600b546601000000000000900460ff161561148b576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600860205260409020546bffffffffffffffffffffffff808316911610156114e5576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260086020526040812080548392906115129084906bffffffffffffffffffffffff16615c8d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555080600560088282829054906101000a90046bffffffffffffffffffffffff166115699190615c8d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b815260040161162192919073ffffffffffffffffffffffffffffffffffffffff9290921682526bffffffffffffffffffffffff16602082015260400190565b602060405180830381600087803b15801561163b57600080fd5b505af115801561164f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167391906154db565b6116a9576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b6116b56134bf565b6040805180820182526000916116e4919084906002908390839080828437600092019190915250612c6d915050565b60008181526006602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1615611746576040517f4a0b8fa700000000000000000000000000000000000000000000000000000000815260048101829052602401610937565b600081815260066020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091556007805460018101825594527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688909301849055518381527fe729ae16526293f74ade739043022254f1489f616295a25bf72dfb4511ed73b89101610c32565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff1680611860576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216146118c7576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610937565b600b546601000000000000900460ff161561190e576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff841660009081526003602052604090206002015460641415611965576040517f05a48e0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020908152604080832067ffffffffffffffff808916855292529091205416156119ac57610a5a565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020818152604080842067ffffffffffffffff8a1680865290835281852080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001908117909155600384528286209094018054948501815585529382902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001685179055905192835290917f43dc749a04ac8fb825cbd514f7c0e13f13bc6f2ee66043b76629d51776cff8e09101610a51565b60015473ffffffffffffffffffffffffffffffffffffffff163314611b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610937565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600b546601000000000000900460ff1615611bc9576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16611c2f576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526003602052604090206001015473ffffffffffffffffffffffffffffffffffffffff163314611cd15767ffffffffffffffff8116600090815260036020526040908190206001015490517fd084e97500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610937565b67ffffffffffffffff81166000818152600360209081526040918290208054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560019093018054909316909255835173ffffffffffffffffffffffffffffffffffffffff909116808252928101919091529092917f6f1dc65165ffffedfd8e507b4a0f1fcfdada045ed11f6c26ba27cedfe87802f0910160405180910390a25050565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff1680611de5576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821614611e4c576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610937565b600b546601000000000000900460ff1615611e93576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020908152604080832067ffffffffffffffff808916855292529091205416611f2e576040517ff0019fe600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff84166024820152604401610937565b67ffffffffffffffff8416600090815260036020908152604080832060020180548251818502810185019093528083529192909190830182828015611fa957602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611f7e575b50505050509050600060018251611fc09190615c76565b905060005b825181101561215f578573ffffffffffffffffffffffffffffffffffffffff16838281518110611ff757611ff7615dbc565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16141561214d57600083838151811061202f5761202f615dbc565b6020026020010151905080600360008a67ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600201838154811061207557612075615dbc565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff949094169390931790925567ffffffffffffffff8a1681526003909152604090206002018054806120ef576120ef615d8d565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555061215f565b8061215781615cba565b915050611fc5565b5073ffffffffffffffffffffffffffffffffffffffff8516600081815260026020908152604080832067ffffffffffffffff8b168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001690555192835290917f182bff9831466789164ca77075fffd84916d35a8180ba73c27e45634549b445b91015b60405180910390a2505050505050565b600b546000906601000000000000900460ff1615612247576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005805467ffffffffffffffff1690600061226183615cf3565b82546101009290920a67ffffffffffffffff8181021990931691831602179091556005541690506000806040519080825280602002602001820160405280156122b4578160200160208202803683370190505b506040805180820182526000808252602080830182815267ffffffffffffffff888116808552600484528685209551865493516bffffffffffffffffffffffff9091167fffffffffffffffffffffffff0000000000000000000000000000000000000000948516176c010000000000000000000000009190931602919091179094558451606081018652338152808301848152818701888152958552600384529590932083518154831673ffffffffffffffffffffffffffffffffffffffff918216178255955160018201805490931696169590951790559151805194955090936123a592600285019201906150c5565b505060405133815267ffffffffffffffff841691507f464722b4166576d3dcbba877b999bc35cf911f4eaf434b7eba68fa113951d0bf9060200160405180910390a250905090565b67ffffffffffffffff81166000908152600360205260408120548190819060609073ffffffffffffffffffffffffffffffffffffffff1661245a576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80861660009081526004602090815260408083205460038352928190208054600290910180548351818602810186019094528084526bffffffffffffffffffffffff8616966c010000000000000000000000009096049095169473ffffffffffffffffffffffffffffffffffffffff90921693909291839183018282801561252157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116124f6575b5050505050905093509350935093509193509193565b600b546601000000000000900460ff161561257e576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146125ed576040517f44b0e3c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114612627576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061263582840184615792565b67ffffffffffffffff811660009081526003602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1661269e576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8116600090815260046020526040812080546bffffffffffffffffffffffff16918691906126d58385615bfe565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555084600560088282829054906101000a90046bffffffffffffffffffffffff1661272c9190615bfe565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508167ffffffffffffffff167fd39ec07f4e209f627a4c427971473820dc129761ba28de8906bd56f57101d4f88287846127939190615bba565b604080519283526020830191909152016121ed565b600b546000906601000000000000900460ff16156127f2576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005a9050600080600061280687876139b5565b9250925092506000866060015163ffffffff1667ffffffffffffffff81111561283157612831615deb565b60405190808252806020026020018201604052801561285a578160200160208202803683370190505b50905060005b876060015163ffffffff168110156128ce5760408051602081018590529081018290526060016040516020818303038152906040528051906020012060001c8282815181106128b1576128b1615dbc565b6020908102919091010152806128c681615cba565b915050612860565b506000838152600960205260408082208290555181907f1fe543e300000000000000000000000000000000000000000000000000000000906129169087908690602401615ab4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252600b80547fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff166601000000000000179055908a015160808b01519192506000916129e49163ffffffff169084613d04565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff1690556020808c01805167ffffffffffffffff9081166000908152600490935260408084205492518216845290922080549394506c01000000000000000000000000918290048316936001939192600c92612a68928692900416615bd2565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000612abf8a600b600001600b9054906101000a900463ffffffff1663ffffffff16612ab985612c9d565b3a613d52565b6020808e015167ffffffffffffffff166000908152600490915260409020549091506bffffffffffffffffffffffff80831691161015612b2b576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808d015167ffffffffffffffff1660009081526004909152604081208054839290612b679084906bffffffffffffffffffffffff16615c8d565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008b81526006602090815260408083205473ffffffffffffffffffffffffffffffffffffffff1683526008909152812080548594509092612bd091859116615bfe565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550877f7dffc5ae5ee4e2e4df1651cf6ad329a73cebdb728f37ea0187b9b17e036756e4888386604051612c53939291909283526bffffffffffffffffffffffff9190911660208301521515604082015260600190565b60405180910390a299505050505050505050505b92915050565b600081604051602001612c8091906158e3565b604051602081830303815290604052805190602001209050919050565b6040805161012081018252600c5463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c010000000000000000000000008104831660608301527001000000000000000000000000000000008104909216608082015262ffffff740100000000000000000000000000000000000000008304811660a08301819052770100000000000000000000000000000000000000000000008404821660c08401527a0100000000000000000000000000000000000000000000000000008404821660e08401527d0100000000000000000000000000000000000000000000000000000000009093041661010082015260009167ffffffffffffffff841611612dbb575192915050565b8267ffffffffffffffff168160a0015162ffffff16108015612df057508060c0015162ffffff168367ffffffffffffffff1611155b15612dff576020015192915050565b8267ffffffffffffffff168160c0015162ffffff16108015612e3457508060e0015162ffffff168367ffffffffffffffff1611155b15612e43576040015192915050565b8267ffffffffffffffff168160e0015162ffffff16108015612e79575080610100015162ffffff168367ffffffffffffffff1611155b15612e88576060015192915050565b6080015192915050565b67ffffffffffffffff8216600090815260036020526040902054829073ffffffffffffffffffffffffffffffffffffffff1680612efb576040517f1f6a65b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821614612f62576040517fd8a3fb5200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610937565b600b546601000000000000900460ff1615612fa9576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb284613257565b15612fe9576040517fb42f66e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a5a8484613542565b612ffb6134bf565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a082319060240160206040518083038186803b15801561308357600080fd5b505afa158015613097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130bb91906154fd565b6005549091506801000000000000000090046bffffffffffffffffffffffff168181111561311f576040517fa99da3020000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610937565b818110156132525760006131338284615c76565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb90604401602060405180830381600087803b1580156131c857600080fd5b505af11580156131dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061320091906154db565b506040805173ffffffffffffffffffffffffffffffffffffffff86168152602081018390527f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600910160405180910390a1505b505050565b67ffffffffffffffff811660009081526003602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561330657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116132db575b505050505081525050905060005b8160400151518110156134a45760005b60075481101561349157600061345a6007838154811061334657613346615dbc565b90600052602060002001548560400151858151811061336757613367615dbc565b602002602001015188600260008960400151898151811061338a5761338a615dbc565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040908101600090812067ffffffffffffffff808f168352935220541660408051602080820187905273ffffffffffffffffffffffffffffffffffffffff959095168183015267ffffffffffffffff9384166060820152919092166080808301919091528251808303909101815260a08201835280519084012060c082019490945260e080820185905282518083039091018152610100909101909152805191012091565b506000818152600960205260409020549091501561347e5750600195945050505050565b508061348981615cba565b915050613324565b508061349c81615cba565b915050613314565b5060009392505050565b6134b66134bf565b61086881613e5a565b60005473ffffffffffffffffffffffffffffffffffffffff163314613540576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610937565b565b600b546601000000000000900460ff1615613589576040517fed3ba6a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff821660009081526003602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff90811682526001830154168185015260028201805484518187028101870186528181529295939486019383018282801561363457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311613609575b5050509190925250505067ffffffffffffffff80851660009081526004602090815260408083208151808301909252546bffffffffffffffffffffffff81168083526c01000000000000000000000000909104909416918101919091529293505b83604001515181101561373b5760026000856040015183815181106136bc576136bc615dbc565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040908101600090812067ffffffffffffffff8a168252909252902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001690558061373381615cba565b915050613695565b5067ffffffffffffffff8516600090815260036020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590613796600283018261514f565b505067ffffffffffffffff8516600090815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600580548291906008906138069084906801000000000000000090046bffffffffffffffffffffffff16615c8d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836bffffffffffffffffffffffff166040518363ffffffff1660e01b81526004016138be92919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b602060405180830381600087803b1580156138d857600080fd5b505af11580156138ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391091906154db565b613946576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff861681526bffffffffffffffffffffffff8316602082015267ffffffffffffffff8716917fe8ed5b475a5b5987aa9165e8731bb78043f39eee32ec5a1169a89e27fcd49815910160405180910390a25050505050565b60008060006139c78560000151612c6d565b60008181526006602052604090205490935073ffffffffffffffffffffffffffffffffffffffff1680613a29576040517f77f5b84c00000000000000000000000000000000000000000000000000000000815260048101859052602401610937565b6080860151604051613a48918691602001918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600990935291205490935080613ac5576040517f3688124a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85516020808801516040808a015160608b015160808c01519251613b3e968b96909594910195865267ffffffffffffffff948516602087015292909316604085015263ffffffff908116606085015291909116608083015273ffffffffffffffffffffffffffffffffffffffff1660a082015260c00190565b604051602081830303815290604052805190602001208114613b8c576040517fd529142c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855167ffffffffffffffff164080613cb05786516040517fe9413d3800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9413d389060240160206040518083038186803b158015613c3057600080fd5b505afa158015613c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6891906154fd565b905080613cb05786516040517f175dadad00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610937565b6000886080015182604051602001613cd2929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c9050613cf78982613f50565b9450505050509250925092565b60005a611388811015613d1657600080fd5b611388810390508460408204820311613d2e57600080fd5b50823b613d3a57600080fd5b60008083516020850160008789f190505b9392505050565b600080613d5d613fd9565b905060008113613d9c576040517f43d4cf6600000000000000000000000000000000000000000000000000000000815260048101829052602401610937565b6000815a613daa8989615bba565b613db49190615c76565b613dc686670de0b6b3a7640000615c39565b613dd09190615c39565b613dda9190615c25565b90506000613df363ffffffff871664e8d4a51000615c39565b9050613e0b816b033b2e3c9fd0803ce8000000615c76565b821115613e44576040517fe80fa38100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e4e8183615bba565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116331415613eda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610937565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000613f848360000151846020015185604001518660600151868860a001518960c001518a60e001518b61010001516140ed565b60038360200151604051602001613f9c929190615aa0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209392505050565b600b54604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051600092670100000000000000900463ffffffff169182151591849182917f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163feaf968c9160048083019260a0929190829003018186803b15801561407f57600080fd5b505afa158015614093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b791906157d7565b5094509092508491505080156140db57506140d28242615c76565b8463ffffffff16105b156140e55750600a545b949350505050565b6140f6896143c4565b61415c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f7075626c6963206b6579206973206e6f74206f6e2063757276650000000000006044820152606401610937565b614165886143c4565b6141cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f67616d6d61206973206e6f74206f6e20637572766500000000000000000000006044820152606401610937565b6141d4836143c4565b61423a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610937565b614243826143c4565b6142a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f73486173685769746e657373206973206e6f74206f6e206375727665000000006044820152606401610937565b6142b5878a888761451f565b61431b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f6164647228632a706b2b732a6729213d5f755769746e657373000000000000006044820152606401610937565b60006143278a876146c2565b9050600061433a898b878b868989614726565b9050600061434b838d8d8a866148ae565b9050808a146143b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f696e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610937565b505050505050505050505050565b80516000907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f11614451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e76616c696420782d6f7264696e61746500000000000000000000000000006044820152606401610937565b60208201517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f116144de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e76616c696420792d6f7264696e61746500000000000000000000000000006044820152606401610937565b60208201517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f9080096145188360005b602002015161490c565b1492915050565b600073ffffffffffffffffffffffffffffffffffffffff821661459e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f626164207769746e6573730000000000000000000000000000000000000000006044820152606401610937565b6020840151600090600116156145b557601c6145b8565b601b5b905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641418587600060200201510986517ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141918203925060009190890987516040805160008082526020820180845287905260ff88169282019290925260608101929092526080820183905291925060019060a0016020604051602081039080840390855afa15801561466f573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff9081169088161495505050505050949350505050565b6146ca61516d565b6146f7600184846040516020016146e3939291906158c2565b604051602081830303815290604052614964565b90505b614703816143c4565b612c6757805160408051602081019290925261471f91016146e3565b90506146fa565b61472e61516d565b825186517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f90819006910614156147c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610937565b6147cc8789886149cd565b614832576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4669727374206d756c20636865636b206661696c6564000000000000000000006044820152606401610937565b61483d8486856149cd565b6148a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5365636f6e64206d756c20636865636b206661696c65640000000000000000006044820152606401610937565b613e4e868484614b5a565b6000600286868685876040516020016148cc96959493929190615850565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209695505050505050565b6000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80848509840990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f600782089392505050565b61496c61516d565b61497582614c89565b815261498a61498582600061450e565b614cde565b6020820181905260029006600114156149c8576020810180517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0390525b919050565b600082614a36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f7a65726f207363616c61720000000000000000000000000000000000000000006044820152606401610937565b83516020850151600090614a4c90600290615d1b565b15614a5857601c614a5b565b601b5b905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641418387096040805160008082526020820180845281905260ff86169282019290925260608101869052608081018390529192509060019060a0016020604051602081039080840390855afa158015614adb573d6000803e3d6000fd5b505050602060405103519050600086604051602001614afa919061583e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012073ffffffffffffffffffffffffffffffffffffffff92831692169190911498975050505050505050565b614b6261516d565b835160208086015185519186015160009384938493614b8393909190614d18565b919450925090507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f858209600114614c17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e765a206d75737420626520696e7665727365206f66207a000000000000006044820152606401610937565b60405180604001604052807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80614c5057614c50615d5e565b87860981526020017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8785099052979650505050505050565b805160208201205b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f81106149c857604080516020808201939093528151808203840181529082019091528051910120614c91565b6000612c67826002614d117ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f6001615bba565b901c614eae565b60008080600180827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f897ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f038808905060007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f038a0890506000614dc083838585614fa2565b9098509050614dd188828e88614ffa565b9098509050614de288828c87614ffa565b90985090506000614df58d878b85614ffa565b9098509050614e0688828686614fa2565b9098509050614e1788828e89614ffa565b9098509050818114614e9a577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f818a0998507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f82890997507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183099650614e9e565b8196505b5050505050509450945094915050565b600080614eb961518b565b6020808252818101819052604082015260608101859052608081018490527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f60a0820152614f056151a9565b60208160c08460057ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa925082614f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6269674d6f64457870206661696c7572652100000000000000000000000000006044820152606401610937565b5195945050505050565b6000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8487097ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8487099097909650945050505050565b600080807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f878509905060007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f87877ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f030990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183087ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f86890990999098509650505050505050565b82805482825590600052602060002090810192821561513f579160200282015b8281111561513f57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906150e5565b5061514b9291506151c7565b5090565b508054600082559060005260206000209081019061086891906151c7565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b8082111561514b57600081556001016151c8565b803573ffffffffffffffffffffffffffffffffffffffff811681146149c857600080fd5b8060408101831015612c6757600080fd5b600082601f83011261522257600080fd5b6040516040810181811067ffffffffffffffff8211171561524557615245615deb565b806040525080838560408601111561525c57600080fd5b60005b600281101561527e57813583526020928301929091019060010161525f565b509195945050505050565b600060a0828403121561529b57600080fd5b60405160a0810181811067ffffffffffffffff821117156152be576152be615deb565b6040529050806152cd83615353565b81526152db60208401615353565b60208201526152ec6040840161533f565b60408201526152fd6060840161533f565b606082015261530e608084016151dc565b60808201525092915050565b803561ffff811681146149c857600080fd5b803562ffffff811681146149c857600080fd5b803563ffffffff811681146149c857600080fd5b803567ffffffffffffffff811681146149c857600080fd5b805169ffffffffffffffffffff811681146149c857600080fd5b60006020828403121561539757600080fd5b613d4b826151dc565b600080606083850312156153b357600080fd5b6153bc836151dc565b91506153cb8460208501615200565b90509250929050565b600080600080606085870312156153ea57600080fd5b6153f3856151dc565b935060208501359250604085013567ffffffffffffffff8082111561541757600080fd5b818701915087601f83011261542b57600080fd5b81358181111561543a57600080fd5b88602082850101111561544c57600080fd5b95989497505060200194505050565b6000806040838503121561546e57600080fd5b615477836151dc565b915060208301356bffffffffffffffffffffffff8116811461549857600080fd5b809150509250929050565b6000604082840312156154b557600080fd5b613d4b8383615200565b6000604082840312156154d157600080fd5b613d4b8383615211565b6000602082840312156154ed57600080fd5b81518015158114613d4b57600080fd5b60006020828403121561550f57600080fd5b5051919050565b600080600080600060a0868803121561552e57600080fd5b8535945061553e60208701615353565b935061554c6040870161531a565b925061555a6060870161533f565b91506155686080870161533f565b90509295509295909350565b60008082840361024081121561558957600080fd5b6101a08082121561559957600080fd5b6155a1615b90565b91506155ad8686615211565b82526155bc8660408701615211565b60208301526080850135604083015260a0850135606083015260c085013560808301526155eb60e086016151dc565b60a08301526101006155ff87828801615211565b60c0840152615612876101408801615211565b60e0840152610180860135818401525081935061563186828701615289565b925050509250929050565b6000806000806000808688036101c081121561565757600080fd5b6156608861531a565b965061566e6020890161533f565b955061567c6040890161533f565b945061568a6060890161533f565b935060808801359250610120807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60830112156156c557600080fd5b6156cd615b90565b91506156db60a08a0161533f565b82526156e960c08a0161533f565b60208301526156fa60e08a0161533f565b604083015261010061570d818b0161533f565b606084015261571d828b0161533f565b608084015261572f6101408b0161532c565b60a08401526157416101608b0161532c565b60c08401526157536101808b0161532c565b60e08401526157656101a08b0161532c565b818401525050809150509295509295509295565b60006020828403121561578b57600080fd5b5035919050565b6000602082840312156157a457600080fd5b613d4b82615353565b600080604083850312156157c057600080fd5b6157c983615353565b91506153cb602084016151dc565b600080600080600060a086880312156157ef57600080fd5b6157f88661536b565b94506020860151935060408601519250606086015191506155686080870161536b565b8060005b6002811015610a5a57815184526020938401939091019060010161581f565b615848818361581b565b604001919050565b868152615860602082018761581b565b61586d606082018661581b565b61587a60a082018561581b565b61588760e082018461581b565b60609190911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166101208201526101340195945050505050565b8381526158d2602082018461581b565b606081019190915260800192915050565b60408101612c67828461581b565b600060208083528351808285015260005b8181101561591e57858101830151858201604001528201615902565b81811115615930576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b818110156159b557845183529383019391830191600101615999565b509098975050505050505050565b60006101c08201905061ffff8816825263ffffffff808816602084015280871660408401528086166060840152846080840152835481811660a0850152615a1760c08501838360201c1663ffffffff169052565b615a2e60e08501838360401c1663ffffffff169052565b615a466101008501838360601c1663ffffffff169052565b615a5e6101208501838360801c1663ffffffff169052565b62ffffff60a082901c811661014086015260b882901c811661016086015260d082901c1661018085015260e81c6101a090930192909252979650505050505050565b82815260608101613d4b602083018461581b565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015615af557845183529383019391830191600101615ad9565b5090979650505050505050565b6000608082016bffffffffffffffffffffffff87168352602067ffffffffffffffff87168185015273ffffffffffffffffffffffffffffffffffffffff80871660408601526080606086015282865180855260a087019150838801945060005b81811015615b80578551841683529484019491840191600101615b62565b50909a9950505050505050505050565b604051610120810167ffffffffffffffff81118282101715615bb457615bb4615deb565b60405290565b60008219821115615bcd57615bcd615d2f565b500190565b600067ffffffffffffffff808316818516808303821115615bf557615bf5615d2f565b01949350505050565b60006bffffffffffffffffffffffff808316818516808303821115615bf557615bf5615d2f565b600082615c3457615c34615d5e565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c7157615c71615d2f565b500290565b600082821015615c8857615c88615d2f565b500390565b60006bffffffffffffffffffffffff83811690831681811015615cb257615cb2615d2f565b039392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615cec57615cec615d2f565b5060010190565b600067ffffffffffffffff80831681811415615d1157615d11615d2f565b6001019392505050565b600082615d2a57615d2a615d5e565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a")
ctorArgs, err := utils.ABIEncode(`[{"type":"address"}, {"type":"address"}, {"type":"address"}]`, linkAddress, bhsAddress, linkEthFeed)
require.NoError(t, err)
bytecode = append(bytecode, ctorArgs...)
- nonce, err := backend.PendingNonceAt(context.Background(), neil.From)
+ nonce, err := backend.PendingNonceAt(ctx, neil.From)
require.NoError(t, err)
- gasPrice, err := backend.SuggestGasPrice(context.Background())
+ gasPrice, err := backend.SuggestGasPrice(ctx)
require.NoError(t, err)
unsignedTx := gethtypes.NewContractCreation(nonce, big.NewInt(0), 15e6, gasPrice, bytecode)
signedTx, err := neil.Signer(neil.From, unsignedTx)
require.NoError(t, err)
- err = backend.SendTransaction(context.Background(), signedTx)
+ err = backend.SendTransaction(ctx, signedTx)
require.NoError(t, err, "could not deploy old vrf coordinator to simulated blockchain")
backend.Commit()
- receipt, err := backend.TransactionReceipt(context.Background(), signedTx.Hash())
+ receipt, err := backend.TransactionReceipt(ctx, signedTx.Hash())
require.NoError(t, err)
oldRootContractAddress := receipt.ContractAddress
require.NotEqual(t, common.HexToAddress("0x0"), oldRootContractAddress, "old vrf coordinator address equal to zero address, deployment failed")
diff --git a/core/web/jobs_controller.go b/core/web/jobs_controller.go
index 4c8a77d370..0f97e0b53d 100644
--- a/core/web/jobs_controller.go
+++ b/core/web/jobs_controller.go
@@ -71,7 +71,7 @@ func (jc *JobsController) Show(c *gin.Context) {
jobSpec, err = jc.App.JobORM().FindJobByExternalJobID(externalJobID, pg.WithParentCtx(c.Request.Context()))
} else if pErr = jobSpec.SetID(c.Param("ID")); pErr == nil {
// Find a job by job ID
- jobSpec, err = jc.App.JobORM().FindJobTx(jobSpec.ID)
+ jobSpec, err = jc.App.JobORM().FindJobTx(c, jobSpec.ID)
} else {
jsonAPIError(c, http.StatusUnprocessableEntity, pErr)
return
diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go
index dfef099c17..06c2624d0f 100644
--- a/integration-tests/load/automationv2_1/automationv2_1_test.go
+++ b/integration-tests/load/automationv2_1/automationv2_1_test.go
@@ -15,11 +15,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/slack-go/slack"
+ "github.com/stretchr/testify/require"
+
ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
"github.com/smartcontractkit/wasp"
- "github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/config"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/environment"
@@ -125,6 +127,7 @@ var (
)
func TestLogTrigger(t *testing.T) {
+ ctx := tests.Context(t)
l := logging.GetTestLogger(t)
l.Info().Msg("Starting automation v2.1 log trigger load test")
@@ -467,7 +470,7 @@ func TestLogTrigger(t *testing.T) {
l.Info().Str("STARTUP_WAIT_TIME", StartupWaitTime.String()).Msg("Waiting for plugin to start")
time.Sleep(StartupWaitTime)
- startBlock, err := chainClient.LatestBlockNumber(context.Background())
+ startBlock, err := chainClient.LatestBlockNumber(ctx)
require.NoError(t, err, "Error getting latest block number")
p := wasp.NewProfile()
@@ -511,7 +514,7 @@ func TestLogTrigger(t *testing.T) {
endTime := time.Now()
testDuration := endTime.Sub(startTime)
l.Info().Str("Duration", testDuration.String()).Msg("Test Duration")
- endBlock, err := chainClient.LatestBlockNumber(context.Background())
+ endBlock, err := chainClient.LatestBlockNumber(ctx)
require.NoError(t, err, "Error getting latest block number")
l.Info().Uint64("Starting Block", startBlock).Uint64("Ending Block", endBlock).Msg("Test Block Range")
@@ -544,7 +547,8 @@ func TestLogTrigger(t *testing.T) {
Topics: [][]common.Hash{{consumerABI.Events["PerformingUpkeep"].ID}},
}
)
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ var cancel context.CancelFunc
+ ctx, cancel = context.WithTimeout(ctx, timeout)
logsInBatch, err := chainClient.FilterLogs(ctx, filterQuery)
cancel()
if err != nil {
diff --git a/plugins/medianpoc/data_source_test.go b/plugins/medianpoc/data_source_test.go
index 5848705b7b..9977daef3d 100644
--- a/plugins/medianpoc/data_source_test.go
+++ b/plugins/medianpoc/data_source_test.go
@@ -11,6 +11,7 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink-common/pkg/types"
@@ -60,7 +61,7 @@ func TestDataSource(t *testing.T) {
spec: spec,
lggr: lggr,
}
- res, err := ds.Observe(context.Background(), ocrtypes.ReportTimestamp{})
+ res, err := ds.Observe(tests.Context(t), ocrtypes.ReportTimestamp{})
require.NoError(t, err)
assert.Equal(t, big.NewInt(expect), res)
assert.Equal(t, spec, pr.spec)
@@ -86,7 +87,7 @@ func TestDataSource_ResultErrors(t *testing.T) {
spec: spec,
lggr: lggr,
}
- _, err := ds.Observe(context.Background(), ocrtypes.ReportTimestamp{})
+ _, err := ds.Observe(tests.Context(t), ocrtypes.ReportTimestamp{})
assert.ErrorContains(t, err, "something went wrong")
}
@@ -111,6 +112,6 @@ func TestDataSource_ResultNotAnInt(t *testing.T) {
spec: spec,
lggr: lggr,
}
- _, err := ds.Observe(context.Background(), ocrtypes.ReportTimestamp{})
+ _, err := ds.Observe(tests.Context(t), ocrtypes.ReportTimestamp{})
assert.ErrorContains(t, err, "cannot convert observation to decimal")
}
diff --git a/plugins/medianpoc/plugin_test.go b/plugins/medianpoc/plugin_test.go
index 569fcb464b..bc6af7ae5d 100644
--- a/plugins/medianpoc/plugin_test.go
+++ b/plugins/medianpoc/plugin_test.go
@@ -1,7 +1,6 @@
package medianpoc
import (
- "context"
"fmt"
"testing"
@@ -13,6 +12,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
"github.com/smartcontractkit/chainlink-common/pkg/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
@@ -89,7 +89,7 @@ func TestNewPlugin(t *testing.T) {
prov := provider{}
f, err := p.newFactory(
- context.Background(),
+ tests.Context(t),
config,
prov,
pr,
From 5e3d68e39b10917c0ed87c9097063ea9017ca56b Mon Sep 17 00:00:00 2001
From: Rens Rooimans
Date: Tue, 21 Nov 2023 08:52:30 +0100
Subject: [PATCH 181/327] Style update shared contracts (#11343)
* style update shared ocr2
* fix comment syntax in shared
* add struct packing comments and make natspec
---------
Co-authored-by: Austin Born
---
.../automation/v2_0/KeeperRegistry2_0.sol | 2 +-
.../automation/v2_1/KeeperRegistry2_1.sol | 2 +-
.../src/v0.8/shared/access/ConfirmedOwner.sol | 6 +-
.../access/ConfirmedOwnerWithProposal.sol | 31 ++--
.../access/SimpleReadAccessController.sol | 26 ++--
.../access/SimpleWriteAccessController.sol | 40 ++----
.../src/v0.8/shared/ocr2/OCR2Abstract.sol | 100 ++++++-------
contracts/src/v0.8/shared/ocr2/OCR2Base.sol | 136 ++++++++----------
8 files changed, 136 insertions(+), 207 deletions(-)
diff --git a/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol b/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol
index 7db02e72e7..bd3c78e45a 100644
--- a/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol
+++ b/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol
@@ -281,7 +281,7 @@ contract KeeperRegistry2_0 is
uint64 offchainConfigVersion,
bytes memory offchainConfig
) external override onlyOwner {
- if (signers.length > maxNumOracles) revert TooManyOracles();
+ if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles();
if (f == 0) revert IncorrectNumberOfFaultyOracles();
if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners();
diff --git a/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol b/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol
index 2f96df6d57..7c88f12f5a 100644
--- a/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol
+++ b/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol
@@ -250,7 +250,7 @@ contract KeeperRegistry2_1 is KeeperRegistryBase2_1, OCR2Abstract, Chainable, IE
uint64 offchainConfigVersion,
bytes memory offchainConfig
) public onlyOwner {
- if (signers.length > maxNumOracles) revert TooManyOracles();
+ if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles();
if (f == 0) revert IncorrectNumberOfFaultyOracles();
if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners();
diff --git a/contracts/src/v0.8/shared/access/ConfirmedOwner.sol b/contracts/src/v0.8/shared/access/ConfirmedOwner.sol
index a25d92ffd6..5b0c1593cc 100644
--- a/contracts/src/v0.8/shared/access/ConfirmedOwner.sol
+++ b/contracts/src/v0.8/shared/access/ConfirmedOwner.sol
@@ -3,10 +3,8 @@ pragma solidity ^0.8.0;
import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol";
-/**
- * @title The ConfirmedOwner contract
- * @notice A contract with helpers for basic contract ownership.
- */
+/// @title The ConfirmedOwner contract
+/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}
diff --git a/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol b/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol
index a6757c3886..7b68418754 100644
--- a/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol
+++ b/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol
@@ -3,10 +3,8 @@ pragma solidity ^0.8.0;
import {IOwnable} from "../interfaces/IOwnable.sol";
-/**
- * @title The ConfirmedOwner contract
- * @notice A contract with helpers for basic contract ownership.
- */
+/// @title The ConfirmedOwner contract
+/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwnerWithProposal is IOwnable {
address private s_owner;
address private s_pendingOwner;
@@ -24,17 +22,12 @@ contract ConfirmedOwnerWithProposal is IOwnable {
}
}
- /**
- * @notice Allows an owner to begin transferring ownership to a new address,
- * pending.
- */
+ /// @notice Allows an owner to begin transferring ownership to a new address.
function transferOwnership(address to) public override onlyOwner {
_transferOwnership(to);
}
- /**
- * @notice Allows an ownership transfer to be completed by the recipient.
- */
+ /// @notice Allows an ownership transfer to be completed by the recipient.
function acceptOwnership() external override {
// solhint-disable-next-line custom-errors
require(msg.sender == s_pendingOwner, "Must be proposed owner");
@@ -46,16 +39,12 @@ contract ConfirmedOwnerWithProposal is IOwnable {
emit OwnershipTransferred(oldOwner, msg.sender);
}
- /**
- * @notice Get the current owner
- */
+ /// @notice Get the current owner
function owner() public view override returns (address) {
return s_owner;
}
- /**
- * @notice validate, transfer ownership, and emit relevant events
- */
+ /// @notice validate, transfer ownership, and emit relevant events
function _transferOwnership(address to) private {
// solhint-disable-next-line custom-errors
require(to != msg.sender, "Cannot transfer to self");
@@ -65,17 +54,13 @@ contract ConfirmedOwnerWithProposal is IOwnable {
emit OwnershipTransferRequested(s_owner, to);
}
- /**
- * @notice validate access
- */
+ /// @notice validate access
function _validateOwnership() internal view {
// solhint-disable-next-line custom-errors
require(msg.sender == s_owner, "Only callable by owner");
}
- /**
- * @notice Reverts if called by anyone other than the contract owner.
- */
+ /// @notice Reverts if called by anyone other than the contract owner.
modifier onlyOwner() {
_validateOwnership();
_;
diff --git a/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol b/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol
index b36fa4e4b6..f4ea905bf9 100644
--- a/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol
+++ b/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol
@@ -3,22 +3,18 @@ pragma solidity ^0.8.0;
import {SimpleWriteAccessController} from "./SimpleWriteAccessController.sol";
-/**
- * @title SimpleReadAccessController
- * @notice Gives access to:
- * - any externally owned account (note that off-chain actors can always read
- * any contract storage regardless of on-chain access control measures, so this
- * does not weaken the access control while improving usability)
- * - accounts explicitly added to an access list
- * @dev SimpleReadAccessController is not suitable for access controlling writes
- * since it grants any externally owned account access! See
- * SimpleWriteAccessController for that.
- */
+/// @title SimpleReadAccessController
+/// @notice Gives access to:
+/// - any externally owned account (note that off-chain actors can always read
+/// any contract storage regardless of on-chain access control measures, so this
+/// does not weaken the access control while improving usability)
+/// - accounts explicitly added to an access list
+/// @dev SimpleReadAccessController is not suitable for access controlling writes
+/// since it grants any externally owned account access! See
+/// SimpleWriteAccessController for that.
contract SimpleReadAccessController is SimpleWriteAccessController {
- /**
- * @notice Returns the access of an address
- * @param _user The address to query
- */
+ /// @notice Returns the access of an address
+ /// @param _user The address to query
function hasAccess(address _user, bytes memory _calldata) public view virtual override returns (bool) {
// solhint-disable-next-line avoid-tx-origin
return super.hasAccess(_user, _calldata) || _user == tx.origin;
diff --git a/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol b/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol
index 117d2e77dd..b431331bc8 100644
--- a/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol
+++ b/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol
@@ -4,13 +4,9 @@ pragma solidity ^0.8.0;
import {ConfirmedOwner} from "./ConfirmedOwner.sol";
import {AccessControllerInterface} from "../interfaces/AccessControllerInterface.sol";
-/**
- * @title SimpleWriteAccessController
- * @notice Gives access to accounts explicitly added to an access list by the
- * controller's owner.
- * @dev does not make any special permissions for externally, see
- * SimpleReadAccessController for that.
- */
+/// @title SimpleWriteAccessController
+/// @notice Gives access to accounts explicitly added to an access list by the controller's owner.
+/// @dev does not make any special permissions for externally, see SimpleReadAccessController for that.
contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwner {
bool public checkEnabled;
mapping(address => bool) internal s_accessList;
@@ -24,18 +20,14 @@ contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwne
checkEnabled = true;
}
- /**
- * @notice Returns the access of an address
- * @param _user The address to query
- */
+ /// @notice Returns the access of an address
+ /// @param _user The address to query
function hasAccess(address _user, bytes memory) public view virtual override returns (bool) {
return s_accessList[_user] || !checkEnabled;
}
- /**
- * @notice Adds an address to the access list
- * @param _user The address to add
- */
+ /// @notice Adds an address to the access list
+ /// @param _user The address to add
function addAccess(address _user) external onlyOwner {
if (!s_accessList[_user]) {
s_accessList[_user] = true;
@@ -44,10 +36,8 @@ contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwne
}
}
- /**
- * @notice Removes an address from the access list
- * @param _user The address to remove
- */
+ /// @notice Removes an address from the access list
+ /// @param _user The address to remove
function removeAccess(address _user) external onlyOwner {
if (s_accessList[_user]) {
s_accessList[_user] = false;
@@ -56,9 +46,7 @@ contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwne
}
}
- /**
- * @notice makes the access check enforced
- */
+ /// @notice makes the access check enforced
function enableAccessCheck() external onlyOwner {
if (!checkEnabled) {
checkEnabled = true;
@@ -67,9 +55,7 @@ contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwne
}
}
- /**
- * @notice makes the access check unenforced
- */
+ /// @notice makes the access check unenforced
function disableAccessCheck() external onlyOwner {
if (checkEnabled) {
checkEnabled = false;
@@ -78,9 +64,7 @@ contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwne
}
}
- /**
- * @dev reverts if the caller does not have access
- */
+ /// @dev reverts if the caller does not have access
modifier checkAccess() {
// solhint-disable-next-line custom-errors
require(hasAccess(msg.sender, msg.data), "No access");
diff --git a/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol b/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol
index 1f19d0de54..cd3f197113 100644
--- a/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol
+++ b/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol
@@ -4,26 +4,20 @@ pragma solidity ^0.8.0;
import {ITypeAndVersion} from "../interfaces/ITypeAndVersion.sol";
abstract contract OCR2Abstract is ITypeAndVersion {
- // Maximum number of oracles the offchain reporting protocol is designed for
- // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
- uint256 internal constant maxNumOracles = 31;
- // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
- uint256 private constant prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00
- // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
- uint256 private constant prefix = 0x0001 << (256 - 16); // 0x000100..00
+ uint256 internal constant MAX_NUM_ORACLES = 31;
+ uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00
+ uint256 private constant PREFIX = 0x0001 << (256 - 16); // 0x000100..00
- /**
- * @notice triggers a new run of the offchain reporting protocol
- * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis
- * @param configDigest configDigest of this configuration
- * @param configCount ordinal number of this config setting among all config settings over the life of this contract
- * @param signers ith element is address ith oracle uses to sign a report
- * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method
- * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
- * @param onchainConfig serialized configuration used by the contract (and possibly oracles)
- * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter
- * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
- */
+ /// @notice triggers a new run of the offchain reporting protocol
+ /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis
+ /// @param configDigest configDigest of this configuration
+ /// @param configCount ordinal number of this config setting among all config settings over the life of this contract
+ /// @param signers ith element is address ith oracle uses to sign a report
+ /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method
+ /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
+ /// @param onchainConfig serialized configuration used by the contract (and possibly oracles)
+ /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter
+ /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
event ConfigSet(
uint32 previousConfigBlockNumber,
bytes32 configDigest,
@@ -36,15 +30,13 @@ abstract contract OCR2Abstract is ITypeAndVersion {
bytes offchainConfig
);
- /**
- * @notice sets offchain reporting protocol configuration incl. participating oracles
- * @param signers addresses with which oracles sign the reports
- * @param transmitters addresses oracles use to transmit the reports
- * @param f number of faulty oracles the system can tolerate
- * @param onchainConfig serialized configuration used by the contract (and possibly oracles)
- * @param offchainConfigVersion version number for offchainEncoding schema
- * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
- */
+ /// @notice sets offchain reporting protocol configuration incl. participating oracles
+ /// @param signers addresses with which oracles sign the reports
+ /// @param transmitters addresses oracles use to transmit the reports
+ /// @param f number of faulty oracles the system can tolerate
+ /// @param onchainConfig serialized configuration used by the contract (and possibly oracles)
+ /// @param offchainConfigVersion version number for offchainEncoding schema
+ /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
function setConfig(
address[] memory signers,
address[] memory transmitters,
@@ -54,12 +46,10 @@ abstract contract OCR2Abstract is ITypeAndVersion {
bytes memory offchainConfig
) external virtual;
- /**
- * @notice information about current offchain reporting protocol configuration
- * @return configCount ordinal number of current config, out of all configs applied to this contract so far
- * @return blockNumber block at which this config was set
- * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)
- */
+ /// @notice information about current offchain reporting protocol configuration
+ /// @return configCount ordinal number of current config, out of all configs applied to this contract so far
+ /// @return blockNumber block at which this config was set
+ /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)
function latestConfigDetails()
external
view
@@ -92,40 +82,34 @@ abstract contract OCR2Abstract is ITypeAndVersion {
)
)
);
- return bytes32((prefix & prefixMask) | (h & ~prefixMask));
+ return bytes32((PREFIX & PREFIX_MASK) | (h & ~PREFIX_MASK));
}
- /**
- * @notice optionally emited to indicate the latest configDigest and epoch for
- which a report was successfully transmited. Alternatively, the contract may
- use latestConfigDigestAndEpoch with scanLogs set to false.
- */
+ /// @notice optionally emitted to indicate the latest configDigest and epoch for
+ /// which a report was successfully transmitted. Alternatively, the contract may
+ /// use latestConfigDigestAndEpoch with scanLogs set to false.
event Transmitted(bytes32 configDigest, uint32 epoch);
- /**
- * @notice optionally returns the latest configDigest and epoch for which a
- report was successfully transmitted. Alternatively, the contract may return
- scanLogs set to true and use Transmitted events to provide this information
- to offchain watchers.
- * @return scanLogs indicates whether to rely on the configDigest and epoch
- returned or whether to scan logs for the Transmitted event instead.
- * @return configDigest
- * @return epoch
- */
+ /// @notice optionally returns the latest configDigest and epoch for which a
+ /// report was successfully transmitted. Alternatively, the contract may return
+ /// scanLogs set to true and use Transmitted events to provide this information
+ /// to offchain watchers.
+ /// @return scanLogs indicates whether to rely on the configDigest and epoch
+ /// returned or whether to scan logs for the Transmitted event instead.
+ /// @return configDigest
+ /// @return epoch
function latestConfigDigestAndEpoch()
external
view
virtual
returns (bool scanLogs, bytes32 configDigest, uint32 epoch);
- /**
- * @notice transmit is called to post a new report to the contract
- * @param reportContext [0]: ConfigDigest, [1]: 27 byte padding, 4-byte epoch and 1-byte round, [2]: ExtraHash
- * @param report serialized report, which the signatures are signing.
- * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries
- * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries
- * @param rawVs ith element is the the V component of the ith signature
- */
+ /// @notice transmit is called to post a new report to the contract
+ /// @param reportContext [0]: ConfigDigest, [1]: 27 byte padding, 4-byte epoch and 1-byte round, [2]: ExtraHash
+ /// @param report serialized report, which the signatures are signing.
+ /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
+ /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
+ /// @param rawVs ith element is the the V component of the ith signature
function transmit(
// NOTE: If these parameters are changed, expectedMsgDataLength and/or
// TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
diff --git a/contracts/src/v0.8/shared/ocr2/OCR2Base.sol b/contracts/src/v0.8/shared/ocr2/OCR2Base.sol
index 0f0317602d..baedac7710 100644
--- a/contracts/src/v0.8/shared/ocr2/OCR2Base.sol
+++ b/contracts/src/v0.8/shared/ocr2/OCR2Base.sol
@@ -1,47 +1,45 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-import {ConfirmedOwner} from "../access/ConfirmedOwner.sol";
+import {OwnerIsCreator} from "../access/OwnerIsCreator.sol";
import {OCR2Abstract} from "./OCR2Abstract.sol";
-/**
- * @notice Onchain verification of reports from the offchain reporting protocol
- * @dev THIS CONTRACT HAS NOT GONE THROUGH ANY SECURITY REVIEW. DO NOT USE IN PROD.
- * @dev For details on its operation, see the offchain reporting protocol design
- * doc, which refers to this contract as simply the "contract".
- * @dev This contract is meant to aid rapid development of new applications based on OCR2.
- * However, for actual production contracts, it is expected that most of the logic of this contract
- * will be folded directly into the application contract. Inheritance prevents us from doing lots
- * of juicy storage layout optimizations, leading to a substantial increase in gas cost.
- */
+/// @notice Onchain verification of reports from the offchain reporting protocol
+/// @dev THIS CONTRACT HAS NOT GONE THROUGH ANY SECURITY REVIEW. DO NOT USE IN PROD.
+/// @dev For details on its operation, see the offchain reporting protocol design
+/// doc, which refers to this contract as simply the "contract".
+/// @dev This contract is meant to aid rapid development of new applications based on OCR2.
+/// However, for actual production contracts, it is expected that most of the logic of this contract
+/// will be folded directly into the application contract. Inheritance prevents us from doing lots
+/// of juicy storage layout optimizations, leading to a substantial increase in gas cost.
// solhint-disable custom-errors
-abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
+abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract {
error ReportInvalid();
bool internal immutable i_uniqueReports;
- constructor(bool uniqueReports) ConfirmedOwner(msg.sender) {
+ constructor(bool uniqueReports) OwnerIsCreator() {
i_uniqueReports = uniqueReports;
}
- // Storing these fields used on the hot path in a ConfigInfo variable reduces the
- // retrieval of all of them to a single SLOAD. If any further fields are
- // added, make sure that storage of the struct still takes at most 32 bytes.
+ /// @dev Storing these fields used on the hot path in a ConfigInfo variable reduces
+ /// the retrieval of all of them to a single SLOAD. If any further fields are
+ /// added, make sure that storage of the struct still takes at most 32 bytes.
struct ConfigInfo {
bytes32 latestConfigDigest;
- uint8 f; // TODO: could be optimized by squeezing into one slot
- uint8 n;
+ uint8 f; // ───╮
+ uint8 n; // ───╯
}
ConfigInfo internal s_configInfo;
- // incremented each time a new config is posted. This count is incorporated
- // into the config digest, to prevent replay attacks.
+ /// @dev Incremented each time a new config is posted. This count is incorporated
+ /// into the config digest, to prevent replay attacks.
uint32 internal s_configCount;
- uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems
- // to extract config from logs.
+ /// @dev Makes it easier for offchain systems to extract config from logs.
+ uint32 internal s_latestConfigBlockNumber;
- // Used for s_oracles[a].role, where a is an address, to track the purpose
- // of the address, or to indicate that the address is unset.
+ /// @dev Used for s_oracles[a].role, where a is an address, to track the purpose
+ /// of the address, or to indicate that the address is unset.
enum Role {
// No oracle role has been set for address a
Unset,
@@ -55,30 +53,26 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
}
struct Oracle {
- uint8 index; // Index of oracle in s_signers/s_transmitters
- Role role; // Role of the address which mapped to this struct
+ uint8 index; // ───╮ Index of oracle in s_signers/s_transmitters
+ Role role; // ─────╯ Role of the address which mapped to this struct
}
mapping(address => Oracle) /* signer OR transmitter address */ internal s_oracles;
- // s_signers contains the signing address of each oracle
+ /// @notice Contains the signing address of each oracle
address[] internal s_signers;
- // s_transmitters contains the transmission address of each oracle,
- // i.e. the address the oracle actually sends transactions to the contract from
+ /// @notice Contains the transmission address of each oracle,
+ /// i.e. the address the oracle actually sends transactions to the contract from
address[] internal s_transmitters;
- /*
- * Config logic
- */
-
- // Reverts transaction if config args are invalid
+ /// @dev Reverts transaction if config args are invalid
modifier checkConfigValid(
uint256 _numSigners,
uint256 _numTransmitters,
uint256 _f
) {
- require(_numSigners <= maxNumOracles, "too many signers");
+ require(_numSigners <= MAX_NUM_ORACLES, "too many signers");
require(_f > 0, "f must be positive");
require(_numSigners == _numTransmitters, "oracle addresses out of registration");
require(_numSigners > 3 * _f, "faulty-oracle f too high");
@@ -105,15 +99,13 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
return (true, bytes32(0), uint32(0));
}
- /**
- * @notice sets offchain reporting protocol configuration incl. participating oracles
- * @param _signers addresses with which oracles sign the reports
- * @param _transmitters addresses oracles use to transmit the reports
- * @param _f number of faulty oracles the system can tolerate
- * @param _onchainConfig encoded on-chain contract configuration
- * @param _offchainConfigVersion version number for offchainEncoding schema
- * @param _offchainConfig encoded off-chain oracle configuration
- */
+ /// @notice sets offchain reporting protocol configuration incl. participating oracles
+ /// @param _signers addresses with which oracles sign the reports
+ /// @param _transmitters addresses oracles use to transmit the reports
+ /// @param _f number of faulty oracles the system can tolerate
+ /// @param _onchainConfig encoded on-chain contract configuration
+ /// @param _offchainConfigVersion version number for offchainEncoding schema
+ /// @param _offchainConfig encoded off-chain oracle configuration
function setConfig(
address[] memory _signers,
address[] memory _transmitters,
@@ -187,12 +179,10 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
_afterSetConfig(args.f, args.onchainConfig);
}
- /**
- * @notice information about current offchain reporting protocol configuration
- * @return configCount ordinal number of current config, out of all configs applied to this contract so far
- * @return blockNumber block at which this config was set
- * @return configDigest domain-separation tag for current config (see configDigestFromConfigData)
- */
+ /// @notice information about current offchain reporting protocol configuration
+ /// @return configCount ordinal number of current config, out of all configs applied to this contract so far
+ /// @return blockNumber block at which this config was set
+ /// @return configDigest domain-separation tag for current config (see configDigestFromConfigData)
function latestConfigDetails()
external
view
@@ -202,10 +192,8 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest);
}
- /**
- * @return list of addresses permitted to transmit reports to this contract
- * @dev The list will match the order used to specify the transmitter during setConfig
- */
+ /// @return list of addresses permitted to transmit reports to this contract
+ /// @dev The list will match the order used to specify the transmitter during setConfig
function transmitters() external view returns (address[] memory) {
return s_transmitters;
}
@@ -214,31 +202,27 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
function _afterSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual;
- /**
- * @dev hook to allow additional validation of the report by the extending contract
- * @param configDigest separation tag for current config (see configDigestFromConfigData)
- * @param epochAndRound 27 byte padding, 4-byte epoch and 1-byte round
- * @param report serialized report
- */
+ /// @dev hook to allow additional validation of the report by the extending contract
+ /// @param configDigest separation tag for current config (see configDigestFromConfigData)
+ /// @param epochAndRound 27 byte padding, 4-byte epoch and 1-byte round
+ /// @param report serialized report
function _validateReport(
bytes32 configDigest,
uint40 epochAndRound,
bytes memory report
) internal virtual returns (bool);
- /**
- * @dev hook called after the report has been fully validated
- * for the extending contract to handle additional logic, such as oracle payment
- * @param initialGas the amount of gas before validation
- * @param transmitter the address of the account that submitted the report
- * @param signers the addresses of all signing accounts
- * @param report serialized report
- */
+ /// @dev hook called after the report has been fully validated
+ /// for the extending contract to handle additional logic, such as oracle payment
+ /// @param initialGas the amount of gas before validation
+ /// @param transmitter the address of the account that submitted the report
+ /// @param signers the addresses of all signing accounts
+ /// @param report serialized report
function _report(
uint256 initialGas,
address transmitter,
uint8 signerCount,
- address[maxNumOracles] memory signers,
+ address[MAX_NUM_ORACLES] memory signers,
bytes calldata report
) internal virtual;
@@ -274,13 +258,11 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
require(msg.data.length == expected, "calldata length mismatch");
}
- /**
- * @notice transmit is called to post a new report to the contract
- * @param report serialized report, which the signatures are signing.
- * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries
- * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries
- * @param rawVs ith element is the the V component of the ith signature
- */
+ /// @notice transmit is called to post a new report to the contract
+ /// @param report serialized report, which the signatures are signing.
+ /// @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries
+ /// @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries
+ /// @param rawVs ith element is the the V component of the ith signature
function transmit(
// NOTE: If these parameters are changed, expectedMsgDataLength and/or
// TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
@@ -328,7 +310,7 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract {
);
}
- address[maxNumOracles] memory signed;
+ address[MAX_NUM_ORACLES] memory signed;
uint8 signerCount = 0;
{
From 0c8c1cd000131018dff070279b4e1a18b3562d53 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Tue, 21 Nov 2023 06:05:58 -0600
Subject: [PATCH 182/327] switch from ocr2vrf to chainlink-vrf (#11346)
---
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 ++--
core/scripts/ocr2vrf/main.go | 3 ++-
core/scripts/ocr2vrf/util.go | 9 +++++----
core/scripts/ocr2vrf/verify.go | 5 +++--
core/services/keystore/keys/dkgencryptkey/key.go | 3 ++-
core/services/ocr2/delegate.go | 15 +++++++--------
core/services/ocr2/plugins/dkg/key_consumer.go | 2 +-
.../services/ocr2/plugins/dkg/onchain_contract.go | 6 +++---
core/services/ocr2/plugins/dkg/persistence/db.go | 6 ++++--
.../ocr2/plugins/dkg/persistence/db_test.go | 4 ++--
core/services/ocr2/plugins/dkg/plugin.go | 6 ++++--
.../plugins/ocr2vrf/coordinator/coordinator.go | 10 ++++++----
.../ocr2vrf/coordinator/coordinator_test.go | 7 ++++---
.../ocr2vrf/internal/ocr2vrf_integration_test.go | 9 +++++----
.../juelsfeecoin/link_eth_price_provider.go | 3 ++-
.../reasonable_gas_price_provider.go | 2 +-
.../ocr2vrf/reportserializer/report_serializer.go | 4 ++--
.../reportserializer/report_serializer_test.go | 4 ++--
go.mod | 2 +-
go.sum | 4 ++--
.../ocr2vrf_actions/ocr2vrf_config_helpers.go | 9 +++++----
.../ocr2vrf_constants/ocr2vrf_constants.go | 2 +-
.../actions/ocr2vrf_actions/ocr2vrf_models.go | 2 +-
.../actions/ocr2vrf_actions/ocr2vrf_steps.go | 2 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
27 files changed, 72 insertions(+), 59 deletions(-)
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 1d8ba40b82..09c76dd195 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -21,10 +21,10 @@ require (
github.com/pelletier/go-toml/v2 v2.1.0
github.com/pkg/errors v0.9.1
github.com/shopspring/decimal v1.3.1
+ github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
- github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.4
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 13496adb7a..b1a0870114 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1470,6 +1470,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1/go.mod h1:UfW7/PZKon+iDEHtrHOfvMnS5GfYOW/SdMZ6P97rPEk=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 h1:yxaHuDTtj2xxtsR8b+LJw8xDvyr6v/F6GP3InsP4wPI=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
+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=
@@ -1478,8 +1480,6 @@ github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XO
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
-github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
-github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/core/scripts/ocr2vrf/main.go b/core/scripts/ocr2vrf/main.go
index c698fcd730..532fbd3f22 100644
--- a/core/scripts/ocr2vrf/main.go
+++ b/core/scripts/ocr2vrf/main.go
@@ -12,7 +12,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/shopspring/decimal"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
diff --git a/core/scripts/ocr2vrf/util.go b/core/scripts/ocr2vrf/util.go
index a2ff55524d..4ec78472e5 100644
--- a/core/scripts/ocr2vrf/util.go
+++ b/core/scripts/ocr2vrf/util.go
@@ -21,10 +21,11 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- "github.com/smartcontractkit/ocr2vrf/dkg"
- "github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
+ "github.com/smartcontractkit/chainlink-vrf/ocr2vrf"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder"
diff --git a/core/scripts/ocr2vrf/verify.go b/core/scripts/ocr2vrf/verify.go
index 4b91148a8c..7d7fb94496 100644
--- a/core/scripts/ocr2vrf/verify.go
+++ b/core/scripts/ocr2vrf/verify.go
@@ -9,12 +9,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/google"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/group/mod"
"go.dedis.ch/kyber/v3/pairing"
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
+
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"
diff --git a/core/services/keystore/keys/dkgencryptkey/key.go b/core/services/keystore/keys/dkgencryptkey/key.go
index 461dc4e2ad..e94f2a6bdf 100644
--- a/core/services/keystore/keys/dkgencryptkey/key.go
+++ b/core/services/keystore/keys/dkgencryptkey/key.go
@@ -6,9 +6,10 @@ import (
"math/big"
"github.com/pkg/errors"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/pairing"
+
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
)
var suite pairing.Suite = &altbn_128.PairingSuite{}
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 4b5932cd70..2f2a903339 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -8,13 +8,11 @@ import (
"log"
"time"
- "google.golang.org/grpc"
- "gopkg.in/guregu/null.v4"
-
"github.com/ethereum/go-ethereum/common"
- "github.com/pkg/errors"
-
"github.com/jmoiron/sqlx"
+ "github.com/pkg/errors"
+ "google.golang.org/grpc"
+ "gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
@@ -26,9 +24,10 @@ import (
ocr2keepers20runner "github.com/smartcontractkit/ocr2keepers/pkg/v2/runner"
ocr2keepers21config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
ocr2keepers21 "github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- dkgpkg "github.com/smartcontractkit/ocr2vrf/dkg"
- "github.com/smartcontractkit/ocr2vrf/ocr2vrf"
+
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg"
+ "github.com/smartcontractkit/chainlink-vrf/ocr2vrf"
commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/loop"
diff --git a/core/services/ocr2/plugins/dkg/key_consumer.go b/core/services/ocr2/plugins/dkg/key_consumer.go
index 99115af70d..23ca7e795b 100644
--- a/core/services/ocr2/plugins/dkg/key_consumer.go
+++ b/core/services/ocr2/plugins/dkg/key_consumer.go
@@ -4,7 +4,7 @@ import (
"encoding/hex"
"fmt"
- "github.com/smartcontractkit/ocr2vrf/dkg"
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
)
type dummyKeyConsumer struct{}
diff --git a/core/services/ocr2/plugins/dkg/onchain_contract.go b/core/services/ocr2/plugins/dkg/onchain_contract.go
index 5f23f33c5d..c6ea84de23 100644
--- a/core/services/ocr2/plugins/dkg/onchain_contract.go
+++ b/core/services/ocr2/plugins/dkg/onchain_contract.go
@@ -8,9 +8,9 @@ import (
"github.com/pkg/errors"
"go.dedis.ch/kyber/v3/sign/anon"
- "github.com/smartcontractkit/ocr2vrf/dkg"
- dkgwrapper "github.com/smartcontractkit/ocr2vrf/gethwrappers/dkg"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
+ dkgwrapper "github.com/smartcontractkit/chainlink-vrf/gethwrappers/dkg"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
)
diff --git a/core/services/ocr2/plugins/dkg/persistence/db.go b/core/services/ocr2/plugins/dkg/persistence/db.go
index c020a68cbe..304422ace2 100644
--- a/core/services/ocr2/plugins/dkg/persistence/db.go
+++ b/core/services/ocr2/plugins/dkg/persistence/db.go
@@ -13,9 +13,11 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
- "github.com/smartcontractkit/ocr2vrf/types/hash"
+
+ 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"
diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go
index d4a4546fb9..b4fa000cb9 100644
--- a/core/services/ocr2/plugins/dkg/persistence/db_test.go
+++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go
@@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
- "github.com/smartcontractkit/ocr2vrf/types/hash"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
+ "github.com/smartcontractkit/chainlink-vrf/types/hash"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
diff --git a/core/services/ocr2/plugins/dkg/plugin.go b/core/services/ocr2/plugins/dkg/plugin.go
index 92910ff7bb..0310122655 100644
--- a/core/services/ocr2/plugins/dkg/plugin.go
+++ b/core/services/ocr2/plugins/dkg/plugin.go
@@ -8,10 +8,12 @@ import (
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
+
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- "github.com/smartcontractkit/ocr2vrf/dkg"
+
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go
index 1b58a01732..6353894153 100644
--- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go
+++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go
@@ -17,13 +17,15 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "github.com/smartcontractkit/libocr/commontypes"
- ocr2Types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2vrf/dkg"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
"golang.org/x/exp/maps"
"google.golang.org/protobuf/proto"
+ "github.com/smartcontractkit/libocr/commontypes"
+ ocr2Types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
+
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"
diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
index f634ee0c01..418e4356c6 100644
--- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go
@@ -21,9 +21,10 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
ocr2Types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2vrf/dkg"
- "github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
+ "github.com/smartcontractkit/chainlink-vrf/ocr2vrf"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink-common/pkg/types"
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 38d7acf7e9..e93824283b 100644
--- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go
@@ -25,10 +25,11 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- ocr2dkg "github.com/smartcontractkit/ocr2vrf/dkg"
- "github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ ocr2dkg "github.com/smartcontractkit/chainlink-vrf/dkg"
+ "github.com/smartcontractkit/chainlink-vrf/ocr2vrf"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
diff --git a/core/services/ocr2/plugins/ocr2vrf/juelsfeecoin/link_eth_price_provider.go b/core/services/ocr2/plugins/ocr2vrf/juelsfeecoin/link_eth_price_provider.go
index d2330d87e4..2601ae1466 100644
--- a/core/services/ocr2/plugins/ocr2vrf/juelsfeecoin/link_eth_price_provider.go
+++ b/core/services/ocr2/plugins/ocr2vrf/juelsfeecoin/link_eth_price_provider.go
@@ -10,7 +10,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
- "github.com/smartcontractkit/ocr2vrf/types"
+
+ "github.com/smartcontractkit/chainlink-vrf/types"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface"
diff --git a/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go b/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go
index c0e969a287..880b808433 100644
--- a/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go
+++ b/core/services/ocr2/plugins/ocr2vrf/reasonablegasprice/reasonable_gas_price_provider.go
@@ -4,7 +4,7 @@ import (
"math/big"
"time"
- "github.com/smartcontractkit/ocr2vrf/types"
+ "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
diff --git a/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go b/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go
index 19b625ff6d..e4112b5543 100644
--- a/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go
+++ b/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go
@@ -4,8 +4,8 @@ import (
"github.com/pkg/errors"
"go.dedis.ch/kyber/v3"
- "github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- types "github.com/smartcontractkit/ocr2vrf/types"
+ "github.com/smartcontractkit/chainlink-vrf/ocr2vrf"
+ "github.com/smartcontractkit/chainlink-vrf/types"
)
type reportSerializer struct {
diff --git a/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer_test.go b/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer_test.go
index dcfd627ac9..32704a55b0 100644
--- a/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer_test.go
+++ b/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer_test.go
@@ -7,8 +7,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- "github.com/smartcontractkit/ocr2vrf/types"
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/reportserializer"
)
diff --git a/go.mod b/go.mod
index 784d3ff78e..c13f476bf2 100644
--- a/go.mod
+++ b/go.mod
@@ -69,9 +69,9 @@ require (
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664
+ github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
- github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wsrpc v0.7.2
diff --git a/go.sum b/go.sum
index fb09e792d6..4f465dc8f9 100644
--- a/go.sum
+++ b/go.sum
@@ -1471,6 +1471,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1/go.mod h1:UfW7/PZKon+iDEHtrHOfvMnS5GfYOW/SdMZ6P97rPEk=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 h1:yxaHuDTtj2xxtsR8b+LJw8xDvyr6v/F6GP3InsP4wPI=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
+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=
@@ -1479,8 +1481,6 @@ github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XO
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
-github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
-github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go
index e424aaa11b..58e394cb79 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_config_helpers.go
@@ -18,10 +18,11 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2vrf/altbn_128"
- "github.com/smartcontractkit/ocr2vrf/dkg"
- "github.com/smartcontractkit/ocr2vrf/ocr2vrf"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+
+ "github.com/smartcontractkit/chainlink-vrf/altbn_128"
+ "github.com/smartcontractkit/chainlink-vrf/dkg"
+ "github.com/smartcontractkit/chainlink-vrf/ocr2vrf"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants/ocr2vrf_constants.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants/ocr2vrf_constants.go
index 7caceec941..7f17be3fd8 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants/ocr2vrf_constants.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants/ocr2vrf_constants.go
@@ -4,7 +4,7 @@ import (
"math/big"
"time"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
)
var (
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_models.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_models.go
index 8f218ab5c7..0858020338 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_models.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_models.go
@@ -1,6 +1,6 @@
package ocr2vrf_actions
-import ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+import ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
type DKGKeyConfig struct {
DKGEncryptionPublicKey string
diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
index 2904162f49..c3add16ec6 100644
--- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
+++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
- ocr2vrftypes "github.com/smartcontractkit/ocr2vrf/types"
+ ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 3b1a5423df..9e99f39b44 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -24,10 +24,10 @@ require (
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
github.com/smartcontractkit/chainlink-testing-framework v1.19.1
+ github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
github.com/smartcontractkit/ocr2keepers v0.7.28
- github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wasp v0.3.0
github.com/spf13/cobra v1.6.1
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 427ad1421c..87cceb9b99 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2377,6 +2377,8 @@ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.202311
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
github.com/smartcontractkit/chainlink-testing-framework v1.19.1 h1:MdGM5jIrBi858Cv7qzfl1Qon93YW8InohAlDQqFoIb4=
github.com/smartcontractkit/chainlink-testing-framework v1.19.1/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+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=
@@ -2385,8 +2387,6 @@ github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XO
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
-github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM=
-github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687/go.mod h1:YYZq52t4wcHoMQeITksYsorD+tZcOyuVU5+lvot3VFM=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
From 98ac92b9e57c8ba386999fe739ca09f0b4886ffb Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Tue, 21 Nov 2023 08:08:17 -0600
Subject: [PATCH 183/327] core/services/job: close test peer wrappers (#11349)
---
core/services/job/orm_test.go | 2 +-
core/services/job/runner_integration_test.go | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go
index 41d02dba06..2e19669417 100644
--- a/core/services/job/orm_test.go
+++ b/core/services/job/orm_test.go
@@ -23,7 +23,7 @@ import (
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)
- t.Cleanup(func() { o.Close() })
+ 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 deb4bff6b0..eb6af3607f 100644
--- a/core/services/job/runner_integration_test.go
+++ b/core/services/job/runner_integration_test.go
@@ -450,6 +450,7 @@ answer1 [type=median index=0];
assert.NoError(t, err)
pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr)
require.NoError(t, pw.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, pw.Close()) })
sd := ocr.NewDelegate(
db,
jobORM,
@@ -484,6 +485,7 @@ answer1 [type=median index=0];
lggr := logger.TestLogger(t)
pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr)
require.NoError(t, pw.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, pw.Close()) })
sd := ocr.NewDelegate(
db,
jobORM,
@@ -512,6 +514,7 @@ answer1 [type=median index=0];
lggr := logger.TestLogger(t)
pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr)
require.NoError(t, pw.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, pw.Close()) })
sd := ocr.NewDelegate(
db,
jobORM,
@@ -566,6 +569,7 @@ answer1 [type=median index=0];
lggr := logger.TestLogger(t)
pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr)
require.NoError(t, pw.Start(testutils.Context(t)))
+ t.Cleanup(func() { assert.NoError(t, pw.Close()) })
sd := ocr.NewDelegate(
db,
jobORM,
@@ -610,7 +614,7 @@ answer1 [type=median index=0];
lggr := logger.TestLogger(t)
pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr)
require.NoError(t, pw.Start(testutils.Context(t)))
-
+ t.Cleanup(func() { assert.NoError(t, pw.Close()) })
sd := ocr.NewDelegate(
db,
jobORM,
From 530225a1918556cbee65bbe2e5aff6bfaeb05abd Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Tue, 21 Nov 2023 10:06:19 -0500
Subject: [PATCH 184/327] [TT-524] [TT-729] More Products and Reporting for
Live Tests (#11327)
* More Specific Tests
* Disable sepolia
* Specify automation test
* Don't give up
* Reduce default funding
* Fix test name
* Messing with jq
* Change all OCR config
* Fiddling with jq more
* Little better reports
* I think I got the formatting now
* Ensure prerequisites
* Debugging
* Remove Sepolia
* Formatting
* Remove if (we'll make it pretty later)
* Strip out quotes
* Fix GHA label
* Remove debug
* More accurate colors
* Ease the debugging process
* More debugging
* Fix needs check
* Check fail
* Check fail better
* Learned some tricks
* Successes
* Extra paren
* Fix emojis
* Purty
* Remove debug and mocks
* Cleanup
---
.github/workflows/live-testnet-tests.yml | 205 ++++++++++++++---------
integration-tests/soak/ocr_test.go | 11 +-
2 files changed, 128 insertions(+), 88 deletions(-)
diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml
index 7eb1669b35..f174e8847b 100644
--- a/.github/workflows/live-testnet-tests.yml
+++ b/.github/workflows/live-testnet-tests.yml
@@ -11,12 +11,16 @@ env:
CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink
INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com
MOD_CACHE_VERSION: 2
+ CHAINLINK_NODE_FUNDING: .1
CHAINLINK_COMMIT_SHA: ${{ github.sha }}
CHAINLINK_ENV_USER: ${{ github.actor }}
TEST_LOG_LEVEL: debug
EVM_KEYS: ${{ secrets.QA_EVM_KEYS }}
+ SEPOLIA_URLS: ${{ secrets.QA_SEPOLIA_URLS }}
+ SEPOLIA_HTTP_URLS: ${{ secrets.QA_SEPOLIA_HTTP_URLS }}
+
OPTIMISM_GOERLI_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_URLS }}
OPTIMISM_GOERLI_HTTP_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_HTTP_URLS }}
@@ -55,61 +59,66 @@ jobs:
AWS_REGION: ${{ secrets.QA_AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
-
- sepolia-smoke-tests:
- environment: integration
- permissions:
- checks: write
- pull-requests: write
- id-token: write
- contents: read
- needs: [build-chainlink]
- env:
- SELECTED_NETWORKS: SEPOLIA
- strategy:
- fail-fast: false
- matrix:
- product: [ocr, automation]
- name: Sepolia ${{ matrix.product }} Tests
- runs-on: ubuntu-latest
- steps:
- - name: Checkout the repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- with:
- ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
- - name: Run Tests
- uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
- env:
- PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
- PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia
- PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
- with:
- test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/${{ matrix.product }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
- test_download_vendor_packages_command: cd ./integration-tests && go mod download
- cl_repo: ${{ env.CHAINLINK_IMAGE }}
- cl_image_tag: ${{ github.sha }}
- aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
- dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
- dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
- artifacts_location: ./integration-tests/smoke/logs
- publish_check_name: Seplia ${{ matrix.product }} Smoke Test Results
- token: ${{ secrets.GITHUB_TOKEN }}
- go_mod_path: ./integration-tests/go.mod
- cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
- cache_restore_only: "true"
- QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
- QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
- QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
- - name: Collect Metrics
- if: always()
- id: collect-gha-metrics
- uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
- with:
- basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
- hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
- this-job-name: Sepolia ${{ matrix.product }} Tests
- test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
- continue-on-error: true
+ # TODO: Re-enable when we have secrets properly configured
+ # sepolia-smoke-tests:
+ # environment: integration
+ # permissions:
+ # checks: write
+ # pull-requests: write
+ # id-token: write
+ # contents: read
+ # needs: [build-chainlink]
+ # env:
+ # SELECTED_NETWORKS: SEPOLIA
+ # strategy:
+ # max-parallel: 1
+ # fail-fast: false
+ # matrix:
+ # include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations
+ # - product: OCR
+ # test: TestOCRBasic
+ # - product: Automation
+ # test: TestAutomationBasic/registry_2_0
+ # name: Sepolia ${{ matrix.product }} Tests
+ # runs-on: ubuntu-latest
+ # steps:
+ # - name: Checkout the repo
+ # uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ # with:
+ # ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }}
+ # - name: Run Tests
+ # uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16
+ # env:
+ # PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }}
+ # PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia
+ # PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
+ # with:
+ # test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 -run ${{ matrix.test }} ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt
+ # test_download_vendor_packages_command: cd ./integration-tests && go mod download
+ # cl_repo: ${{ env.CHAINLINK_IMAGE }}
+ # cl_image_tag: ${{ github.sha }}
+ # aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}
+ # dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
+ # dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
+ # artifacts_location: ./integration-tests/smoke/logs
+ # publish_check_name: Seplia ${{ matrix.product }} Smoke Test Results
+ # token: ${{ secrets.GITHUB_TOKEN }}
+ # go_mod_path: ./integration-tests/go.mod
+ # cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }}
+ # cache_restore_only: "true"
+ # QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }}
+ # QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }}
+ # QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }}
+ # - name: Collect Metrics
+ # if: always()
+ # id: collect-gha-metrics
+ # uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2
+ # with:
+ # basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }}
+ # hostname: ${{ secrets.GRAFANA_CLOUD_HOST }}
+ # this-job-name: Sepolia ${{ matrix.product }} Tests
+ # test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}'
+ # continue-on-error: true
optimism-goerli-smoke-tests:
environment: integration
@@ -123,8 +132,13 @@ jobs:
SELECTED_NETWORKS: OPTIMISM_GOERLI
strategy:
fail-fast: false
+ max-parallel: 1
matrix:
- product: [ocr, automation]
+ include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations
+ - product: OCR
+ test: TestOCRBasic
+ - product: Automation
+ test: TestAutomationBasic/registry_2_0
name: Optimism Goerli ${{ matrix.product }} Tests
runs-on: ubuntu-latest
steps:
@@ -139,7 +153,7 @@ jobs:
PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-optimism-goerli
PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
with:
- test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/${{ matrix.product }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 -run ${{ matrix.test }} ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
@@ -177,9 +191,14 @@ jobs:
env:
SELECTED_NETWORKS: ARBITRUM_GOERLI
strategy:
+ max-parallel: 1
fail-fast: false
matrix:
- product: [ocr, automation]
+ include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations
+ - product: OCR
+ test: TestOCRBasic
+ - product: Automation
+ test: TestAutomationBasic/registry_2_0
name: Arbitrum Goerli ${{ matrix.product }} Tests
runs-on: ubuntu-latest
steps:
@@ -194,7 +213,7 @@ jobs:
PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-arbitrum-goerli
PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }}
with:
- test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 ./smoke/${{ matrix.product }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt
+ test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=1 -run ${{ matrix.test }} ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt
test_download_vendor_packages_command: cd ./integration-tests && go mod download
cl_repo: ${{ env.CHAINLINK_IMAGE }}
cl_image_tag: ${{ github.sha }}
@@ -233,10 +252,10 @@ jobs:
id-token: write
contents: read
runs-on: ubuntu-latest
- needs: [sepolia-smoke-tests, optimism-goerli-smoke-tests, arbitrum-goerli-smoke-tests]
+ needs: [optimism-goerli-smoke-tests, arbitrum-goerli-smoke-tests]
steps:
- name: Debug Result
- run: echo ${{needs.*.result}}
+ run: echo ${{ join(needs.*.result, ',') }}
- name: Main Slack Notification
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
id: slack
@@ -246,13 +265,13 @@ jobs:
{
"attachments": [
{
- "color": "${{ needs.*.result == 'success' && '#2E7D32' || '#C62828' }}",
+ "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
- "text": "Live Smoke Test Results ${{ needs.*.result == 'success' && ':white_check_mark:' || ':x:'}}",
+ "text": "Live Smoke Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}",
"emoji": true
}
},
@@ -274,7 +293,7 @@ jobs:
SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
testnet-smoke-tests-results:
- name: Post Test Results
+ name: Post Test Results for ${{ matrix.network }}
if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }}
environment: integration
permissions:
@@ -287,23 +306,53 @@ jobs:
strategy:
fail-fast: false
matrix:
- testnet: [sepolia, optimism-goerli, arbitrum-goerli]
+ network: [Optimism Goerli, Arbitrum Goerli]
steps:
- name: Get Results
id: test-results
run: |
+ # I feel like there's some clever, fully jq way to do this, but I ain't got the motivation to figure it out
echo "Querying test results"
- echo "status=$(curl \
+ PARSED_RESULTS=$(curl \
-H "Authorization: Bearer ${{ github.token }}" \
'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \
- | jq -r '.jobs[] | select(.name == "Live Testnet Smoke Tests ${{ matrix.testnet }}-smoke-tests").steps[] | select(.name == "Run Tests").conclusion')" >> $GITHUB_OUTPUT
+ | jq -r --arg pattern "${{ matrix.network }} (?\\w+) Tests" '.jobs[]
+ | select(.name | test($pattern)) as $job
+ | $job.steps[]
+ | select(.name == "Run Tests")
+ | { conclusion: (if .conclusion == "success" then ":white_check_mark:" else ":x:" end), product: ("*" + ($job.name | capture($pattern).product) + "*") }')
- echo "status=$(curl \
- -H "Authorization: Bearer ${{ github.token }}" \
- 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \
- | jq -r '.jobs[] | select(.name == "Live Testnet Smoke Tests ${{ matrix.testnet }}-smoke-tests"").steps[] | select(.name == "Run Tests").conclusion')"
- echo "thread_ts=${{ needs.testnet-smoke-tests-notify.outputs.thread_ts }}"
+ echo "Parsed Results:"
+ echo $PARSED_RESULTS
+
+ ALL_SUCCESS=true
+ for row in $(echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")'); do
+ success=false
+ break
+ done
+
+ echo all_success=$ALL_SUCCESS >> $GITHUB_OUTPUT
+
+ FORMATTED_RESULTS=$(echo $PARSED_RESULTS | jq -s '[.[]
+ | {
+ conclusion: .conclusion,
+ product: .product
+ }
+ ]
+ | map("{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"\(.product): \(.conclusion)\"}}")
+ | join(",")')
+
+ echo "Formatted Results:"
+ echo $FORMATTED_RESULTS
+
+ # Cleans out backslashes and quotes from jq
+ CLEAN_RESULTS=$(echo "$FORMATTED_RESULTS" | sed 's/\\\"/"/g' | sed 's/^"//;s/"$//')
+
+ echo "Clean Results"
+ echo $CLEAN_RESULTS
+
+ echo results=$CLEAN_RESULTS >> $GITHUB_OUTPUT
- name: Test Details
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
@@ -314,26 +363,20 @@ jobs:
"thread_ts": "${{ needs.testnet-smoke-tests-notify.outputs.thread_ts }}",
"attachments": [
{
- "color": "${{ steps.test-results.outputs.status == 'success' && '#2E7D32' || '#C62828' }}",
+ "color": "${{ steps.test-results.outputs.all_success && '#2E7D32' || '#C62828' }}",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
- "text": "${{ matrix.testnet }} Smoke Test Results ${{ steps.test-results.outputs.status == 'success' && ':white_check_mark:' || ':x:'}}",
+ "text": "${{ matrix.network }} ${{ steps.test-results.outputs.all_success && ':white_check_mark:' || ':x: Notifying <@U01Q4N37KFG>'}}",
"emoji": true
}
},
{
"type": "divider"
},
- {
- "type": "section",
- "text": {
- "type": "mrkdwn",
- "text": "OCR ${{ steps.test-results.outputs.status == 'success' && ':white_check_mark:' || ':x:'}}"
- }
- }
+ ${{ steps.test-results.outputs.results }}
]
}
]
diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go
index 4f42ff803e..4d7971d678 100644
--- a/integration-tests/soak/ocr_test.go
+++ b/integration-tests/soak/ocr_test.go
@@ -1,16 +1,13 @@
package soak
import (
- "fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
- "github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
- "github.com/smartcontractkit/chainlink/integration-tests/config"
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
)
@@ -19,10 +16,10 @@ func TestOCRSoak(t *testing.T) {
// Use this variable to pass in any custom EVM specific TOML values to your Chainlink nodes
customNetworkTOML := ``
// Uncomment below for debugging TOML issues on the node
- network := networks.MustGetSelectedNetworksFromEnv()[0]
- fmt.Println("Using Chainlink TOML\n---------------------")
- fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customNetworkTOML, network))
- fmt.Println("---------------------")
+ // network := networks.MustGetSelectedNetworksFromEnv()[0]
+ // fmt.Println("Using Chainlink TOML\n---------------------")
+ // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customNetworkTOML, network))
+ // fmt.Println("---------------------")
ocrSoakTest, err := testsetups.NewOCRSoakTest(t, false)
require.NoError(t, err, "Error creating soak test")
From f34b581ae7bee8529635e9526eecd4bdc30b26e5 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Tue, 21 Nov 2023 10:13:03 -0600
Subject: [PATCH 185/327] switch from ocr2keepers to chainlink-automation
(#11333)
---
contracts/src/v0.8/automation/v2_1/LICENSE | 2 +-
core/scripts/chaincli/handler/debug.go | 3 ++-
.../chaincli/handler/keeper_deployer.go | 7 ++++---
core/scripts/chaincli/handler/ocr2_config.go | 4 +++-
core/scripts/chaincli/handler/report.go | 4 +++-
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 ++--
core/services/ocr2/delegate.go | 16 +++++++--------
.../plugins/ocr2keeper/custom_telemetry.go | 2 +-
.../ocr2/plugins/ocr2keeper/evm20/abi.go | 3 ++-
.../ocr2/plugins/ocr2keeper/evm20/abi_test.go | 3 ++-
.../ocr2/plugins/ocr2keeper/evm20/encoder.go | 5 +++--
.../plugins/ocr2keeper/evm20/encoder_test.go | 3 ++-
.../ocr2/plugins/ocr2keeper/evm20/head.go | 2 +-
.../plugins/ocr2keeper/evm20/log_provider.go | 6 +++---
.../ocr2/plugins/ocr2keeper/evm20/registry.go | 2 +-
.../plugins/ocr2keeper/evm20/registry_test.go | 2 +-
.../plugins/ocr2keeper/evm21/active_list.go | 2 +-
.../ocr2keeper/evm21/active_list_test.go | 3 ++-
.../evm21/autotelemetry21/custom_telemetry.go | 2 +-
.../ocr2keeper/evm21/block_subscriber.go | 2 +-
.../ocr2keeper/evm21/block_subscriber_test.go | 2 +-
.../ocr2keeper/evm21/core/interfaces.go | 2 +-
.../evm21/core/mocks/upkeep_state_reader.go | 2 +-
.../plugins/ocr2keeper/evm21/core/payload.go | 3 ++-
.../ocr2keeper/evm21/core/payload_test.go | 4 ++--
.../plugins/ocr2keeper/evm21/core/testutil.go | 3 ++-
.../plugins/ocr2keeper/evm21/core/trigger.go | 2 +-
.../ocr2keeper/evm21/core/trigger_test.go | 3 ++-
.../plugins/ocr2keeper/evm21/core/type.go | 2 +-
.../ocr2keeper/evm21/core/type_test.go | 4 ++--
.../ocr2keeper/evm21/encoding/encoder.go | 2 +-
.../ocr2keeper/evm21/encoding/encoder_test.go | 3 ++-
.../ocr2keeper/evm21/encoding/interface.go | 2 +-
.../ocr2keeper/evm21/encoding/packer.go | 2 +-
.../ocr2keeper/evm21/encoding/packer_test.go | 3 ++-
.../ocr2/plugins/ocr2keeper/evm21/keyring.go | 3 ++-
.../plugins/ocr2keeper/evm21/keyring_test.go | 6 ++++--
.../ocr2keeper/evm21/logprovider/buffer.go | 4 ++--
.../evm21/logprovider/buffer_test.go | 3 ++-
.../evm21/logprovider/integration_test.go | 5 ++---
.../ocr2keeper/evm21/logprovider/provider.go | 2 +-
.../logprovider/provider_life_cycle_test.go | 2 +-
.../evm21/logprovider/provider_test.go | 5 ++---
.../ocr2keeper/evm21/logprovider/recoverer.go | 4 ++--
.../evm21/logprovider/recoverer_test.go | 2 +-
.../evm21/mercury/streams/streams.go | 2 +-
.../evm21/mercury/streams/streams_test.go | 13 +++++-------
.../ocr2keeper/evm21/payload_builder.go | 2 +-
.../ocr2keeper/evm21/payload_builder_test.go | 2 +-
.../ocr2/plugins/ocr2keeper/evm21/registry.go | 2 +-
.../evm21/registry_check_pipeline.go | 3 ++-
.../evm21/registry_check_pipeline_test.go | 20 ++++++++-----------
.../plugins/ocr2keeper/evm21/registry_test.go | 3 ++-
.../ocr2/plugins/ocr2keeper/evm21/services.go | 6 ++++--
.../ocr2keeper/evm21/transmit/cache.go | 2 +-
.../ocr2keeper/evm21/transmit/cache_test.go | 3 ++-
.../ocr2keeper/evm21/transmit/encoding.go | 2 +-
.../evm21/transmit/encoding_test.go | 3 ++-
.../evm21/transmit/event_provider.go | 2 +-
.../evm21/transmit/event_provider_test.go | 2 +-
.../ocr2keeper/evm21/upkeep_provider.go | 2 +-
.../ocr2keeper/evm21/upkeep_provider_test.go | 3 ++-
.../ocr2keeper/evm21/upkeepstate/store.go | 2 +-
.../evm21/upkeepstate/store_test.go | 2 +-
.../plugins/ocr2keeper/integration_21_test.go | 6 +++---
.../plugins/ocr2keeper/integration_test.go | 11 +++++-----
core/services/ocr2/plugins/ocr2keeper/util.go | 12 +++++------
core/services/relay/evm/ocr2keeper.go | 6 +++---
core/services/telemetry/manager_test.go | 5 +++--
go.mod | 2 +-
go.sum | 4 ++--
.../actions/automation_ocr_helpers.go | 5 +++--
.../actions/automation_ocr_helpers_local.go | 8 +++++---
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 ++--
.../automationv2_1/automationv2_1_test.go | 13 +++++++-----
77 files changed, 166 insertions(+), 142 deletions(-)
diff --git a/contracts/src/v0.8/automation/v2_1/LICENSE b/contracts/src/v0.8/automation/v2_1/LICENSE
index 03ba03d779..7d09d647f5 100644
--- a/contracts/src/v0.8/automation/v2_1/LICENSE
+++ b/contracts/src/v0.8/automation/v2_1/LICENSE
@@ -12,7 +12,7 @@ Licensor: SmartContract Chainlink Limited SEZC
Licensed Work: Automation v2.1
The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC
-Additional Use Grant: Any uses listed and defined at https://github.com/smartcontractkit/ocr2keepers/tree/main/pkg/v3/Automation_v2.1_Grants.md
+Additional Use Grant: Any uses listed and defined at https://github.com/smartcontractkit/chainlink-automation/tree/main/pkg/v3/Automation_v2.1_Grants.md
Change Date: September 12, 2027
diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go
index 8f65b1f881..4938907669 100644
--- a/core/scripts/chaincli/handler/debug.go
+++ b/core/scripts/chaincli/handler/debug.go
@@ -19,7 +19,8 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/core/scripts/chaincli/config"
"github.com/smartcontractkit/chainlink/core/scripts/common"
diff --git a/core/scripts/chaincli/handler/keeper_deployer.go b/core/scripts/chaincli/handler/keeper_deployer.go
index eae8c68d33..7c53275342 100644
--- a/core/scripts/chaincli/handler/keeper_deployer.go
+++ b/core/scripts/chaincli/handler/keeper_deployer.go
@@ -13,14 +13,15 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/umbracle/ethgo/abi"
+
ocr2config "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
- ocr3confighelper "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
+ "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/umbracle/ethgo/abi"
"github.com/smartcontractkit/chainlink/core/scripts/chaincli/config"
- offchain20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
+ offchain20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config"
"github.com/smartcontractkit/chainlink/v2/core/cmd"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
diff --git a/core/scripts/chaincli/handler/ocr2_config.go b/core/scripts/chaincli/handler/ocr2_config.go
index 7cf2536405..21b2ad414a 100644
--- a/core/scripts/chaincli/handler/ocr2_config.go
+++ b/core/scripts/chaincli/handler/ocr2_config.go
@@ -11,8 +11,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/olekukonko/tablewriter"
+
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
- ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
+
+ ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
)
diff --git a/core/scripts/chaincli/handler/report.go b/core/scripts/chaincli/handler/report.go
index 90f2be9654..8381bbc137 100644
--- a/core/scripts/chaincli/handler/report.go
+++ b/core/scripts/chaincli/handler/report.go
@@ -16,8 +16,10 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/olekukonko/tablewriter"
+
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers20 "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+
+ ocr2keepers20 "github.com/smartcontractkit/chainlink-automation/pkg/v2"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
evm "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm20"
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 09c76dd195..0d78e15d59 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -21,10 +21,10 @@ require (
github.com/pelletier/go-toml/v2 v2.1.0
github.com/pkg/errors v0.9.1
github.com/shopspring/decimal v1.3.1
+ github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459
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-20231107151413-13e0202ae8d7
- github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.4
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index b1a0870114..3dd48f7445 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1462,6 +1462,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
+github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459 h1:hJhuShYv9eUQxHJQdOmyEymVmApOrICrQdOY7kKQ5Io=
+github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
@@ -1478,8 +1480,6 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XOYSxpFmFqlhr5IaEh1uQ1F6CewJ30D/U/P34c=
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
-github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
-github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index 2f2a903339..7a90e3b07e 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -17,13 +17,14 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers20 "github.com/smartcontractkit/ocr2keepers/pkg/v2"
- ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
- ocr2keepers20coordinator "github.com/smartcontractkit/ocr2keepers/pkg/v2/coordinator"
- ocr2keepers20polling "github.com/smartcontractkit/ocr2keepers/pkg/v2/observer/polling"
- ocr2keepers20runner "github.com/smartcontractkit/ocr2keepers/pkg/v2/runner"
- ocr2keepers21config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
- ocr2keepers21 "github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
+
+ ocr2keepers20 "github.com/smartcontractkit/chainlink-automation/pkg/v2"
+ ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config"
+ ocr2keepers20coordinator "github.com/smartcontractkit/chainlink-automation/pkg/v2/coordinator"
+ ocr2keepers20polling "github.com/smartcontractkit/chainlink-automation/pkg/v2/observer/polling"
+ ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner"
+ ocr2keepers21config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config"
+ ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin"
"github.com/smartcontractkit/chainlink-vrf/altbn_128"
dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg"
@@ -66,7 +67,6 @@ import (
functionsRelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions"
evmmercury "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury"
mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils"
-
evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization"
"github.com/smartcontractkit/chainlink/v2/core/services/telemetry"
diff --git a/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
index 6d52c0e8d2..fd43747f52 100644
--- a/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/custom_telemetry.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/abi.go b/core/services/ocr2/plugins/ocr2keeper/evm20/abi.go
index 4c0beee8fd..98aeed6678 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/abi.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/abi.go
@@ -8,7 +8,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
)
type evmRegistryPackerV2_0 struct {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/abi_test.go b/core/services/ocr2/plugins/ocr2keeper/evm20/abi_test.go
index 7efc3feb1f..c63c0d00f3 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/abi_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/abi_test.go
@@ -8,9 +8,10 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
"github.com/stretchr/testify/assert"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/encoder.go b/core/services/ocr2/plugins/ocr2keeper/evm20/encoder.go
index 3984cb7496..aa98fd44ce 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/encoder.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/encoder.go
@@ -6,8 +6,9 @@ import (
"reflect"
"github.com/ethereum/go-ethereum/accounts/abi"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
- "github.com/smartcontractkit/ocr2keepers/pkg/v2/encoding"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v2/encoding"
)
type EVMAutomationEncoder20 struct {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/encoder_test.go b/core/services/ocr2/plugins/ocr2keeper/evm20/encoder_test.go
index 74be6b46ee..7621289265 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/encoder_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/encoder_test.go
@@ -5,8 +5,9 @@ import (
"testing"
"github.com/pkg/errors"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
"github.com/stretchr/testify/assert"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
)
func TestEVMAutomationEncoder20(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/head.go b/core/services/ocr2/plugins/ocr2keeper/evm20/head.go
index 1023bff5dd..7898317355 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/head.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/head.go
@@ -4,7 +4,7 @@ import (
"context"
"fmt"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
index d8941d505b..7ab641d2bf 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/log_provider.go
@@ -11,9 +11,9 @@ import (
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
- pluginutils "github.com/smartcontractkit/ocr2keepers/pkg/util"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
- "github.com/smartcontractkit/ocr2keepers/pkg/v2/encoding"
+ pluginutils "github.com/smartcontractkit/chainlink-automation/pkg/util"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v2/encoding"
"github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
index 7fe4087cfa..3cb91ab8dc 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry.go
@@ -17,7 +17,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"go.uber.org/multierr"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
index 340bd92357..0e0ceba716 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm20/registry_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v2"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v2"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/active_list.go b/core/services/ocr2/plugins/ocr2keeper/evm21/active_list.go
index 899dd398d0..9f82555633 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/active_list.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/active_list.go
@@ -4,7 +4,7 @@ import (
"math/big"
"sync"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/active_list_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/active_list_test.go
index 76ca6bfdf1..06b9979eef 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/active_list_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/active_list_test.go
@@ -5,9 +5,10 @@ import (
"sort"
"testing"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
index 0cf0bbef5c..0ed4c84dbb 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/autotelemetry21/custom_telemetry.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
index ae407b0ea9..134a75fc2c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
index afb9d4a091..41a43b951e 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/block_subscriber_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/interfaces.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/interfaces.go
index d9417c72a1..49975855b5 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/interfaces.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/interfaces.go
@@ -3,7 +3,7 @@ package core
import (
"context"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
// UpkeepStateReader is the interface for reading the current state of upkeeps.
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/mocks/upkeep_state_reader.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/mocks/upkeep_state_reader.go
index 40b63611c9..b036fbb26c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/mocks/upkeep_state_reader.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/mocks/upkeep_state_reader.go
@@ -7,7 +7,7 @@ import (
mock "github.com/stretchr/testify/mock"
- types "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ types "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
// UpkeepStateReader is an autogenerated mock type for the UpkeepStateReader type
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload.go
index d733673767..ed5530ae7b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload.go
@@ -6,7 +6,8 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/crypto"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
var (
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload_test.go
index 1ca280c0d2..cb3a67dde0 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/payload_test.go
@@ -5,9 +5,9 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
-
"github.com/stretchr/testify/assert"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
func TestWorkID(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/testutil.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/testutil.go
index 47935b56f6..3c0eeb1c44 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/testutil.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/testutil.go
@@ -4,7 +4,8 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
// GenUpkeepID generates an ocr2keepers.UpkeepIdentifier with a specific UpkeepType and some random string
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger.go
index 7927347959..02e6946c8f 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger_test.go
index 0233e40679..366d59b639 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/trigger_test.go
@@ -7,8 +7,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
func TestPackUnpackTrigger(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/type.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/type.go
index aeb56a16f6..7820b47e6e 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/type.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/type.go
@@ -3,7 +3,7 @@ package core
import (
"math/big"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
const (
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/core/type_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/core/type_test.go
index 8a2a51533e..6f81ca7690 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/core/type_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/core/type_test.go
@@ -4,9 +4,9 @@ import (
"math/big"
"testing"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
-
"github.com/stretchr/testify/assert"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
func TestGetUpkeepType(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder.go
index 239de099c0..fadf55633d 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder.go
@@ -4,7 +4,7 @@ import (
"fmt"
"math/big"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder_test.go
index 578153e07a..63ff2650be 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/encoder_test.go
@@ -5,9 +5,10 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go
index e21ecfb800..cf98115d76 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/interface.go
@@ -3,7 +3,7 @@ package encoding
import (
"math/big"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go
index 28c6c4a975..0157d1baf8 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go
index 03b55bfccc..b52b777dbe 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/encoding/packer_test.go
@@ -9,10 +9,11 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/keyring.go b/core/services/ocr2/plugins/ocr2keeper/evm21/keyring.go
index df4e3a8650..2d84f09637 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/keyring.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/keyring.go
@@ -3,7 +3,8 @@ package evm
import (
"github.com/smartcontractkit/libocr/offchainreporting2/types"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
+
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin"
)
var _ ocr3types.OnchainKeyring[plugin.AutomationReportInfo] = &onchainKeyringV3Wrapper{}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/keyring_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/keyring_test.go
index 14c42a810c..92a05c2d76 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/keyring_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/keyring_test.go
@@ -3,10 +3,12 @@ package evm
import (
"testing"
+ "github.com/stretchr/testify/assert"
+
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
- "github.com/stretchr/testify/assert"
+
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin"
)
func TestNewOnchainKeyringV3Wrapper(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer.go
index b06a3ca809..81f51311d4 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer.go
@@ -7,8 +7,8 @@ import (
"sync"
"sync/atomic"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/random"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/random"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer_test.go
index 5c8908f9be..a973ea6e19 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/buffer_test.go
@@ -7,9 +7,10 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
index c7db01d878..dd90b5e00b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go
@@ -12,14 +12,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
"golang.org/x/time/rate"
- "github.com/jmoiron/sqlx"
-
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
index d3f069a9bf..a3887cbe78 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go
@@ -16,7 +16,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
index b28b45fcb4..c58bd85951 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_life_cycle_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
index c6ebb1c51a..81774e2638 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go
@@ -11,15 +11,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "golang.org/x/time/rate"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
-
- "golang.org/x/time/rate"
)
func TestLogEventProvider_GetFilters(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
index c656656815..98eb0b291b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go
@@ -16,8 +16,8 @@ import (
"github.com/ethereum/go-ethereum/common"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/random"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/random"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
index 77b0eec545..10e58bf26b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer_test.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
index d34787f501..f98d4ed2df 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams.go
@@ -15,7 +15,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/patrickmn/go-cache"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
index 0653796f41..baa277e035 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams/streams_test.go
@@ -15,24 +15,21 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
- "github.com/stretchr/testify/require"
-
"github.com/stretchr/testify/assert"
-
"github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
- v02 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02"
- v03 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03"
-
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury"
+ v02 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v02"
+ v03 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/v03"
)
type MockMercuryConfigProvider struct {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder.go b/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder.go
index b14e687b5d..e138f440e4 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder.go
@@ -3,7 +3,7 @@ package evm
import (
"context"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go
index e68e316ae3..d7c2312d19 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/payload_builder_test.go
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
index afb1a7cf6c..18795eb073 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry.go
@@ -19,7 +19,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/services"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
index ad31c8feb0..b0db3f7dd1 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline.go
@@ -9,7 +9,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
index d4e38637d8..4eaf334f7c 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_check_pipeline_test.go
@@ -8,31 +8,27 @@ import (
"sync/atomic"
"testing"
- "github.com/stretchr/testify/require"
-
"github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/patrickmn/go-cache"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
-
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
-
+ "github.com/patrickmn/go-cache"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/encoding"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go
index 4be0ccce4e..fdc6675da8 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/registry_test.go
@@ -11,10 +11,11 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
coreTypes "github.com/ethereum/go-ethereum/core/types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
types3 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/services.go b/core/services/ocr2/plugins/ocr2keeper/evm21/services.go
index d178a9af57..18c9ed6d39 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/services.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/services.go
@@ -5,10 +5,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/jmoiron/sqlx"
+
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache.go
index 5e0dadbdc4..99e1f1dc16 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache.go
@@ -3,7 +3,7 @@ package transmit
import (
"sync"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
// transmitEventCache holds a ring buffer of the last visited blocks (transmit block),
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache_test.go
index 55d245c168..7f4a129656 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/cache_test.go
@@ -3,8 +3,9 @@ package transmit
import (
"testing"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/require"
+
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
)
func TestTransmitEventCache_Sanity(t *testing.T) {
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding.go
index ec709d04bd..17d3cd439f 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding.go
@@ -4,7 +4,7 @@ import (
"fmt"
"math/big"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding_test.go
index f081f82f2a..7415b3701f 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/encoding_test.go
@@ -4,9 +4,10 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
index 000d40f407..95f5ec0bf1 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
index a33056977a..8d56fec22a 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider.go
index 5cb60d5dc1..5b6d4ac703 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider.go
@@ -4,7 +4,7 @@ import (
"context"
"fmt"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider_test.go
index ac49675812..69bfabb259 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeep_provider_test.go
@@ -5,9 +5,10 @@ import (
"sync/atomic"
"testing"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
"github.com/stretchr/testify/require"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/core"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
index f5e3969bc7..505959b8f3 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store.go
@@ -8,7 +8,7 @@ import (
"sync"
"time"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go
index 579d875792..138b9ffd78 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evm21/upkeepstate/store_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
index d2f35a3e37..01418b9f76 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go
@@ -26,13 +26,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/umbracle/ethgo/abi"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
-
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
+
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/config"
"github.com/smartcontractkit/chainlink-common/pkg/types"
@@ -55,6 +54,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
)
diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
index 3eda886796..1ab9194c49 100644
--- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go
@@ -23,15 +23,16 @@ import (
"github.com/hashicorp/consul/sdk/freeport"
"github.com/onsi/gomega"
"github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/umbracle/ethgo/abi"
"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "github.com/umbracle/ethgo/abi"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v2/config"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
@@ -60,8 +61,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
-
- "github.com/smartcontractkit/chainlink-common/pkg/types"
)
const (
diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go
index 504b6267c6..2c477e7a6a 100644
--- a/core/services/ocr2/plugins/ocr2keeper/util.go
+++ b/core/services/ocr2/plugins/ocr2keeper/util.go
@@ -6,14 +6,14 @@ import (
"github.com/jmoiron/sqlx"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers20 "github.com/smartcontractkit/ocr2keepers/pkg/v2"
- ocr2keepers20coordinator "github.com/smartcontractkit/ocr2keepers/pkg/v2/coordinator"
- ocr2keepers20polling "github.com/smartcontractkit/ocr2keepers/pkg/v2/observer/polling"
- ocr2keepers20runner "github.com/smartcontractkit/ocr2keepers/pkg/v2/runner"
- "github.com/smartcontractkit/chainlink-common/pkg/types"
+ ocr2keepers20 "github.com/smartcontractkit/chainlink-automation/pkg/v2"
+ ocr2keepers20coordinator "github.com/smartcontractkit/chainlink-automation/pkg/v2/coordinator"
+ ocr2keepers20polling "github.com/smartcontractkit/chainlink-automation/pkg/v2/observer/polling"
+ ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner"
+ ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
- ocr2keepers21 "github.com/smartcontractkit/ocr2keepers/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go
index 2e8f9cbf48..2b484edb79 100644
--- a/core/services/relay/evm/ocr2keeper.go
+++ b/core/services/relay/evm/ocr2keeper.go
@@ -14,11 +14,11 @@ import (
"github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator"
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
- "github.com/smartcontractkit/ocr2keepers/pkg/v3/plugin"
+ ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin"
- ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go
index 31f7ea74c1..f09e4d3482 100644
--- a/core/services/telemetry/manager_test.go
+++ b/core/services/telemetry/manager_test.go
@@ -190,12 +190,13 @@ func TestNewManager(t *testing.T) {
require.Equal(t, "TelemetryManager", m.Name())
require.Nil(t, m.Start(testutils.Context(t)))
+ t.Cleanup(func() {
+ require.NoError(t, m.Close())
+ })
testutils.WaitForLogMessageCount(t, logObs, "error connecting error while dialing dial tcp", 3)
hr := m.HealthReport()
require.Equal(t, 4, len(hr))
- require.Nil(t, m.Close())
- time.Sleep(time.Second * 1)
}
func TestCorrectEndpointRouting(t *testing.T) {
diff --git a/go.mod b/go.mod
index c13f476bf2..b3bdeb74cf 100644
--- a/go.mod
+++ b/go.mod
@@ -65,13 +65,13 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
+ github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664
github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
- github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wsrpc v0.7.2
diff --git a/go.sum b/go.sum
index 4f465dc8f9..bdfbe2107e 100644
--- a/go.sum
+++ b/go.sum
@@ -1463,6 +1463,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
+github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459 h1:hJhuShYv9eUQxHJQdOmyEymVmApOrICrQdOY7kKQ5Io=
+github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
@@ -1479,8 +1481,6 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XOYSxpFmFqlhr5IaEh1uQ1F6CewJ30D/U/P34c=
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
-github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
-github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go
index e1635902db..38df2e00b5 100644
--- a/integration-tests/actions/automation_ocr_helpers.go
+++ b/integration-tests/actions/automation_ocr_helpers.go
@@ -17,8 +17,9 @@ import (
ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
- ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
+
+ ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config"
+ ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
diff --git a/integration-tests/actions/automation_ocr_helpers_local.go b/integration-tests/actions/automation_ocr_helpers_local.go
index f541594c4d..e591e75a98 100644
--- a/integration-tests/actions/automation_ocr_helpers_local.go
+++ b/integration-tests/actions/automation_ocr_helpers_local.go
@@ -9,12 +9,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/lib/pq"
"github.com/rs/zerolog"
+ "gopkg.in/guregu/null.v4"
+
ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
- ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config"
- ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
- "gopkg.in/guregu/null.v4"
+
+ ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config"
+ ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index 9e99f39b44..cdd42deda7 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -22,12 +22,12 @@ require (
github.com/scylladb/go-reflectx v1.0.1
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
+ github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
github.com/smartcontractkit/chainlink-testing-framework v1.19.1
github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7
- github.com/smartcontractkit/ocr2keepers v0.7.28
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
github.com/smartcontractkit/wasp v0.3.0
github.com/spf13/cobra v1.6.1
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 87cceb9b99..08b772c9ce 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2367,6 +2367,8 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo=
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
+github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459 h1:hJhuShYv9eUQxHJQdOmyEymVmApOrICrQdOY7kKQ5Io=
+github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
@@ -2385,8 +2387,6 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7 h1:21V61XOYSxpFmFqlhr5IaEh1uQ1F6CewJ30D/U/P34c=
github.com/smartcontractkit/libocr v0.0.0-20231107151413-13e0202ae8d7/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0=
-github.com/smartcontractkit/ocr2keepers v0.7.28 h1:dufAiYl4+uly9aH0+6GkS2jYzHGujq7tg0LYQE+x6JU=
-github.com/smartcontractkit/ocr2keepers v0.7.28/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go
index 06c2624d0f..1f39d5e4b0 100644
--- a/integration-tests/load/automationv2_1/automationv2_1_test.go
+++ b/integration-tests/load/automationv2_1/automationv2_1_test.go
@@ -18,9 +18,10 @@ import (
"github.com/stretchr/testify/require"
ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
- ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config"
"github.com/smartcontractkit/wasp"
+ ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config"
+
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/config"
@@ -29,15 +30,17 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum"
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
+
+ registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper"
+
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
contractseth "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/testreporters"
- registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper"
)
const (
From 4342e167b5f4b3ace7be3f374a64d047dd7492cc Mon Sep 17 00:00:00 2001
From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com>
Date: Tue, 21 Nov 2023 10:29:38 -0800
Subject: [PATCH 186/327] release/2.7.0 -> develop (#11291)
* Bump version and update CHANGELOG for core v2.7.0
* core: log a warning when deprecated P2P.V1 config is set in TOML (#11073)
* core: log a warning when deprecated P2P.V1 config is set in TOML
* change default P2P from V1 to V2
* bump operator ui
(cherry picked from commit 5808e734cf024a5e8c5450e939e1f2d5b3cba546)
* operator-ui deprecation warnings (#11104)
Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com>
Co-authored-by: github-merge-queue[bot]
Co-authored-by: Jordan Krage
* chore: bump sigstore/cosign-installer from 2.1.0 to 3.1.2
* Finalize date on changelog for 2.7.0
---------
Co-authored-by: Jordan Krage
Co-authored-by: chainchad <96362174+chainchad@users.noreply.github.com>
Co-authored-by: george-dorin <120329946+george-dorin@users.noreply.github.com>
Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com>
Co-authored-by: github-merge-queue[bot]
Co-authored-by: Erik Burton
---
docs/CHANGELOG.md | 4 ++--
integration-tests/smoke/automation_test.go | 7 ++-----
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 1351c42134..8e016347c4 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -36,6 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
...
+
+
## 2.7.1 - UNRELEASED
### Fixed
@@ -74,8 +76,6 @@ Starting in `v2.9.0`:
- Removed the ability to set a next nonce value for an address through CLI
-
-
## 2.6.0 - 2023-10-18
### Added
diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go
index 05d19d5ccd..cdc8748676 100644
--- a/integration-tests/smoke/automation_test.go
+++ b/integration-tests/smoke/automation_test.go
@@ -10,16 +10,12 @@ import (
"testing"
"time"
- "github.com/kelseyhightower/envconfig"
-
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
-
"github.com/ethereum/go-ethereum/common"
+ "github.com/kelseyhightower/envconfig"
"github.com/onsi/gomega"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
-
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/networks"
"github.com/smartcontractkit/chainlink-testing-framework/utils/ptr"
@@ -27,6 +23,7 @@ import (
cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1"
+ "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21/mercury/streams"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
From 4c6d0fe9d0bc4e4c450b0c528e08db000b745e9f Mon Sep 17 00:00:00 2001
From: chainchad <96362174+chainchad@users.noreply.github.com>
Date: Tue, 21 Nov 2023 14:49:47 -0500
Subject: [PATCH 187/327] Avoid checking version file bump on forks in CI
(#11351)
---
.github/workflows/build-publish.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml
index 1bda6957a2..de33663d88 100644
--- a/.github/workflows/build-publish.yml
+++ b/.github/workflows/build-publish.yml
@@ -17,7 +17,8 @@ jobs:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Check for VERSION file bump on tags
- if: ${{ startsWith(github.ref, 'refs/tags/v') }}
+ # Avoids checking VERSION file bump on forks.
+ if: ${{ github.repository == 'smartcontractkit/chainlink' && startsWith(github.ref, 'refs/tags/v') }}
uses: ./.github/actions/version-file-bump
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
From aca537daff2cd5c01cc0f204b1b345a7e6c1385c Mon Sep 17 00:00:00 2001
From: amit-momin <108959691+amit-momin@users.noreply.github.com>
Date: Tue, 21 Nov 2023 16:04:20 -0600
Subject: [PATCH 188/327] Remove dependencies on services package in common
(#11321)
* Removed dependencies on services package in common
* Marked json data type as deprecated and cleaned up test vars
* Replaced json data type with alias
---
common/txmgr/types/forwarder_manager.go | 4 +-
common/txmgr/types/tx.go | 6 +-
common/txmgr/types/tx_attempt_builder.go | 4 +-
common/txmgr/types/tx_store.go | 3 -
common/types/head_tracker.go | 6 +-
core/chains/evm/txmgr/broadcaster_test.go | 4 +-
core/chains/evm/txmgr/evm_tx_store.go | 7 +--
core/chains/evm/txmgr/transmitchecker_test.go | 6 +-
core/scripts/go.mod | 2 +-
core/scripts/go.sum | 4 +-
core/services/keystore/keys/ethkey/key.go | 10 ++--
core/services/pg/datatypes/json.go | 56 +------------------
core/services/vrf/v2/integration_v2_test.go | 17 +++---
core/services/vrf/v2/listener_v2_test.go | 10 ++--
go.mod | 2 +-
go.sum | 4 +-
integration-tests/go.mod | 2 +-
integration-tests/go.sum | 4 +-
18 files changed, 49 insertions(+), 102 deletions(-)
diff --git a/common/txmgr/types/forwarder_manager.go b/common/txmgr/types/forwarder_manager.go
index 8d58f91295..4d70b73000 100644
--- a/common/txmgr/types/forwarder_manager.go
+++ b/common/txmgr/types/forwarder_manager.go
@@ -1,13 +1,13 @@
package types
import (
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/services"
)
//go:generate mockery --quiet --name ForwarderManager --output ./mocks/ --case=underscore
type ForwarderManager[ADDR types.Hashable] interface {
- services.ServiceCtx
+ services.Service
ForwarderFor(addr ADDR) (forwarder ADDR, err error)
// Converts payload to be forwarder-friendly
ConvertPayload(dest ADDR, origPayload []byte) ([]byte, error)
diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go
index 11017bd032..78f6fba459 100644
--- a/common/txmgr/types/tx.go
+++ b/common/txmgr/types/tx.go
@@ -13,11 +13,11 @@ import (
"github.com/pkg/errors"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
clnull "github.com/smartcontractkit/chainlink/v2/core/null"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
)
// TxStrategy controls how txes are queued and sent
@@ -210,7 +210,7 @@ type Tx[
// Marshalled TxMeta
// Used for additional context around transactions which you want to log
// at send time.
- Meta *datatypes.JSON
+ Meta *sqlutil.JSON
Subject uuid.NullUUID
ChainID CHAIN_ID
@@ -219,7 +219,7 @@ type Tx[
// TransmitChecker defines the check that should be performed before a transaction is submitted on
// chain.
- TransmitChecker *datatypes.JSON
+ TransmitChecker *sqlutil.JSON
// Marks tx requiring callback
SignalCallback bool
diff --git a/common/txmgr/types/tx_attempt_builder.go b/common/txmgr/types/tx_attempt_builder.go
index 887219c490..75712fc0c3 100644
--- a/common/txmgr/types/tx_attempt_builder.go
+++ b/common/txmgr/types/tx_attempt_builder.go
@@ -3,10 +3,10 @@ package types
import (
"context"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services"
)
// TxAttemptBuilder takes the base unsigned transaction + optional parameters (tx type, gas parameters)
@@ -23,7 +23,7 @@ type TxAttemptBuilder[
FEE feetypes.Fee, // FEE - chain fee type
] interface {
// interfaces for running the underlying estimator
- services.ServiceCtx
+ services.Service
types.HeadTrackable[HEAD, BLOCK_HASH]
// NewTxAttempt builds a transaction using the configured transaction type and fee estimator (new estimation)
diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go
index c2dfeee414..f731031f92 100644
--- a/common/txmgr/types/tx_store.go
+++ b/common/txmgr/types/tx_store.go
@@ -9,7 +9,6 @@ import (
feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/common/types"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
)
// TxStore is a superset of all the needed persistence layer methods
@@ -118,8 +117,6 @@ type ReceiptPlus[R any] struct {
FailOnRevert bool `db:"fail_on_revert"`
}
-type QueryerFunc = func(tx pg.Queryer) error
-
type ChainReceipt[TX_HASH, BLOCK_HASH types.Hashable] interface {
GetStatus() uint64
GetTxHash() TX_HASH
diff --git a/common/types/head_tracker.go b/common/types/head_tracker.go
index 811298f895..d8fa801178 100644
--- a/common/types/head_tracker.go
+++ b/common/types/head_tracker.go
@@ -3,7 +3,7 @@ package types
import (
"context"
- "github.com/smartcontractkit/chainlink/v2/core/services"
+ "github.com/smartcontractkit/chainlink-common/pkg/services"
)
// HeadTracker holds and stores the block experienced by a particular node in a thread safe manner.
@@ -11,7 +11,7 @@ import (
//
//go:generate mockery --quiet --name HeadTracker --output ../mocks/ --case=underscore
type HeadTracker[H Head[BLOCK_HASH], BLOCK_HASH Hashable] interface {
- services.ServiceCtx
+ services.Service
// Backfill given a head will fill in any missing heads up to the given depth
// (used for testing)
Backfill(ctx context.Context, headWithChain H, depth uint) (err error)
@@ -68,7 +68,7 @@ type NewHeadHandler[H Head[BLOCK_HASH], BLOCK_HASH Hashable] func(ctx context.Co
//
//go:generate mockery --quiet --name HeadBroadcaster --output ../mocks/ --case=underscore
type HeadBroadcaster[H Head[BLOCK_HASH], BLOCK_HASH Hashable] interface {
- services.ServiceCtx
+ services.Service
BroadcastNewLongestChain(H)
HeadBroadcasterRegistry[H, BLOCK_HASH]
}
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index bf480c66af..d1e26c6c96 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -22,6 +22,7 @@ import (
"go.uber.org/zap/zapcore"
"gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
@@ -43,7 +44,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -255,7 +255,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
tr := int32(99)
b, err := json.Marshal(txmgr.TxMeta{JobID: &tr})
require.NoError(t, err)
- meta := datatypes.JSON(b)
+ meta := sqlutil.JSON(b)
earlierEthTx := txmgr.Tx{
FromAddress: fromAddress,
ToAddress: toAddress,
diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go
index 0e08d32b77..84fe9a02c6 100644
--- a/core/chains/evm/txmgr/evm_tx_store.go
+++ b/core/chains/evm/txmgr/evm_tx_store.go
@@ -18,6 +18,7 @@ import (
pkgerrors "github.com/pkg/errors"
nullv4 "gopkg.in/guregu/null.v4"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
"github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
@@ -27,7 +28,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/null"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
"github.com/smartcontractkit/chainlink/v2/core/utils"
)
@@ -171,14 +171,14 @@ type DbEthTx struct {
// Marshalled EvmTxMeta
// Used for additional context around transactions which you want to log
// at send time.
- Meta *datatypes.JSON
+ Meta *sqlutil.JSON
Subject uuid.NullUUID
PipelineTaskRunID uuid.NullUUID
MinConfirmations null.Uint32
EVMChainID utils.Big
// TransmitChecker defines the check that should be performed before a transaction is submitted on
// chain.
- TransmitChecker *datatypes.JSON
+ TransmitChecker *sqlutil.JSON
InitialBroadcastAt *time.Time
// Marks tx requiring callback
SignalCallback bool
@@ -1451,7 +1451,6 @@ func (o *evmTxStore) UpdateTxFatalError(ctx context.Context, etx *Tx) error {
}
// Updates eth attempt from in_progress to broadcast. Also updates the eth tx to unconfirmed.
-// One of the more complicated signatures. We have to accept variable pg.QOpt and QueryerFunc arguments
func (o *evmTxStore) UpdateTxAttemptInProgressToBroadcast(ctx context.Context, etx *Tx, attempt TxAttempt, NewAttemptState txmgrtypes.TxAttemptState) error {
var cancel context.CancelFunc
ctx, cancel = o.mergeContexts(ctx)
diff --git a/core/chains/evm/txmgr/transmitchecker_test.go b/core/chains/evm/txmgr/transmitchecker_test.go
index b43fcb4f45..5ebf5f32e3 100644
--- a/core/chains/evm/txmgr/transmitchecker_test.go
+++ b/core/chains/evm/txmgr/transmitchecker_test.go
@@ -20,6 +20,7 @@ import (
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
@@ -29,7 +30,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
)
func TestFactory(t *testing.T) {
@@ -192,7 +192,7 @@ func TestTransmitCheckers(t *testing.T) {
b, err := json.Marshal(meta)
require.NoError(t, err)
- metaJson := datatypes.JSON(b)
+ metaJson := sqlutil.JSON(b)
tx := txmgr.Tx{
FromAddress: common.HexToAddress("0xfe0629509E6CB8dfa7a99214ae58Ceb465d5b5A9"),
@@ -296,7 +296,7 @@ func TestTransmitCheckers(t *testing.T) {
b, err := json.Marshal(meta)
require.NoError(t, err)
- metaJson := datatypes.JSON(b)
+ metaJson := sqlutil.JSON(b)
tx := txmgr.Tx{
FromAddress: common.HexToAddress("0xfe0629509E6CB8dfa7a99214ae58Ceb465d5b5A9"),
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 0d78e15d59..e9fa432d4c 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -303,7 +303,7 @@ require (
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect
- github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e // indirect
+ github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 3dd48f7445..3d9962474b 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -1464,8 +1464,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459 h1:hJhuShYv9eUQxHJQdOmyEymVmApOrICrQdOY7kKQ5Io=
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k=
-github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
-github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3 h1:cyA1aW1PYrOLZAMaSmuH7U99QBTfrF59s+6uDxQgOr0=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542/go.mod h1:EpvRoycRD+kniYlz+pCpRT5e+fmPm0mSD/vmND+0oMg=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 h1:D7yb4kgNGVAiD5lFYqm/LW8d5jU66TXyYvSskDiW9yg=
diff --git a/core/services/keystore/keys/ethkey/key.go b/core/services/keystore/keys/ethkey/key.go
index 4201251e34..6335ed55ad 100644
--- a/core/services/keystore/keys/ethkey/key.go
+++ b/core/services/keystore/keys/ethkey/key.go
@@ -3,7 +3,7 @@ package ethkey
import (
"time"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
)
// NOTE: This model refers to the OLD key and is only used for migrations
@@ -15,10 +15,10 @@ import (
type Key struct {
ID int32
Address EIP55Address
- JSON datatypes.JSON `json:"-"`
- CreatedAt time.Time `json:"-"`
- UpdatedAt time.Time `json:"-"`
- DeletedAt *time.Time `json:"-"`
+ JSON sqlutil.JSON `json:"-"`
+ CreatedAt time.Time `json:"-"`
+ UpdatedAt time.Time `json:"-"`
+ DeletedAt *time.Time `json:"-"`
// IsFunding marks the address as being used for rescuing the node and the pending transactions
// Only one key can be IsFunding=true at a time.
IsFunding bool
diff --git a/core/services/pg/datatypes/json.go b/core/services/pg/datatypes/json.go
index d84c89269c..ac72a5a5ed 100644
--- a/core/services/pg/datatypes/json.go
+++ b/core/services/pg/datatypes/json.go
@@ -1,59 +1,9 @@
package datatypes
import (
- "database/sql/driver"
- "encoding/json"
- "errors"
- "fmt"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
)
// JSON defined JSON data type, need to implements driver.Valuer, sql.Scanner interface
-type JSON json.RawMessage
-
-// Value return json value, implement driver.Valuer interface
-func (j JSON) Value() (driver.Value, error) {
- if len(j) == 0 {
- return nil, nil
- }
- bytes, err := json.RawMessage(j).MarshalJSON()
- return string(bytes), err
-}
-
-// Scan scan value into Jsonb, implements sql.Scanner interface
-func (j *JSON) Scan(value interface{}) error {
- if value == nil {
- *j = JSON("null")
- return nil
- }
- var bytes []byte
- switch v := value.(type) {
- case []byte:
- bytes = v
- case string:
- bytes = []byte(v)
- default:
- return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
- }
-
- result := json.RawMessage{}
- err := json.Unmarshal(bytes, &result)
- *j = JSON(result)
- return err
-}
-
-// MarshalJSON to output non base64 encoded []byte
-func (j JSON) MarshalJSON() ([]byte, error) {
- return json.RawMessage(j).MarshalJSON()
-}
-
-// UnmarshalJSON to deserialize []byte
-func (j *JSON) UnmarshalJSON(b []byte) error {
- result := json.RawMessage{}
- err := result.UnmarshalJSON(b)
- *j = JSON(result)
- return err
-}
-
-func (j JSON) String() string {
- return string(j)
-}
+// Deprecated: Use sqlutil.JSON instead
+type JSON = sqlutil.JSON
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index 6880fa1799..f57cb640f6 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -30,6 +30,7 @@ import (
"github.com/jmoiron/sqlx"
commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -70,7 +71,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey"
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1"
@@ -2038,13 +2038,13 @@ func TestStartingCountsV1(t *testing.T) {
}
md1, err := json.Marshal(&m1)
require.NoError(t, err)
- md1_ := datatypes.JSON(md1)
+ md1SQL := sqlutil.JSON(md1)
reqID2 := utils.PadByteToHash(0x11)
m2 := txmgr.TxMeta{
RequestID: &reqID2,
}
md2, err := json.Marshal(&m2)
- md2_ := datatypes.JSON(md2)
+ md2SQL := sqlutil.JSON(md2)
require.NoError(t, err)
chainID := utils.NewBig(testutils.SimulatedChainID)
confirmedTxes := []txmgr.Tx{
@@ -2056,7 +2056,7 @@ func TestStartingCountsV1(t *testing.T) {
InitialBroadcastAt: &b,
CreatedAt: b,
State: txmgrcommon.TxConfirmed,
- Meta: &datatypes.JSON{},
+ Meta: &sqlutil.JSON{},
EncodedPayload: []byte{},
ChainID: chainID.ToInt(),
},
@@ -2068,7 +2068,7 @@ func TestStartingCountsV1(t *testing.T) {
InitialBroadcastAt: &b,
CreatedAt: b,
State: txmgrcommon.TxConfirmed,
- Meta: &md1_,
+ Meta: &md1SQL,
EncodedPayload: []byte{},
ChainID: chainID.ToInt(),
},
@@ -2080,7 +2080,7 @@ func TestStartingCountsV1(t *testing.T) {
InitialBroadcastAt: &b,
CreatedAt: b,
State: txmgrcommon.TxConfirmed,
- Meta: &md2_,
+ Meta: &md2SQL,
EncodedPayload: []byte{},
ChainID: chainID.ToInt(),
},
@@ -2092,7 +2092,7 @@ func TestStartingCountsV1(t *testing.T) {
InitialBroadcastAt: &b,
CreatedAt: b,
State: txmgrcommon.TxConfirmed,
- Meta: &md2_,
+ Meta: &md2SQL,
EncodedPayload: []byte{},
ChainID: chainID.ToInt(),
},
@@ -2105,6 +2105,7 @@ func TestStartingCountsV1(t *testing.T) {
RequestID: &reqID3,
})
require.NoError(t, err2)
+ mdSQL := sqlutil.JSON(md)
newNonce := evmtypes.Nonce(i + 1)
unconfirmedTxes = append(unconfirmedTxes, txmgr.Tx{
Sequence: &newNonce,
@@ -2114,7 +2115,7 @@ func TestStartingCountsV1(t *testing.T) {
State: txmgrcommon.TxUnconfirmed,
BroadcastAt: &b,
InitialBroadcastAt: &b,
- Meta: (*datatypes.JSON)(&md),
+ Meta: &mdSQL,
EncodedPayload: []byte{},
ChainID: chainID.ToInt(),
})
diff --git a/core/services/vrf/v2/listener_v2_test.go b/core/services/vrf/v2/listener_v2_test.go
index 17615feb63..513aa01ef6 100644
--- a/core/services/vrf/v2/listener_v2_test.go
+++ b/core/services/vrf/v2/listener_v2_test.go
@@ -17,9 +17,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
- "github.com/smartcontractkit/chainlink/v2/core/services/pg/datatypes"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm"
@@ -77,7 +77,7 @@ func addEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, from common.Address, s
RequestTxHash: &reqTxHash,
})
require.NoError(t, err)
- meta := datatypes.JSON(b)
+ meta := sqlutil.JSON(b)
tx := &txmgr.Tx{
FromAddress: from,
ToAddress: from,
@@ -103,7 +103,7 @@ func addConfirmedEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, from common.A
GlobalSubID: txMetaGlobalSubID,
})
require.NoError(t, err)
- meta := datatypes.JSON(b)
+ meta := sqlutil.JSON(b)
now := time.Now()
tx := &txmgr.Tx{
@@ -135,7 +135,7 @@ func addEthTxNativePayment(t *testing.T, txStore txmgr.TestEvmTxStore, from comm
RequestTxHash: &reqTxHash,
})
require.NoError(t, err)
- meta := datatypes.JSON(b)
+ meta := sqlutil.JSON(b)
tx := &txmgr.Tx{
FromAddress: from,
ToAddress: from,
@@ -161,7 +161,7 @@ func addConfirmedEthTxNativePayment(t *testing.T, txStore txmgr.TestEvmTxStore,
GlobalSubID: txMetaGlobalSubID,
})
require.NoError(t, err)
- meta := datatypes.JSON(b)
+ meta := sqlutil.JSON(b)
now := time.Now()
tx := &txmgr.Tx{
Sequence: &nonce,
diff --git a/go.mod b/go.mod
index b3bdeb74cf..e6bb7347ff 100644
--- a/go.mod
+++ b/go.mod
@@ -66,7 +66,7 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459
- github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
+ github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664
diff --git a/go.sum b/go.sum
index bdfbe2107e..24d662390d 100644
--- a/go.sum
+++ b/go.sum
@@ -1465,8 +1465,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459 h1:hJhuShYv9eUQxHJQdOmyEymVmApOrICrQdOY7kKQ5Io=
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k=
-github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
-github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3 h1:cyA1aW1PYrOLZAMaSmuH7U99QBTfrF59s+6uDxQgOr0=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542/go.mod h1:EpvRoycRD+kniYlz+pCpRT5e+fmPm0mSD/vmND+0oMg=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 h1:D7yb4kgNGVAiD5lFYqm/LW8d5jU66TXyYvSskDiW9yg=
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index cdd42deda7..d626b38cca 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -23,7 +23,7 @@ require (
github.com/segmentio/ksuid v1.0.4
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459
- github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e
+ github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3
github.com/smartcontractkit/chainlink-testing-framework v1.19.1
github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 08b772c9ce..b8a84de26e 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -2369,8 +2369,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv
github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M=
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459 h1:hJhuShYv9eUQxHJQdOmyEymVmApOrICrQdOY7kKQ5Io=
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k=
-github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e h1:Fsx5IJDD14wdCAe2lEI1xgztIvzjiE2iVHvYzg/grew=
-github.com/smartcontractkit/chainlink-common v0.1.7-0.20231117021201-6814387d8d3e/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3 h1:cyA1aW1PYrOLZAMaSmuH7U99QBTfrF59s+6uDxQgOr0=
+github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3/go.mod h1:Hrru9i7n+WEYyW2aIt3/YGPhxLX+HEGWnhk3yVXeDF8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542 h1:oewYJtdRkJKUHCNDCj5C2LQe6Oq6qy975g931nfG0cc=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231117191236-12eab01a4542/go.mod h1:EpvRoycRD+kniYlz+pCpRT5e+fmPm0mSD/vmND+0oMg=
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1 h1:D7yb4kgNGVAiD5lFYqm/LW8d5jU66TXyYvSskDiW9yg=
From f7c254bc9c7320506536b1c23bd5005476e17ee7 Mon Sep 17 00:00:00 2001
From: cfal
Date: Wed, 22 Nov 2023 20:12:32 +0900
Subject: [PATCH 189/327] core/cmd/shell.go: pass DB and QConfig fields to
CosmosFactoryConfig (#11360)
---
core/cmd/shell.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 52c9090736..b82bd85e3e 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -176,6 +176,8 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G
cosmosCfg := chainlink.CosmosFactoryConfig{
Keystore: keyStore.Cosmos(),
TOMLConfigs: cfg.CosmosConfigs(),
+ DB: db,
+ QConfig: cfg.Database(),
}
initOps = append(initOps, chainlink.InitCosmos(ctx, relayerFactory, cosmosCfg))
}
From 60cb43a46b8d9d1eb7d3820687aa911249228bde Mon Sep 17 00:00:00 2001
From: Adam Hamrick
Date: Wed, 22 Nov 2023 11:09:29 -0500
Subject: [PATCH 190/327] Update CTF (#11367)
---
integration-tests/go.mod | 14 ++++++++------
integration-tests/go.sum | 21 ++++++++++++---------
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index d626b38cca..ba90493d29 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -24,12 +24,12 @@ require (
github.com/slack-go/slack v0.12.2
github.com/smartcontractkit/chainlink-automation v1.0.0-alpha.0.0.20231120164534-d4cab696c459
github.com/smartcontractkit/chainlink-common v0.1.7-0.20231121180428-d7f28e91ccc3
- github.com/smartcontractkit/chainlink-testing-framework v1.19.1
+ github.com/smartcontractkit/chainlink-testing-framework v1.19.4
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-20231107151413-13e0202ae8d7
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1
- github.com/smartcontractkit/wasp v0.3.0
+ github.com/smartcontractkit/wasp v0.3.6
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.4
github.com/testcontainers/testcontainers-go v0.23.0
@@ -85,6 +85,7 @@ require (
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee // indirect
+ github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect
github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
@@ -205,7 +206,7 @@ require (
github.com/gosimple/slug v1.13.1 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/grafana/dskit v0.0.0-20230201083518-528d8a7d52f2 // indirect
- github.com/grafana/loki v1.6.2-0.20230403212622-90888a0cc737 // indirect
+ github.com/grafana/loki v1.6.2-0.20231017135925-990ac685e6a6 // indirect
github.com/grafana/loki/pkg/push v0.0.0-20230127102416-571f88bc5765 // indirect
github.com/grafana/pyroscope-go v1.0.4 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect
@@ -360,6 +361,7 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/otiai10/copy v1.14.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
+ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
@@ -381,7 +383,7 @@ require (
github.com/russross/blackfriday v1.6.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
- github.com/sercand/kuberesolver v2.4.0+incompatible // indirect
+ github.com/sercand/kuberesolver/v4 v4.0.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v3 v3.23.9 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
@@ -420,7 +422,7 @@ require (
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect
github.com/valyala/fastjson v1.4.1 // indirect
- github.com/weaveworks/common v0.0.0-20221201103051-7c2720a9024d // indirect
+ github.com/weaveworks/common v0.0.0-20230411130259-f7d83a041205 // indirect
github.com/weaveworks/promrus v1.2.0 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect
@@ -513,5 +515,5 @@ replace (
github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f
github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.43.1-0.20230327151049-211ae4f1f0a2
- github.com/sercand/kuberesolver v2.4.0+incompatible => github.com/sercand/kuberesolver/v5 v5.1.1
+ github.com/sercand/kuberesolver/v4 => github.com/sercand/kuberesolver/v5 v5.1.1
)
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index b8a84de26e..849df2afca 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -721,6 +721,8 @@ github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee h1:BnPxIde0gjtTnc9Er7cxvBk8DHLWhEux0SxayC8dP6I=
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
+github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g=
+github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE=
github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0=
github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
@@ -1360,8 +1362,8 @@ github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6
github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
github.com/grafana/dskit v0.0.0-20230201083518-528d8a7d52f2 h1:IOks+FXJ6iO/pfbaVEf4efNw+YzYBYNCkCabyrbkFTM=
github.com/grafana/dskit v0.0.0-20230201083518-528d8a7d52f2/go.mod h1:zj+5BNZAVmQafV583uLTAOzRr963KPdEm4d6NPmtbwg=
-github.com/grafana/loki v1.6.2-0.20230403212622-90888a0cc737 h1:o45+fZAYRtTjx+9fFml9LZxsCmLX65l39eWDgvdkIr0=
-github.com/grafana/loki v1.6.2-0.20230403212622-90888a0cc737/go.mod h1:kxNnWCr4EMobhndjy7a2Qpm7jkLPnJW2ariYvY77hLE=
+github.com/grafana/loki v1.6.2-0.20231017135925-990ac685e6a6 h1:V5PspEXlSlNh22sMyGkgfSOVVLTsSmhbmsp1VPt8Fdc=
+github.com/grafana/loki v1.6.2-0.20231017135925-990ac685e6a6/go.mod h1:+aWr7OBDuZMT+p0rKmLfW5saO2m3YOGBnt++IlgLhVk=
github.com/grafana/loki/pkg/push v0.0.0-20230127102416-571f88bc5765 h1:VXitROTlmZtLzvokNe8ZbUKpmwldM4Hy1zdNRO32jKU=
github.com/grafana/loki/pkg/push v0.0.0-20230127102416-571f88bc5765/go.mod h1:DhJMrd2QInI/1CNtTN43BZuTmkccdizW1jZ+F6aHkhY=
github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMHC7Bm0=
@@ -1377,7 +1379,6 @@ github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLt
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio=
@@ -2197,6 +2198,8 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
@@ -2377,8 +2380,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231117191230-aa6640f2edd1/go.mod h1:UfW7/PZKon+iDEHtrHOfvMnS5GfYOW/SdMZ6P97rPEk=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664 h1:yxaHuDTtj2xxtsR8b+LJw8xDvyr6v/F6GP3InsP4wPI=
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231117204155-b253a2f56664/go.mod h1:3Fa+HQTZ3R3fPC0hUqugvoo+NEeo8Y4J2WOnQfi7O34=
-github.com/smartcontractkit/chainlink-testing-framework v1.19.1 h1:MdGM5jIrBi858Cv7qzfl1Qon93YW8InohAlDQqFoIb4=
-github.com/smartcontractkit/chainlink-testing-framework v1.19.1/go.mod h1:zScXRqmvbyTFUooyLYrOp4+V/sFPUbFJNRc72YmnuIk=
+github.com/smartcontractkit/chainlink-testing-framework v1.19.4 h1:a5zG5k3MNbDBWiBdxF2cBLaMyB+WD0ROWPiZ0DVJQMc=
+github.com/smartcontractkit/chainlink-testing-framework v1.19.4/go.mod h1:+FVgkz6phTc+piVT57AcQfr3I8xvZgZ1lOpRPOu/dLQ=
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=
@@ -2391,8 +2394,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw=
-github.com/smartcontractkit/wasp v0.3.0 h1:mueeLvpb6HyGNwILxCOKShDR6q18plQn7Gb1j3G/Qkk=
-github.com/smartcontractkit/wasp v0.3.0/go.mod h1:skquNdMbKxIrHi5O8Kyukf66AaaXuEpEEaSTxfHbhak=
+github.com/smartcontractkit/wasp v0.3.6 h1:1TLWfrTzqZwNvyyoKzPZ8FLQat2lNz640eM+mMh2YxM=
+github.com/smartcontractkit/wasp v0.3.6/go.mod h1:L/cyUGfpaWxy/2twOVJLRt2mySJEIqGrFj9nyvRLpSo=
github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ=
github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -2530,8 +2533,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
-github.com/weaveworks/common v0.0.0-20221201103051-7c2720a9024d h1:9Z/HiqeGN+LOnmotAMpFEQjuXZ4AGAVFG0rC1laP5Go=
-github.com/weaveworks/common v0.0.0-20221201103051-7c2720a9024d/go.mod h1:Fnq3+U51tMkPRMC6Wr7zKGUeFFYX4YjNrNK50iU0fcE=
+github.com/weaveworks/common v0.0.0-20230411130259-f7d83a041205 h1:gjb7t9LCnRu14LHubyLIgrE+EYlAaREiPn/VknV7R3s=
+github.com/weaveworks/common v0.0.0-20230411130259-f7d83a041205/go.mod h1:O9wmSPNVSuqxzUZPFlHnPQ8xnyvx0qBnKGFfGbj95uY=
github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M=
github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
From 543d94633499d592c2cd44f7048912eb38f7bae6 Mon Sep 17 00:00:00 2001
From: Jordan Krage
Date: Wed, 22 Nov 2023 10:17:51 -0600
Subject: [PATCH 191/327] core/web: go:generate operator-ui assets (#11239)
---
.gitignore | 3 -
.goreleaser.develop.yaml | 2 -
GNUmakefile | 2 +-
core/web/assets/9f6d832ef97e8493764e.svg | 1 +
core/web/assets/9f6d832ef97e8493764e.svg.gz | Bin 0 -> 193 bytes
core/web/assets/ba8bbf16ebf8e1d05bef.svg | 1 +
core/web/assets/ba8bbf16ebf8e1d05bef.svg.gz | Bin 0 -> 1739 bytes
core/web/assets/index.html | 1 +
core/web/assets/index.html.gz | Bin 0 -> 420 bytes
core/web/assets/main.b0b6f79f7f4a94560e37.js | 187 ++++++++++++++++++
.../assets/main.b0b6f79f7f4a94560e37.js.gz | Bin 0 -> 1190421 bytes
core/web/middleware.go | 1 +
12 files changed, 192 insertions(+), 6 deletions(-)
create mode 100644 core/web/assets/9f6d832ef97e8493764e.svg
create mode 100644 core/web/assets/9f6d832ef97e8493764e.svg.gz
create mode 100644 core/web/assets/ba8bbf16ebf8e1d05bef.svg
create mode 100644 core/web/assets/ba8bbf16ebf8e1d05bef.svg.gz
create mode 100644 core/web/assets/index.html.gz
create mode 100644 core/web/assets/main.b0b6f79f7f4a94560e37.js
create mode 100644 core/web/assets/main.b0b6f79f7f4a94560e37.js.gz
diff --git a/.gitignore b/.gitignore
index 48e228eb83..3f016503a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,9 +55,6 @@ golangci-lint-output.txt
# can be left behind by tests
core/cmd/vrfkey1
-# left behind by webpack - compiled frontend assets
-core/web/assets
-
# Integration Tests
integration-tests/**/logs/
tests-*.xml
diff --git a/.goreleaser.develop.yaml b/.goreleaser.develop.yaml
index 53c927c9f9..2031249165 100644
--- a/.goreleaser.develop.yaml
+++ b/.goreleaser.develop.yaml
@@ -10,8 +10,6 @@ env:
before:
hooks:
- - go mod tidy
- - make operator-ui
- ./tools/bin/goreleaser_utils before_hook
# See https://goreleaser.com/customization/build/
diff --git a/GNUmakefile b/GNUmakefile
index 2801f94968..cb665498a3 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -79,7 +79,7 @@ docker-plugins:
.PHONY: operator-ui
operator-ui: ## Fetch the frontend
- ./operator_ui/install.sh
+ go generate ./core/web
.PHONY: abigen
abigen: ## Build & install abigen.
diff --git a/core/web/assets/9f6d832ef97e8493764e.svg b/core/web/assets/9f6d832ef97e8493764e.svg
new file mode 100644
index 0000000000..e35f1df284
--- /dev/null
+++ b/core/web/assets/9f6d832ef97e8493764e.svg
@@ -0,0 +1 @@
+
diff --git a/core/web/assets/9f6d832ef97e8493764e.svg.gz b/core/web/assets/9f6d832ef97e8493764e.svg.gz
new file mode 100644
index 0000000000000000000000000000000000000000..44cd870b0bbe539c0d37376c0006f03325f13e24
GIT binary patch
literal 193
zcmV;y06za8iwFP!0000212vC34}&lag!ldmE1hv34m4DRp);)PRo_xtP(cLo>ze@G
z?(?0`a?y_unBMNwTlO4=?#Q|K9z9|EeQ+g&;32_aeBJ!1oh%a|fDULt6K1R|y7Taa
zt7Ww`n1gVM28C2rE_o-SHkGRDgyK2+|0?+AM<`2YX_KeSc1
literal 0
HcmV?d00001
diff --git a/core/web/assets/ba8bbf16ebf8e1d05bef.svg b/core/web/assets/ba8bbf16ebf8e1d05bef.svg
new file mode 100644
index 0000000000..3ca546a8aa
--- /dev/null
+++ b/core/web/assets/ba8bbf16ebf8e1d05bef.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/core/web/assets/ba8bbf16ebf8e1d05bef.svg.gz b/core/web/assets/ba8bbf16ebf8e1d05bef.svg.gz
new file mode 100644
index 0000000000000000000000000000000000000000..7e4f235f1b9263b49c03bad9b2924a6355913d21
GIT binary patch
literal 1739
zcmV;+1~mB}iwFP!000021I1WNZxlxm{wpiz+S8t@eiMU4eDT3KA^G4-G+7&LX$*+9
z)}Sc=J>OS7yBI7M!Xc4GZ%x0d>Z@mSve~{_-CjLEI-fpWfA~X=R#(&gG`yYeu9vwL
z=04udZ#U16Ztm~jKRZ5tczEy+!N2?P=2*vZJjNAAtL^Re!*B0CK0g{)<4Q2S!kQn`
z(TkI->(`qXC!70E^YshAo;QR1_4;<6pZ%g!ny#i_|2{eHizml@>;3ILzFvN~|MT7S
z;c6u($9?AH{d9k`TF=u4!q`O+_xaK9ItHJLYt6^J9tRzLs7{jCG6eNGxgb6*B&KU~
zqtoO=aLtG8w0cPnr?kz3j4ohuJ&3PqC_Xg|xegL+#MV6xHtLKW?#0f9Qt+wZAkp{%
zgv_}pWKrTmV?J?H#<}c^!_8TFbIEhVckoh9HRHzYL?KLp$l@h90ap#lOYS622I*wS
zL8SQ_-D6ZPkB+~MUR7UsEu=fsqCQ>Z?5o^BL=6{>yw~cR3=pnC(NczF2rCipB(yP|
z6GSIyosx3VuMO~ph>sCQsW1_K+MqtPq4^Ys>TBp!@;L(2N{OP^2&xIpROFBfAp~3x
zDY75yECS=@3YlXWd`QF+=Au+a1wX7m^gF-5$)VLH!=rn4F2dV|POI)PNMoKshN^cVZZ*bL2f0wa%Nc#nJmv=a#g1buF
z0nzNxFczoASz@J883@v~)d4hd%eSCubLFkjT
zA4)+#gL}$dEL`7asZOJ>XDK6d>3K>BHMlwA2LVOK78qO6vlJ0p`Lm$_4YER*tu9D`
zcxS015D&4=5y{or6>FS}3`SJE%EG}^*J+f$lwakPsUE9EKL%9+$OASnr72z*+IcD^R<*~`GP%>Ba&DsoL-Akl;P}{0z
zTI3FdQAJwT8`Qf7=coZWU#w1%&zKqhjR`rIg;XxVM;akvo$XYw$s^Zmg))6ARZ6O|
z(9Ee!up>JI;1lWoU;>K^^Lp0HJNp?D$F(M8Cj4ZtGmj+S1D
zRS^KFk@!WC8BLhhyP9rob~Q~Gx|bq)gtHRfu?vAgOPl$&t7gg;NAp=>ai|kDHFcMA
z2(p;|D(jBB^=d<~N;g%TRJxW*`njxA;{|3
z=obwRQ6@O3?oP8sgbrvE3s~=s9O)*DCE*~lTHu7Pr#n`pE#vmgX19o2
z_&*;m)ud#yVTnOsM{2T;!}YOaZ9xJ%ZV}rEzHIv0*r7Jb<+FD~x;C(cFC@o{W<|^P
zEP0sS-#YfEK<>WPq*K82qHqbx`miTAvqi)E2P#=YfkQ-lH!<%jW7y~oKk!6o#>q&V
zM_5PO2-n(Am-31iH)Q?&{YW26N?2RHS3WImfRxNQro!CFzLrLOhYxS_1|QeSY03Y876$sE+efF5u9-35Us|h
z8F|1ZImaS9c@{oA+;Zm!FVcBnQt3N($9Yv?G&p#K1oKR!s1a==BGB0**r8F0ZT6!j
z4|EX5rzaJxip4%sQ9P$tp~piZkonOxg4Operator UIChainlink
\ No newline at end of file
diff --git a/core/web/assets/index.html.gz b/core/web/assets/index.html.gz
new file mode 100644
index 0000000000000000000000000000000000000000..24cc3068f6e66871c3c3479164b48ea3e892d6ee
GIT binary patch
literal 420
zcmV;V0bBkbiwFP!000021C^3bZ`3dl#lMQN#EEVk=(bC%I6YKCDiT7X^uTdqPc{bs
zi9EAu_uJzn+m(=z5QjMNi{I~!$8O%(WcWCu7&!R0IgJRmZ2~d~Ge9O}EuX%B+I*Di
zBu5CS<>c^rOqr!HDKf^g?Aci!w8hC8+$@s|7acqB8#3Tgzn>ZG*kk*3#0;FWczS5m
zDmC84Um~N|l7>Py2Ntftr5G~yS`N%3-6}-^%Fhy-!Eoim-n~>2S(S2KoEcSd-NAvA
zHYto5iQay=?^6!Ia{)`tpUA$@sM@Er_Xwk-su-0ay6Yi0f7IVnmpI*C*7e1&5Ak
zJ+@6uC;3M@h=^zfCxH<x2
literal 0
HcmV?d00001
diff --git a/core/web/assets/main.b0b6f79f7f4a94560e37.js b/core/web/assets/main.b0b6f79f7f4a94560e37.js
new file mode 100644
index 0000000000..6c9f23d1cc
--- /dev/null
+++ b/core/web/assets/main.b0b6f79f7f4a94560e37.js
@@ -0,0 +1,187 @@
+(()=>{var __webpack_modules__={23564(e,t,n){"use strict";n.d(t,{Jh:()=>u,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */ var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.default=e.exports,e.exports.__esModule=!0},37316(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.default=e.exports,e.exports.__esModule=!0},78585(e,t,n){var r=n(50008).default,i=n(81506);function a(e,t){return t&&("object"===r(t)||"function"==typeof t)?t:i(e)}e.exports=a,e.exports.default=e.exports,e.exports.__esModule=!0},99489(e){function t(n,r){return e.exports=t=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},e.exports.default=e.exports,e.exports.__esModule=!0,t(n,r)}e.exports=t,e.exports.default=e.exports,e.exports.__esModule=!0},319(e,t,n){var r=n(23646),i=n(46860),a=n(60379),o=n(98206);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.default=e.exports,e.exports.__esModule=!0},50008(e){function t(n){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?(e.exports=t=function(e){return typeof e},e.exports.default=e.exports,e.exports.__esModule=!0):(e.exports=t=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.default=e.exports,e.exports.__esModule=!0),t(n)}e.exports=t,e.exports.default=e.exports,e.exports.__esModule=!0},60379(e,t,n){var r=n(67228);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.default=e.exports,e.exports.__esModule=!0},98925(e,t,n){"use strict";let r=n(98633),i=n.g.Date;class a extends i{constructor(e){super(e),this.isDate=!0}toISOString(){return`${this.getUTCFullYear()}-${r(2,this.getUTCMonth()+1)}-${r(2,this.getUTCDate())}`}}e.exports=e=>{let t=new a(e);if(!isNaN(t))return t;throw TypeError("Invalid Datetime")}},86595(e,t,n){"use strict";let r=n(98633);class i extends Date{constructor(e){super(e+"Z"),this.isFloating=!0}toISOString(){let e=`${this.getUTCFullYear()}-${r(2,this.getUTCMonth()+1)}-${r(2,this.getUTCDate())}`,t=`${r(2,this.getUTCHours())}:${r(2,this.getUTCMinutes())}:${r(2,this.getUTCSeconds())}.${r(3,this.getUTCMilliseconds())}`;return`${e}T${t}`}}e.exports=e=>{let t=new i(e);if(!isNaN(t))return t;throw TypeError("Invalid Datetime")}},76114(e){"use strict";e.exports=e=>{let t=new Date(e);if(!isNaN(t))return t;throw TypeError("Invalid Datetime")}},99439(e,t,n){"use strict";let r=n(98633);class i extends Date{constructor(e){super(`0000-01-01T${e}Z`),this.isTime=!0}toISOString(){return`${r(2,this.getUTCHours())}:${r(2,this.getUTCMinutes())}:${r(2,this.getUTCSeconds())}.${r(3,this.getUTCMilliseconds())}`}}e.exports=e=>{let t=new i(e);if(!isNaN(t))return t;throw TypeError("Invalid Datetime")}},98633(e){"use strict";e.exports=(e,t)=>{for(t=String(t);t.length{let t=new TomlError(e.message);return t.code=e.code,t.wrapped=e,t},module.exports.TomlError=TomlError;let createDateTime=__webpack_require__(76114),createDateTimeFloat=__webpack_require__(86595),createDate=__webpack_require__(98925),createTime=__webpack_require__(99439),CTRL_I=9,CTRL_J=10,CTRL_M=13,CTRL_CHAR_BOUNDARY=31,CHAR_SP=32,CHAR_QUOT=34,CHAR_NUM=35,CHAR_APOS=39,CHAR_PLUS=43,CHAR_COMMA=44,CHAR_HYPHEN=45,CHAR_PERIOD=46,CHAR_0=48,CHAR_1=49,CHAR_7=55,CHAR_9=57,CHAR_COLON=58,CHAR_EQUALS=61,CHAR_A=65,CHAR_E=69,CHAR_F=70,CHAR_T=84,CHAR_U=85,CHAR_Z=90,CHAR_LOWBAR=95,CHAR_a=97,CHAR_b=98,CHAR_e=101,CHAR_f=102,CHAR_i=105,CHAR_l=108,CHAR_n=110,CHAR_o=111,CHAR_r=114,CHAR_s=115,CHAR_t=116,CHAR_u=117,CHAR_x=120,CHAR_z=122,CHAR_LCUB=123,CHAR_RCUB=125,CHAR_LSQB=91,CHAR_BSOL=92,CHAR_RSQB=93,CHAR_DEL=127,SURROGATE_FIRST=55296,SURROGATE_LAST=57343,escapes={[CHAR_b]:"\b",[CHAR_t]:" ",[CHAR_n]:"\n",[CHAR_f]:"\f",[CHAR_r]:"\r",[CHAR_QUOT]:'"',[CHAR_BSOL]:"\\"};function isDigit(e){return e>=CHAR_0&&e<=CHAR_9}function isHexit(e){return e>=CHAR_A&&e<=CHAR_F||e>=CHAR_a&&e<=CHAR_f||e>=CHAR_0&&e<=CHAR_9}function isBit(e){return e===CHAR_1||e===CHAR_0}function isOctit(e){return e>=CHAR_0&&e<=CHAR_7}function isAlphaNumQuoteHyphen(e){return e>=CHAR_A&&e<=CHAR_Z||e>=CHAR_a&&e<=CHAR_z||e>=CHAR_0&&e<=CHAR_9||e===CHAR_APOS||e===CHAR_QUOT||e===CHAR_LOWBAR||e===CHAR_HYPHEN}function isAlphaNumHyphen(e){return e>=CHAR_A&&e<=CHAR_Z||e>=CHAR_a&&e<=CHAR_z||e>=CHAR_0&&e<=CHAR_9||e===CHAR_LOWBAR||e===CHAR_HYPHEN}let _type=Symbol("type"),_declared=Symbol("declared"),hasOwnProperty=Object.prototype.hasOwnProperty,defineProperty=Object.defineProperty,descriptor={configurable:!0,enumerable:!0,writable:!0,value:void 0};function hasKey(e,t){return!!hasOwnProperty.call(e,t)||("__proto__"===t&&defineProperty(e,"__proto__",descriptor),!1)}let INLINE_TABLE=Symbol("inline-table");function InlineTable(){return Object.defineProperties({},{[_type]:{value:INLINE_TABLE}})}function isInlineTable(e){return null!==e&&"object"==typeof e&&e[_type]===INLINE_TABLE}let TABLE=Symbol("table");function Table(){return Object.defineProperties({},{[_type]:{value:TABLE},[_declared]:{value:!1,writable:!0}})}function isTable(e){return null!==e&&"object"==typeof e&&e[_type]===TABLE}let _contentType=Symbol("content-type"),INLINE_LIST=Symbol("inline-list");function InlineList(e){return Object.defineProperties([],{[_type]:{value:INLINE_LIST},[_contentType]:{value:e}})}function isInlineList(e){return null!==e&&"object"==typeof e&&e[_type]===INLINE_LIST}let LIST=Symbol("list");function List(){return Object.defineProperties([],{[_type]:{value:LIST}})}function isList(e){return null!==e&&"object"==typeof e&&e[_type]===LIST}let _custom;try{let utilInspect=eval("require('util').inspect");_custom=utilInspect.custom}catch(_){}let _inspect=_custom||"inspect";class BoxedBigInt{constructor(e){try{this.value=__webpack_require__.g.BigInt.asIntN(64,e)}catch(t){this.value=null}Object.defineProperty(this,_type,{value:INTEGER})}isNaN(){return null===this.value}toString(){return String(this.value)}[_inspect](){return`[BigInt: ${this.toString()}]}`}valueOf(){return this.value}}let INTEGER=Symbol("integer");function Integer(e){let t=Number(e);return(Object.is(t,-0)&&(t=0),__webpack_require__.g.BigInt&&!Number.isSafeInteger(t))?new BoxedBigInt(e):Object.defineProperties(new Number(t),{isNaN:{value:function(){return isNaN(this)}},[_type]:{value:INTEGER},[_inspect]:{value:()=>`[Integer: ${e}]`}})}function isInteger(e){return null!==e&&"object"==typeof e&&e[_type]===INTEGER}let FLOAT=Symbol("float");function Float(e){return Object.defineProperties(new Number(e),{[_type]:{value:FLOAT},[_inspect]:{value:()=>`[Float: ${e}]`}})}function isFloat(e){return null!==e&&"object"==typeof e&&e[_type]===FLOAT}function tomlType(e){let t=typeof e;if("object"===t){if(null===e)return"null";if(e instanceof Date)return"datetime";if(_type in e)switch(e[_type]){case INLINE_TABLE:return"inline-table";case INLINE_LIST:return"inline-list";case TABLE:return"table";case LIST:return"list";case FLOAT:return"float";case INTEGER:return"integer"}}return t}function makeParserClass(e){class t extends e{constructor(){super(),this.ctx=this.obj=Table()}atEndOfWord(){return this.char===CHAR_NUM||this.char===CTRL_I||this.char===CHAR_SP||this.atEndOfLine()}atEndOfLine(){return this.char===e.END||this.char===CTRL_J||this.char===CTRL_M}parseStart(){if(this.char===e.END)return null;if(this.char===CHAR_LSQB)return this.call(this.parseTableOrList);if(this.char===CHAR_NUM)return this.call(this.parseComment);if(this.char===CTRL_J||this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M)return null;if(isAlphaNumQuoteHyphen(this.char))return this.callNow(this.parseAssignStatement);else throw this.error(new TomlError(`Unknown character "${this.char}"`))}parseWhitespaceToEOL(){if(this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M)return null;if(this.char===CHAR_NUM)return this.goto(this.parseComment);if(this.char===e.END||this.char===CTRL_J)return this.return();throw this.error(new TomlError("Unexpected character, expected only whitespace or comments till end of line"))}parseAssignStatement(){return this.callNow(this.parseAssign,this.recordAssignStatement)}recordAssignStatement(e){let t=this.ctx,n=e.key.pop();for(let r of e.key){if(hasKey(t,r)&&!isTable(t[r]))throw this.error(new TomlError("Can't redefine existing key"));t=t[r]=t[r]||Table()}if(hasKey(t,n))throw this.error(new TomlError("Can't redefine existing key"));return t[_declared]=!0,isInteger(e.value)||isFloat(e.value)?t[n]=e.value.valueOf():t[n]=e.value,this.goto(this.parseWhitespaceToEOL)}parseAssign(){return this.callNow(this.parseKeyword,this.recordAssignKeyword)}recordAssignKeyword(e){return this.state.resultTable?this.state.resultTable.push(e):this.state.resultTable=[e],this.goto(this.parseAssignKeywordPreDot)}parseAssignKeywordPreDot(){return this.char===CHAR_PERIOD?this.next(this.parseAssignKeywordPostDot):this.char!==CHAR_SP&&this.char!==CTRL_I?this.goto(this.parseAssignEqual):void 0}parseAssignKeywordPostDot(){if(this.char!==CHAR_SP&&this.char!==CTRL_I)return this.callNow(this.parseKeyword,this.recordAssignKeyword)}parseAssignEqual(){if(this.char===CHAR_EQUALS)return this.next(this.parseAssignPreValue);throw this.error(new TomlError('Invalid character, expected "="'))}parseAssignPreValue(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseValue,this.recordAssignValue)}recordAssignValue(e){return this.returnNow({key:this.state.resultTable,value:e})}parseComment(){do{if(this.char===e.END||this.char===CTRL_J)return this.return();if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("comments")}while(this.nextChar())}parseTableOrList(){if(this.char!==CHAR_LSQB)return this.goto(this.parseTable);this.next(this.parseList)}parseTable(){return this.ctx=this.obj,this.goto(this.parseTableNext)}parseTableNext(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseKeyword,this.parseTableMore)}parseTableMore(e){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CHAR_RSQB){if(hasKey(this.ctx,e)&&(!isTable(this.ctx[e])||this.ctx[e][_declared]))throw this.error(new TomlError("Can't redefine existing key"));return this.ctx=this.ctx[e]=this.ctx[e]||Table(),this.ctx[_declared]=!0,this.next(this.parseWhitespaceToEOL)}if(this.char===CHAR_PERIOD){if(hasKey(this.ctx,e)){if(isTable(this.ctx[e]))this.ctx=this.ctx[e];else if(isList(this.ctx[e]))this.ctx=this.ctx[e][this.ctx[e].length-1];else throw this.error(new TomlError("Can't redefine existing key"))}else this.ctx=this.ctx[e]=Table();return this.next(this.parseTableNext)}throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"))}parseList(){return this.ctx=this.obj,this.goto(this.parseListNext)}parseListNext(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseKeyword,this.parseListMore)}parseListMore(e){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CHAR_RSQB){if(hasKey(this.ctx,e)||(this.ctx[e]=List()),isInlineList(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline array"));if(isList(this.ctx[e])){let t=Table();this.ctx[e].push(t),this.ctx=t}else throw this.error(new TomlError("Can't redefine an existing key"));return this.next(this.parseListEnd)}if(this.char===CHAR_PERIOD){if(hasKey(this.ctx,e)){if(isInlineList(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline array"));if(isInlineTable(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline table"));else if(isList(this.ctx[e]))this.ctx=this.ctx[e][this.ctx[e].length-1];else if(isTable(this.ctx[e]))this.ctx=this.ctx[e];else throw this.error(new TomlError("Can't redefine an existing key"))}else this.ctx=this.ctx[e]=Table();return this.next(this.parseListNext)}throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"))}parseListEnd(e){if(this.char===CHAR_RSQB)return this.next(this.parseWhitespaceToEOL);throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"))}parseValue(){if(this.char===e.END)throw this.error(new TomlError("Key without value"));if(this.char===CHAR_QUOT)return this.next(this.parseDoubleString);if(this.char===CHAR_APOS)return this.next(this.parseSingleString);if(this.char===CHAR_HYPHEN||this.char===CHAR_PLUS)return this.goto(this.parseNumberSign);if(this.char===CHAR_i)return this.next(this.parseInf);if(this.char===CHAR_n)return this.next(this.parseNan);if(isDigit(this.char))return this.goto(this.parseNumberOrDateTime);else if(this.char===CHAR_t||this.char===CHAR_f)return this.goto(this.parseBoolean);else if(this.char===CHAR_LSQB)return this.call(this.parseInlineList,this.recordValue);else if(this.char===CHAR_LCUB)return this.call(this.parseInlineTable,this.recordValue);else throw this.error(new TomlError("Unexpected character, expecting string, number, datetime, boolean, inline array or inline table"))}recordValue(e){return this.returnNow(e)}parseInf(){if(this.char===CHAR_n)return this.next(this.parseInf2);throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'))}parseInf2(){if(this.char===CHAR_f)return"-"===this.state.buf?this.return(-1/0):this.return(1/0);throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'))}parseNan(){if(this.char===CHAR_a)return this.next(this.parseNan2);throw this.error(new TomlError('Unexpected character, expected "nan"'))}parseNan2(){if(this.char===CHAR_n)return this.return(NaN);throw this.error(new TomlError('Unexpected character, expected "nan"'))}parseKeyword(){return this.char===CHAR_QUOT?this.next(this.parseBasicString):this.char===CHAR_APOS?this.next(this.parseLiteralString):this.goto(this.parseBareKey)}parseBareKey(){do{if(this.char===e.END)throw this.error(new TomlError("Key ended without value"));if(isAlphaNumHyphen(this.char))this.consume();else if(0!==this.state.buf.length)return this.returnNow();else throw this.error(new TomlError("Empty bare keys are not allowed"))}while(this.nextChar())}parseSingleString(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiStringMaybe):this.goto(this.parseLiteralString)}parseLiteralString(){do{if(this.char===CHAR_APOS)return this.return();if(this.atEndOfLine())throw this.error(new TomlError("Unterminated string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("strings");else this.consume()}while(this.nextChar())}parseLiteralMultiStringMaybe(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiString):this.returnNow()}parseLiteralMultiString(){return this.char===CTRL_M?null:this.char===CTRL_J?this.next(this.parseLiteralMultiStringContent):this.goto(this.parseLiteralMultiStringContent)}parseLiteralMultiStringContent(){do{if(this.char===CHAR_APOS)return this.next(this.parseLiteralMultiEnd);if(this.char===e.END)throw this.error(new TomlError("Unterminated multi-line string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I&&this.char!==CTRL_J&&this.char!==CTRL_M)throw this.errorControlCharIn("strings");else this.consume()}while(this.nextChar())}parseLiteralMultiEnd(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiEnd2):(this.state.buf+="'",this.goto(this.parseLiteralMultiStringContent))}parseLiteralMultiEnd2(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiEnd3):(this.state.buf+="''",this.goto(this.parseLiteralMultiStringContent))}parseLiteralMultiEnd3(){return this.char===CHAR_APOS?(this.state.buf+="'",this.next(this.parseLiteralMultiEnd4)):this.returnNow()}parseLiteralMultiEnd4(){return this.char===CHAR_APOS?(this.state.buf+="'",this.return()):this.returnNow()}parseDoubleString(){return this.char===CHAR_QUOT?this.next(this.parseMultiStringMaybe):this.goto(this.parseBasicString)}parseBasicString(){do{if(this.char===CHAR_BSOL)return this.call(this.parseEscape,this.recordEscapeReplacement);if(this.char===CHAR_QUOT)return this.return();if(this.atEndOfLine())throw this.error(new TomlError("Unterminated string"));else if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("strings");else this.consume()}while(this.nextChar())}recordEscapeReplacement(e){return this.state.buf+=e,this.goto(this.parseBasicString)}parseMultiStringMaybe(){return this.char===CHAR_QUOT?this.next(this.parseMultiString):this.returnNow()}parseMultiString(){return this.char===CTRL_M?null:this.char===CTRL_J?this.next(this.parseMultiStringContent):this.goto(this.parseMultiStringContent)}parseMultiStringContent(){do{if(this.char===CHAR_BSOL)return this.call(this.parseMultiEscape,this.recordMultiEscapeReplacement);if(this.char===CHAR_QUOT)return this.next(this.parseMultiEnd);if(this.char===e.END)throw this.error(new TomlError("Unterminated multi-line string"));else if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I&&this.char!==CTRL_J&&this.char!==CTRL_M)throw this.errorControlCharIn("strings");else this.consume()}while(this.nextChar())}errorControlCharIn(e){let t="\\u00";return this.char<16&&(t+="0"),t+=this.char.toString(16),this.error(new TomlError(`Control characters (codes < 0x1f and 0x7f) are not allowed in ${e}, use ${t} instead`))}recordMultiEscapeReplacement(e){return this.state.buf+=e,this.goto(this.parseMultiStringContent)}parseMultiEnd(){return this.char===CHAR_QUOT?this.next(this.parseMultiEnd2):(this.state.buf+='"',this.goto(this.parseMultiStringContent))}parseMultiEnd2(){return this.char===CHAR_QUOT?this.next(this.parseMultiEnd3):(this.state.buf+='""',this.goto(this.parseMultiStringContent))}parseMultiEnd3(){return this.char===CHAR_QUOT?(this.state.buf+='"',this.next(this.parseMultiEnd4)):this.returnNow()}parseMultiEnd4(){return this.char===CHAR_QUOT?(this.state.buf+='"',this.return()):this.returnNow()}parseMultiEscape(){return this.char===CTRL_M||this.char===CTRL_J?this.next(this.parseMultiTrim):this.char===CHAR_SP||this.char===CTRL_I?this.next(this.parsePreMultiTrim):this.goto(this.parseEscape)}parsePreMultiTrim(){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CTRL_M||this.char===CTRL_J)return this.next(this.parseMultiTrim);throw this.error(new TomlError("Can't escape whitespace"))}parseMultiTrim(){return this.char===CTRL_J||this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M?null:this.returnNow()}parseEscape(){if(this.char in escapes)return this.return(escapes[this.char]);if(this.char===CHAR_u)return this.call(this.parseSmallUnicode,this.parseUnicodeReturn);if(this.char===CHAR_U)return this.call(this.parseLargeUnicode,this.parseUnicodeReturn);throw this.error(new TomlError("Unknown escape character: "+this.char))}parseUnicodeReturn(e){try{let t=parseInt(e,16);if(t>=SURROGATE_FIRST&&t<=SURROGATE_LAST)throw this.error(new TomlError("Invalid unicode, character in range 0xD800 - 0xDFFF is reserved"));return this.returnNow(String.fromCodePoint(t))}catch(n){throw this.error(TomlError.wrap(n))}}parseSmallUnicode(){if(isHexit(this.char)){if(this.consume(),this.state.buf.length>=4)return this.return()}else throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"))}parseLargeUnicode(){if(isHexit(this.char)){if(this.consume(),this.state.buf.length>=8)return this.return()}else throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"))}parseNumberSign(){return this.consume(),this.next(this.parseMaybeSignedInfOrNan)}parseMaybeSignedInfOrNan(){return this.char===CHAR_i?this.next(this.parseInf):this.char===CHAR_n?this.next(this.parseNan):this.callNow(this.parseNoUnder,this.parseNumberIntegerStart)}parseNumberIntegerStart(){return this.char===CHAR_0?(this.consume(),this.next(this.parseNumberIntegerExponentOrDecimal)):this.goto(this.parseNumberInteger)}parseNumberIntegerExponentOrDecimal(){return this.char===CHAR_PERIOD?(this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat)):this.char===CHAR_E||this.char===CHAR_e?(this.consume(),this.next(this.parseNumberExponentSign)):this.returnNow(Integer(this.state.buf))}parseNumberInteger(){if(isDigit(this.char))this.consume();else{if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnder);if(this.char===CHAR_E||this.char===CHAR_e)return this.consume(),this.next(this.parseNumberExponentSign);if(this.char===CHAR_PERIOD)return this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat);let e=Integer(this.state.buf);if(!e.isNaN())return this.returnNow(e);throw this.error(new TomlError("Invalid number"))}}parseNoUnder(){if(this.char===CHAR_LOWBAR||this.char===CHAR_PERIOD||this.char===CHAR_E||this.char===CHAR_e)throw this.error(new TomlError("Unexpected character, expected digit"));if(this.atEndOfWord())throw this.error(new TomlError("Incomplete number"));return this.returnNow()}parseNoUnderHexOctBinLiteral(){if(this.char===CHAR_LOWBAR||this.char===CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected digit"));if(this.atEndOfWord())throw this.error(new TomlError("Incomplete number"));return this.returnNow()}parseNumberFloat(){if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnder,this.parseNumberFloat);if(isDigit(this.char))this.consume();else if(this.char===CHAR_E||this.char===CHAR_e)return this.consume(),this.next(this.parseNumberExponentSign);else return this.returnNow(Float(this.state.buf))}parseNumberExponentSign(){if(isDigit(this.char))return this.goto(this.parseNumberExponent);if(this.char===CHAR_HYPHEN||this.char===CHAR_PLUS)this.consume(),this.call(this.parseNoUnder,this.parseNumberExponent);else throw this.error(new TomlError("Unexpected character, expected -, + or digit"))}parseNumberExponent(){if(isDigit(this.char))this.consume();else if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnder);else return this.returnNow(Float(this.state.buf))}parseNumberOrDateTime(){return this.char===CHAR_0?(this.consume(),this.next(this.parseNumberBaseOrDateTime)):this.goto(this.parseNumberOrDateTimeOnly)}parseNumberOrDateTimeOnly(){if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnder,this.parseNumberInteger);if(isDigit(this.char))this.consume(),this.state.buf.length>4&&this.next(this.parseNumberInteger);else if(this.char===CHAR_E||this.char===CHAR_e)return this.consume(),this.next(this.parseNumberExponentSign);else if(this.char===CHAR_PERIOD)return this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat);else if(this.char===CHAR_HYPHEN)return this.goto(this.parseDateTime);else if(this.char===CHAR_COLON)return this.goto(this.parseOnlyTimeHour);else return this.returnNow(Integer(this.state.buf))}parseDateTimeOnly(){if(this.state.buf.length<4){if(isDigit(this.char))return this.consume();if(this.char===CHAR_COLON)return this.goto(this.parseOnlyTimeHour);throw this.error(new TomlError("Expected digit while parsing year part of a date"))}if(this.char===CHAR_HYPHEN)return this.goto(this.parseDateTime);throw this.error(new TomlError("Expected hyphen (-) while parsing year part of date"))}parseNumberBaseOrDateTime(){if(this.char===CHAR_b)return this.consume(),this.call(this.parseNoUnderHexOctBinLiteral,this.parseIntegerBin);if(this.char===CHAR_o)return this.consume(),this.call(this.parseNoUnderHexOctBinLiteral,this.parseIntegerOct);if(this.char===CHAR_x)return this.consume(),this.call(this.parseNoUnderHexOctBinLiteral,this.parseIntegerHex);if(this.char===CHAR_PERIOD)return this.goto(this.parseNumberInteger);if(isDigit(this.char))return this.goto(this.parseDateTimeOnly);else return this.returnNow(Integer(this.state.buf))}parseIntegerHex(){if(isHexit(this.char))this.consume();else{if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnderHexOctBinLiteral);let e=Integer(this.state.buf);if(!e.isNaN())return this.returnNow(e);throw this.error(new TomlError("Invalid number"))}}parseIntegerOct(){if(isOctit(this.char))this.consume();else{if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnderHexOctBinLiteral);let e=Integer(this.state.buf);if(!e.isNaN())return this.returnNow(e);throw this.error(new TomlError("Invalid number"))}}parseIntegerBin(){if(isBit(this.char))this.consume();else{if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnderHexOctBinLiteral);let e=Integer(this.state.buf);if(!e.isNaN())return this.returnNow(e);throw this.error(new TomlError("Invalid number"))}}parseDateTime(){if(this.state.buf.length<4)throw this.error(new TomlError("Years less than 1000 must be zero padded to four characters"));return this.state.result=this.state.buf,this.state.buf="",this.next(this.parseDateMonth)}parseDateMonth(){if(this.char===CHAR_HYPHEN){if(this.state.buf.length<2)throw this.error(new TomlError("Months less than 10 must be zero padded to two characters"));return this.state.result+="-"+this.state.buf,this.state.buf="",this.next(this.parseDateDay)}if(isDigit(this.char))this.consume();else throw this.error(new TomlError("Incomplete datetime"))}parseDateDay(){if(this.char===CHAR_T||this.char===CHAR_SP){if(this.state.buf.length<2)throw this.error(new TomlError("Days less than 10 must be zero padded to two characters"));return this.state.result+="-"+this.state.buf,this.state.buf="",this.next(this.parseStartTimeHour)}if(this.atEndOfWord())return this.returnNow(createDate(this.state.result+"-"+this.state.buf));if(isDigit(this.char))this.consume();else throw this.error(new TomlError("Incomplete datetime"))}parseStartTimeHour(){return this.atEndOfWord()?this.returnNow(createDate(this.state.result)):this.goto(this.parseTimeHour)}parseTimeHour(){if(this.char===CHAR_COLON){if(this.state.buf.length<2)throw this.error(new TomlError("Hours less than 10 must be zero padded to two characters"));return this.state.result+="T"+this.state.buf,this.state.buf="",this.next(this.parseTimeMin)}if(isDigit(this.char))this.consume();else throw this.error(new TomlError("Incomplete datetime"))}parseTimeMin(){if(this.state.buf.length<2&&isDigit(this.char))this.consume();else if(2===this.state.buf.length&&this.char===CHAR_COLON)return this.state.result+=":"+this.state.buf,this.state.buf="",this.next(this.parseTimeSec);else throw this.error(new TomlError("Incomplete datetime"))}parseTimeSec(){if(isDigit(this.char)){if(this.consume(),2===this.state.buf.length)return this.state.result+=":"+this.state.buf,this.state.buf="",this.next(this.parseTimeZoneOrFraction)}else throw this.error(new TomlError("Incomplete datetime"))}parseOnlyTimeHour(){if(this.char===CHAR_COLON){if(this.state.buf.length<2)throw this.error(new TomlError("Hours less than 10 must be zero padded to two characters"));return this.state.result=this.state.buf,this.state.buf="",this.next(this.parseOnlyTimeMin)}throw this.error(new TomlError("Incomplete time"))}parseOnlyTimeMin(){if(this.state.buf.length<2&&isDigit(this.char))this.consume();else if(2===this.state.buf.length&&this.char===CHAR_COLON)return this.state.result+=":"+this.state.buf,this.state.buf="",this.next(this.parseOnlyTimeSec);else throw this.error(new TomlError("Incomplete time"))}parseOnlyTimeSec(){if(isDigit(this.char)){if(this.consume(),2===this.state.buf.length)return this.next(this.parseOnlyTimeFractionMaybe)}else throw this.error(new TomlError("Incomplete time"))}parseOnlyTimeFractionMaybe(){if(this.state.result+=":"+this.state.buf,this.char!==CHAR_PERIOD)return this.return(createTime(this.state.result));this.state.buf="",this.next(this.parseOnlyTimeFraction)}parseOnlyTimeFraction(){if(isDigit(this.char))this.consume();else if(this.atEndOfWord()){if(0===this.state.buf.length)throw this.error(new TomlError("Expected digit in milliseconds"));return this.returnNow(createTime(this.state.result+"."+this.state.buf))}else throw this.error(new TomlError("Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z"))}parseTimeZoneOrFraction(){if(this.char===CHAR_PERIOD)this.consume(),this.next(this.parseDateTimeFraction);else if(this.char===CHAR_HYPHEN||this.char===CHAR_PLUS)this.consume(),this.next(this.parseTimeZoneHour);else if(this.char===CHAR_Z)return this.consume(),this.return(createDateTime(this.state.result+this.state.buf));else if(this.atEndOfWord())return this.returnNow(createDateTimeFloat(this.state.result+this.state.buf));else throw this.error(new TomlError("Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z"))}parseDateTimeFraction(){if(isDigit(this.char))this.consume();else if(1===this.state.buf.length)throw this.error(new TomlError("Expected digit in milliseconds"));else if(this.char===CHAR_HYPHEN||this.char===CHAR_PLUS)this.consume(),this.next(this.parseTimeZoneHour);else if(this.char===CHAR_Z)return this.consume(),this.return(createDateTime(this.state.result+this.state.buf));else if(this.atEndOfWord())return this.returnNow(createDateTimeFloat(this.state.result+this.state.buf));else throw this.error(new TomlError("Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z"))}parseTimeZoneHour(){if(isDigit(this.char)){if(this.consume(),/\d\d$/.test(this.state.buf))return this.next(this.parseTimeZoneSep)}else throw this.error(new TomlError("Unexpected character in datetime, expected digit"))}parseTimeZoneSep(){if(this.char===CHAR_COLON)this.consume(),this.next(this.parseTimeZoneMin);else throw this.error(new TomlError("Unexpected character in datetime, expected colon"))}parseTimeZoneMin(){if(isDigit(this.char)){if(this.consume(),/\d\d$/.test(this.state.buf))return this.return(createDateTime(this.state.result+this.state.buf))}else throw this.error(new TomlError("Unexpected character in datetime, expected digit"))}parseBoolean(){return this.char===CHAR_t?(this.consume(),this.next(this.parseTrue_r)):this.char===CHAR_f?(this.consume(),this.next(this.parseFalse_a)):void 0}parseTrue_r(){if(this.char===CHAR_r)return this.consume(),this.next(this.parseTrue_u);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseTrue_u(){if(this.char===CHAR_u)return this.consume(),this.next(this.parseTrue_e);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseTrue_e(){if(this.char===CHAR_e)return this.return(!0);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseFalse_a(){if(this.char===CHAR_a)return this.consume(),this.next(this.parseFalse_l);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseFalse_l(){if(this.char===CHAR_l)return this.consume(),this.next(this.parseFalse_s);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseFalse_s(){if(this.char===CHAR_s)return this.consume(),this.next(this.parseFalse_e);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseFalse_e(){if(this.char===CHAR_e)return this.return(!1);throw this.error(new TomlError("Invalid boolean, expected true or false"))}parseInlineList(){if(this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M||this.char===CTRL_J)return null;if(this.char===e.END)throw this.error(new TomlError("Unterminated inline array"));return this.char===CHAR_NUM?this.call(this.parseComment):this.char===CHAR_RSQB?this.return(this.state.resultArr||InlineList()):this.callNow(this.parseValue,this.recordInlineListValue)}recordInlineListValue(e){return this.state.resultArr||(this.state.resultArr=InlineList(tomlType(e))),isFloat(e)||isInteger(e)?this.state.resultArr.push(e.valueOf()):this.state.resultArr.push(e),this.goto(this.parseInlineListNext)}parseInlineListNext(){if(this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M||this.char===CTRL_J)return null;if(this.char===CHAR_NUM)return this.call(this.parseComment);if(this.char===CHAR_COMMA)return this.next(this.parseInlineList);if(this.char===CHAR_RSQB)return this.goto(this.parseInlineList);throw this.error(new TomlError("Invalid character, expected whitespace, comma (,) or close bracket (])"))}parseInlineTable(){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===e.END||this.char===CHAR_NUM||this.char===CTRL_J||this.char===CTRL_M)throw this.error(new TomlError("Unterminated inline array"));return this.char===CHAR_RCUB?this.return(this.state.resultTable||InlineTable()):(this.state.resultTable||(this.state.resultTable=InlineTable()),this.callNow(this.parseAssign,this.recordInlineTableValue))}recordInlineTableValue(e){let t=this.state.resultTable,n=e.key.pop();for(let r of e.key){if(hasKey(t,r)&&(!isTable(t[r])||t[r][_declared]))throw this.error(new TomlError("Can't redefine existing key"));t=t[r]=t[r]||Table()}if(hasKey(t,n))throw this.error(new TomlError("Can't redefine existing key"));return isInteger(e.value)||isFloat(e.value)?t[n]=e.value.valueOf():t[n]=e.value,this.goto(this.parseInlineTableNext)}parseInlineTableNext(){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===e.END||this.char===CHAR_NUM||this.char===CTRL_J||this.char===CTRL_M)throw this.error(new TomlError("Unterminated inline array"));if(this.char===CHAR_COMMA)return this.next(this.parseInlineTablePostComma);if(this.char===CHAR_RCUB)return this.goto(this.parseInlineTable);throw this.error(new TomlError("Invalid character, expected whitespace, comma (,) or close bracket (])"))}parseInlineTablePostComma(){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===e.END||this.char===CHAR_NUM||this.char===CTRL_J||this.char===CTRL_M)throw this.error(new TomlError("Unterminated inline array"));if(this.char===CHAR_COMMA)throw this.error(new TomlError("Empty elements in inline tables are not permitted"));if(this.char!==CHAR_RCUB)return this.goto(this.parseInlineTable);throw this.error(new TomlError("Trailing commas in inline tables are not permitted"))}}return t}},90560(e,t,n){"use strict";e.exports=a;let r=n(8676),i=n(22418);function a(e,t){t||(t={});let n=0,a=t.blocksize||40960,o=new r;return new Promise((e,t)=>{setImmediate(s,n,a,e,t)});function s(t,n,r,a){if(t>=e.length)try{return r(o.finish())}catch(u){return a(i(u,e))}try{o.parse(e.slice(t,t+n)),setImmediate(s,t+n,n,r,a)}catch(c){a(i(c,e))}}}},22418(e){"use strict";function t(e,t){if(null==e.pos||null==e.line)return e;let n=e.message;if(n+=` at row ${e.line+1}, col ${e.col+1}, pos ${e.pos}:
+`,t&&t.split){let r=t.split(/\n/),i=String(Math.min(r.length,e.line+3)).length,a=" ";for(;a.length "+r[o]+"\n",n+=a+" ";for(let u=0;u{let i,a=!1,o=!1;function s(){if(a=!0,!i)try{n(t.finish())}catch(e){r(e)}}function u(e){o=!0,r(e)}function c(){i=!0;let n;for(;null!==(n=e.read());)try{t.parse(n)}catch(r){return u(r)}if(i=!1,a)return s();o||e.once("readable",c)}e.once("end",s),e.once("error",u),c()})}function s(){let e=new i;return new r.Transform({objectMode:!0,transform(t,n,r){try{e.parse(t.toString(n))}catch(i){this.emit("error",i)}r()},flush(t){try{this.push(e.finish())}catch(n){this.emit("error",n)}t()}})}},56530(e,t,n){"use strict";e.exports=a;let r=n(8676),i=n(22418);function a(e){n.g.Buffer&&n.g.Buffer.isBuffer(e)&&(e=e.toString("utf8"));let t=new r;try{return t.parse(e),t.finish()}catch(a){throw i(a,e)}}},83512(e,t,n){"use strict";e.exports=n(56530),e.exports.async=n(90560),e.exports.stream=n(6435),e.exports.prettyError=n(22418)},36921(e){"use strict";function t(e){if(null===e)throw n("null");if(void 0===e)throw n("undefined");if("object"!=typeof e)throw n(typeof e);if("function"==typeof e.toJSON&&(e=e.toJSON()),null==e)return null;let t=u(e);if("table"!==t)throw n(t);return o("","",e)}function n(e){return Error("Can only stringify objects, not "+e)}function r(e){return Object.keys(e).filter(t=>s(e[t]))}function i(e){return Object.keys(e).filter(t=>!s(e[t]))}function a(e){let t=Array.isArray(e)?[]:Object.prototype.hasOwnProperty.call(e,"__proto__")?{["__proto__"]:void 0}:{};for(let n of Object.keys(e))!e[n]||"function"!=typeof e[n].toJSON||"toISOString"in e[n]?t[n]=e[n]:t[n]=e[n].toJSON();return t}function o(e,t,n){let o,s;o=r(n=a(n)),s=i(n);let l=[],f=t||"";o.forEach(e=>{var t=u(n[e]);"undefined"!==t&&"null"!==t&&l.push(f+c(e)+" = "+b(n[e],!0))}),l.length>0&&l.push("");let d=e&&o.length>0?t+" ":"";return s.forEach(t=>{l.push(S(e,d,t,n[t]))}),l.join("\n")}function s(e){switch(u(e)){case"undefined":case"null":case"integer":case"nan":case"float":case"boolean":case"string":case"datetime":return!0;case"array":return 0===e.length||"table"!==u(e[0]);case"table":return 0===Object.keys(e).length;default:return!1}}function u(e){if(void 0===e)return"undefined";if(null===e)return"null";if("bigint"==typeof e||Number.isInteger(e)&&!Object.is(e,-0))return"integer";if("number"==typeof e)return"float";if("boolean"==typeof e)return"boolean";else if("string"==typeof e)return"string";else if("toISOString"in e)return isNaN(e)?"undefined":"datetime";else if(Array.isArray(e))return"array";else return"table"}function c(e){let t=String(e);return/^[-A-Za-z0-9_]+$/.test(t)?t:l(t)}function l(e){return'"'+h(e).replace(/"/g,'\\"')+'"'}function f(e){return"'"+e+"'"}function d(e,t){for(;t.length"\\u"+d(4,e.codePointAt(0).toString(16)))}function p(e){let t=e.split(/\n/).map(e=>h(e).replace(/"(?="")/g,'\\"')).join("\n");return'"'===t.slice(-1)&&(t+="\\\n"),'"""\n'+t+'"""'}function b(e,t){let n=u(e);return"string"===n&&(t&&/\n/.test(e)?n="string-multiline":!/[\b\t\n\f\r']/.test(e)&&/"/.test(e)&&(n="string-literal")),m(e,n)}function m(e,t){switch(t||(t=u(e)),t){case"string-multiline":return p(e);case"string":return l(e);case"string-literal":return f(e);case"integer":return g(e);case"float":return v(e);case"boolean":return y(e);case"datetime":return w(e);case"array":return _(e.filter(e=>"null"!==u(e)&&"undefined"!==u(e)&&"nan"!==u(e)));case"table":return E(e);default:throw n(t)}}function g(e){return String(e).replace(/\B(?=(\d{3})+(?!\d))/g,"_")}function v(e){if(e===1/0)return"inf";if(e===-1/0)return"-inf";if(Object.is(e,NaN))return"nan";if(Object.is(e,-0))return"-0.0";let[t,n]=String(e).split(".");return g(t)+"."+n}function y(e){return String(e)}function w(e){return e.toISOString()}function _(e){e=a(e);let t="[",n=e.map(e=>m(e));return n.join(", ").length>60||/\n/.test(n)?t+="\n "+n.join(",\n ")+"\n":t+=" "+n.join(", ")+(n.length>0?" ":""),t+"]"}function E(e){e=a(e);let t=[];return Object.keys(e).forEach(n=>{t.push(c(n)+" = "+b(e[n],!1))}),"{ "+t.join(", ")+(t.length>0?" ":"")+"}"}function S(e,t,r,i){let a=u(i);if("array"===a)return k(e,t,r,i);if("table"===a)return x(e,t,r,i);throw n(a)}function k(e,t,r,i){i=a(i);let s=u(i[0]);if("table"!==s)throw n(s);let l=e+c(r),f="";return i.forEach(e=>{f.length>0&&(f+="\n"),f+=t+"[["+l+"]]\n",f+=o(l+".",t,e)}),f}function x(e,t,n,i){let a=e+c(n),s="";return r(i).length>0&&(s+=t+"["+a+"]\n"),s+o(a+".",t,i)}e.exports=t,e.exports.value=m},5022(e,t,n){"use strict";t.parse=n(83512),t.stringify=n(36921)},46515(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184)),c=r(n(78252)),l=n(98741),f=r(n(68821)),d=function(e){var t="light"===e.palette.type?e.palette.grey[100]:e.palette.grey[900];return{root:{display:"flex",flexDirection:"column",width:"100%",boxSizing:"border-box",zIndex:e.zIndex.appBar,flexShrink:0},positionFixed:{position:"fixed",top:0,left:"auto",right:0},positionAbsolute:{position:"absolute",top:0,left:"auto",right:0},positionSticky:{position:"sticky",top:0,left:"auto",right:0},positionStatic:{position:"static"},positionRelative:{position:"relative"},colorDefault:{backgroundColor:t,color:e.palette.getContrastText(t)},colorPrimary:{backgroundColor:e.palette.primary.main,color:e.palette.primary.contrastText},colorSecondary:{backgroundColor:e.palette.secondary.main,color:e.palette.secondary.contrastText}}};function h(e){var t,n=e.children,r=e.classes,c=e.className,d=e.color,h=e.position,p=(0,o.default)(e,["children","classes","className","color","position"]),b=(0,u.default)(r.root,r["position".concat((0,l.capitalize)(h))],(t={},(0,a.default)(t,r["color".concat((0,l.capitalize)(d))],"inherit"!==d),(0,a.default)(t,"mui-fixed","fixed"===h),t),c);return s.default.createElement(f.default,(0,i.default)({square:!0,component:"header",elevation:4,className:b},p),n)}t.styles=d,h.defaultProps={color:"primary",position:"fixed"};var p=(0,c.default)(d,{name:"MuiAppBar"})(h);t.default=p},95880(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(46515))},68477(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(59713)),a=r(n(67154)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=function(e){return{root:{position:"relative",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,width:40,height:40,fontFamily:e.typography.fontFamily,fontSize:e.typography.pxToRem(20),borderRadius:"50%",overflow:"hidden",userSelect:"none"},colorDefault:{color:e.palette.background.default,backgroundColor:"light"===e.palette.type?e.palette.grey[400]:e.palette.grey[600]},img:{width:"100%",height:"100%",textAlign:"center",objectFit:"cover"}}};function f(e){var t=e.alt,n=e.children,r=e.childrenClassName,c=e.classes,l=e.className,f=e.component,d=e.imgProps,h=e.sizes,p=e.src,b=e.srcSet,m=(0,o.default)(e,["alt","children","childrenClassName","classes","className","component","imgProps","sizes","src","srcSet"]),g=null,v=p||b;return g=v?s.default.createElement("img",(0,a.default)({alt:t,src:p,srcSet:b,sizes:h,className:c.img},d)):r&&s.default.isValidElement(n)?s.default.cloneElement(n,{className:(0,u.default)(r,n.props.className)}):n,s.default.createElement(f,(0,a.default)({className:(0,u.default)(c.root,c.system,(0,i.default)({},c.colorDefault,!v),l)},m),g)}t.styles=l,f.defaultProps={component:"div"};var d=(0,c.default)(l,{name:"MuiAvatar"})(f);t.default=d},90338(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(68477))},9211(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184)),c=r(n(78252)),l=r(n(46408)),f={root:{zIndex:-1,position:"fixed",right:0,bottom:0,top:0,left:0,backgroundColor:"rgba(0, 0, 0, 0.5)",WebkitTapHighlightColor:"transparent",touchAction:"none"},invisible:{backgroundColor:"transparent"}};function d(e){var t=e.classes,n=e.className,r=e.invisible,c=e.open,f=e.transitionDuration,d=(0,o.default)(e,["classes","className","invisible","open","transitionDuration"]);return s.default.createElement(l.default,(0,i.default)({in:c,timeout:f},d),s.default.createElement("div",{className:(0,u.default)(t.root,(0,a.default)({},t.invisible,r),n),"aria-hidden":"true"}))}t.styles=f,d.defaultProps={invisible:!1};var h=(0,c.default)(f,{name:"MuiBackdrop"})(d);t.default=h},14983(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(9211))},84732(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=n(98741),f=10,d=function(e){return{root:{position:"relative",display:"inline-flex",verticalAlign:"middle"},badge:{display:"flex",flexDirection:"row",flexWrap:"wrap",justifyContent:"center",alignContent:"center",alignItems:"center",position:"absolute",top:0,right:0,boxSizing:"border-box",fontFamily:e.typography.fontFamily,fontWeight:e.typography.fontWeightMedium,fontSize:e.typography.pxToRem(12),minWidth:2*f,padding:"0 4px",height:2*f,borderRadius:f,backgroundColor:e.palette.color,color:e.palette.textColor,zIndex:1,transform:"scale(1) translate(50%, -50%)",transformOrigin:"100% 0%",transition:e.transitions.create("transform",{easing:e.transitions.easing.easeInOut,duration:e.transitions.duration.enteringScreen})},colorPrimary:{backgroundColor:e.palette.primary.main,color:e.palette.primary.contrastText},colorSecondary:{backgroundColor:e.palette.secondary.main,color:e.palette.secondary.contrastText},colorError:{backgroundColor:e.palette.error.main,color:e.palette.error.contrastText},invisible:{transition:e.transitions.create("transform",{easing:e.transitions.easing.easeInOut,duration:e.transitions.duration.leavingScreen}),transform:"scale(0) translate(50%, -50%)",transformOrigin:"100% 0%"},dot:{height:6,minWidth:6,padding:0}}};function h(e){var t,n=e.badgeContent,r=e.children,c=e.classes,f=e.className,d=e.color,h=e.component,p=e.invisible,b=e.showZero,m=e.max,g=e.variant,v=(0,o.default)(e,["badgeContent","children","classes","className","color","component","invisible","showZero","max","variant"]),y=p;null!=p||0!==Number(n)||b||(y=!0);var w=(0,u.default)(c.badge,(t={},(0,a.default)(t,c["color".concat((0,l.capitalize)(d))],"default"!==d),(0,a.default)(t,c.invisible,y),(0,a.default)(t,c.dot,"dot"===g),t)),_="";return"dot"!==g&&(_=n>m?"".concat(m,"+"):n),s.default.createElement(h,(0,i.default)({className:(0,u.default)(c.root,f)},v),r,s.default.createElement("span",{className:w},_))}t.styles=d,h.defaultProps={color:"default",component:"span",max:99,showZero:!1,variant:"standard"};var p=(0,c.default)(d,{name:"MuiBadge"})(h);t.default=p},70398(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(84732))},21783(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(59713)),a=r(n(6479)),o=r(n(67154)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=n(59114),f=r(n(16070)),d=n(98741),h=function(e){return{root:(0,o.default)({lineHeight:1.75},e.typography.button,{boxSizing:"border-box",minWidth:64,padding:"6px 16px",borderRadius:e.shape.borderRadius,color:e.palette.text.primary,transition:e.transitions.create(["background-color","box-shadow","border"],{duration:e.transitions.duration.short}),"&:hover":{textDecoration:"none",backgroundColor:(0,l.fade)(e.palette.text.primary,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"},"&$disabled":{backgroundColor:"transparent"}},"&$disabled":{color:e.palette.action.disabled}}),label:{width:"100%",display:"inherit",alignItems:"inherit",justifyContent:"inherit"},text:{padding:"6px 8px"},textPrimary:{color:e.palette.primary.main,"&:hover":{backgroundColor:(0,l.fade)(e.palette.primary.main,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}}},textSecondary:{color:e.palette.secondary.main,"&:hover":{backgroundColor:(0,l.fade)(e.palette.secondary.main,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}}},flat:{},flatPrimary:{},flatSecondary:{},outlined:{padding:"5px 16px",border:"1px solid ".concat("light"===e.palette.type?"rgba(0, 0, 0, 0.23)":"rgba(255, 255, 255, 0.23)"),"&$disabled":{border:"1px solid ".concat(e.palette.action.disabled)}},outlinedPrimary:{color:e.palette.primary.main,border:"1px solid ".concat((0,l.fade)(e.palette.primary.main,.5)),"&:hover":{border:"1px solid ".concat(e.palette.primary.main),backgroundColor:(0,l.fade)(e.palette.primary.main,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}}},outlinedSecondary:{color:e.palette.secondary.main,border:"1px solid ".concat((0,l.fade)(e.palette.secondary.main,.5)),"&:hover":{border:"1px solid ".concat(e.palette.secondary.main),backgroundColor:(0,l.fade)(e.palette.secondary.main,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}},"&$disabled":{border:"1px solid ".concat(e.palette.action.disabled)}},contained:{color:e.palette.getContrastText(e.palette.grey[300]),backgroundColor:e.palette.grey[300],boxShadow:e.shadows[2],"&$focusVisible":{boxShadow:e.shadows[6]},"&:active":{boxShadow:e.shadows[8]},"&$disabled":{color:e.palette.action.disabled,boxShadow:e.shadows[0],backgroundColor:e.palette.action.disabledBackground},"&:hover":{backgroundColor:e.palette.grey.A100,"@media (hover: none)":{backgroundColor:e.palette.grey[300]},"&$disabled":{backgroundColor:e.palette.action.disabledBackground}}},containedPrimary:{color:e.palette.primary.contrastText,backgroundColor:e.palette.primary.main,"&:hover":{backgroundColor:e.palette.primary.dark,"@media (hover: none)":{backgroundColor:e.palette.primary.main}}},containedSecondary:{color:e.palette.secondary.contrastText,backgroundColor:e.palette.secondary.main,"&:hover":{backgroundColor:e.palette.secondary.dark,"@media (hover: none)":{backgroundColor:e.palette.secondary.main}}},raised:{},raisedPrimary:{},raisedSecondary:{},fab:{borderRadius:"50%",padding:0,minWidth:0,width:56,height:56,boxShadow:e.shadows[6],"&:active":{boxShadow:e.shadows[12]}},extendedFab:{borderRadius:24,padding:"0 16px",width:"auto",minWidth:48,height:48},focusVisible:{},disabled:{},colorInherit:{color:"inherit",borderColor:"currentColor"},mini:{width:40,height:40},sizeSmall:{padding:"4px 8px",minWidth:64,fontSize:e.typography.pxToRem(13)},sizeLarge:{padding:"8px 24px",fontSize:e.typography.pxToRem(15)},fullWidth:{width:"100%"}}};function p(e){var t,n=e.children,r=e.classes,c=e.className,l=e.color,h=e.disabled,p=e.disableFocusRipple,b=e.focusVisibleClassName,m=e.fullWidth,g=e.mini,v=e.size,y=e.variant,w=(0,a.default)(e,["children","classes","className","color","disabled","disableFocusRipple","focusVisibleClassName","fullWidth","mini","size","variant"]),_="fab"===y||"extendedFab"===y,E="contained"===y||"raised"===y,S="text"===y||"flat"===y,k=(0,u.default)(r.root,(t={},(0,i.default)(t,r.fab,_),(0,i.default)(t,r.mini,_&&g),(0,i.default)(t,r.extendedFab,"extendedFab"===y),(0,i.default)(t,r.text,S),(0,i.default)(t,r.textPrimary,S&&"primary"===l),(0,i.default)(t,r.textSecondary,S&&"secondary"===l),(0,i.default)(t,r.flat,S),(0,i.default)(t,r.flatPrimary,S&&"primary"===l),(0,i.default)(t,r.flatSecondary,S&&"secondary"===l),(0,i.default)(t,r.contained,E||_),(0,i.default)(t,r.containedPrimary,(E||_)&&"primary"===l),(0,i.default)(t,r.containedSecondary,(E||_)&&"secondary"===l),(0,i.default)(t,r.raised,E||_),(0,i.default)(t,r.raisedPrimary,(E||_)&&"primary"===l),(0,i.default)(t,r.raisedSecondary,(E||_)&&"secondary"===l),(0,i.default)(t,r.outlined,"outlined"===y),(0,i.default)(t,r.outlinedPrimary,"outlined"===y&&"primary"===l),(0,i.default)(t,r.outlinedSecondary,"outlined"===y&&"secondary"===l),(0,i.default)(t,r["size".concat((0,d.capitalize)(v))],"medium"!==v),(0,i.default)(t,r.disabled,h),(0,i.default)(t,r.fullWidth,m),(0,i.default)(t,r.colorInherit,"inherit"===l),t),c);return s.default.createElement(f.default,(0,o.default)({className:k,disabled:h,focusRipple:!p,focusVisibleClassName:(0,u.default)(r.focusVisible,b)},w),s.default.createElement("span",{className:r.label},n))}t.styles=h,p.defaultProps={color:"default",component:"button",disabled:!1,disableFocusRipple:!1,fullWidth:!1,mini:!1,size:"medium",type:"button",variant:"text"};var b=(0,c.default)(h,{name:"MuiButton"})(p);t.default=b},83638(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(21783))},74610(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(34575)),u=r(n(93913)),c=r(n(78585)),l=r(n(29754)),f=r(n(2205)),d=r(n(81506)),h=r(n(67294));r(n(45697));var p=r(n(73935)),b=r(n(94184));n(55252);var m=r(n(62614)),g=r(n(78252)),v=r(n(78582)),y=n(32252),w=r(n(65406)),_=r(n(83673)),E={root:{display:"inline-flex",alignItems:"center",justifyContent:"center",position:"relative",WebkitTapHighlightColor:"transparent",backgroundColor:"transparent",outline:"none",border:0,margin:0,borderRadius:0,padding:0,cursor:"pointer",userSelect:"none",verticalAlign:"middle","-moz-appearance":"none","-webkit-appearance":"none",textDecoration:"none",color:"inherit","&::-moz-focus-inner":{borderStyle:"none"},"&$disabled":{pointerEvents:"none",cursor:"default"}},disabled:{},focusVisible:{}};t.styles=E;var S=function(e){function t(){(0,s.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;a0&&void 0!==arguments[0]?arguments[0]:{},o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},s=arguments.length>2?arguments[2]:void 0,u=o.pulsate,c=void 0!==u&&u,l=o.center,f=void 0===l?n.props.center||o.pulsate:l,h=o.fakeElement,b=void 0!==h&&h;if("mousedown"===a.type&&n.ignoringMouseDown){n.ignoringMouseDown=!1;return}"touchstart"===a.type&&(n.ignoringMouseDown=!0);var m=b?null:p.default.findDOMNode((0,d.default)((0,d.default)(n))),g=m?m.getBoundingClientRect():{width:0,height:0,left:0,top:0};if(!f&&(0!==a.clientX||0!==a.clientY)&&(a.clientX||a.touches)){var v=a.clientX?a.clientX:a.touches[0].clientX,y=a.clientY?a.clientY:a.touches[0].clientY;t=Math.round(v-g.left),r=Math.round(y-g.top)}else t=Math.round(g.width/2),r=Math.round(g.height/2);if(f)(i=Math.sqrt((2*Math.pow(g.width,2)+Math.pow(g.height,2))/3))%2==0&&(i+=1);else{i=Math.sqrt(Math.pow(2*Math.max(Math.abs((m?m.clientWidth:0)-t),t)+2,2)+Math.pow(2*Math.max(Math.abs((m?m.clientHeight:0)-r),r)+2,2))}a.touches?(n.startTimerCommit=function(){n.startCommit({pulsate:c,rippleX:t,rippleY:r,rippleSize:i,cb:s})},n.startTimer=setTimeout(function(){n.startTimerCommit&&(n.startTimerCommit(),n.startTimerCommit=null)},w)):n.startCommit({pulsate:c,rippleX:t,rippleY:r,rippleSize:i,cb:s})},n.startCommit=function(e){var t=e.pulsate,r=e.rippleX,i=e.rippleY,a=e.rippleSize,s=e.cb;n.setState(function(e){return{nextKey:e.nextKey+1,ripples:[].concat((0,o.default)(e.ripples),[h.default.createElement(v.default,{key:e.nextKey,classes:n.props.classes,timeout:{exit:y,enter:y},pulsate:t,rippleX:r,rippleY:i,rippleSize:a})])}},s)},n.stop=function(e,t){clearTimeout(n.startTimer);var r=n.state.ripples;if("touchend"===e.type&&n.startTimerCommit){e.persist(),n.startTimerCommit(),n.startTimerCommit=null,n.startTimer=setTimeout(function(){n.stop(e,t)});return}n.startTimerCommit=null,r&&r.length&&n.setState({ripples:r.slice(1)},t)},n}return(0,f.default)(t,e),(0,u.default)(t,[{key:"componentWillUnmount",value:function(){clearTimeout(this.startTimer)}},{key:"render",value:function(){var e=this.props,t=(e.center,e.classes),n=e.className,r=(0,a.default)(e,["center","classes","className"]);return h.default.createElement(b.default,(0,i.default)({component:"span",enter:!0,exit:!0,className:(0,m.default)(t.root,n)},r),this.state.ripples)}}]),t}(h.default.PureComponent);E.defaultProps={center:!1};var S=(0,g.default)(_,{flip:!1,name:"MuiTouchRipple"})(E);t.default=S},83673(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=function(e,t,n,r){return function(i){r&&r.call(e,i);var a=!1;return i.defaultPrevented&&(a=!0),e.props.disableTouchRipple&&"Blur"!==t&&(a=!0),!a&&e.ripple&&e.ripple[n](i),"function"==typeof e.props["on".concat(t)]&&e.props["on".concat(t)](i),!0}};"undefined"==typeof window&&(n=function(){return function(){}});var r=n;t.default=r},32252(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.detectFocusVisible=s,t.listenForFocusKeys=f,r(n(42473));var i=r(n(16143)),a={focusKeyPressed:!1,keyUpEventTimeout:-1};function o(e){for(var t=e.activeElement;t&&t.shadowRoot&&t.shadowRoot.activeElement;)t=t.shadowRoot.activeElement;return t}function s(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1;e.focusVisibleTimeout=setTimeout(function(){var u=(0,i.default)(t),c=o(u);a.focusKeyPressed&&(c===t||t.contains(c))?n():r-1}var l=function(e){c(e)&&(a.focusKeyPressed=!0,clearTimeout(a.keyUpEventTimeout),a.keyUpEventTimeout=setTimeout(function(){a.focusKeyPressed=!1},500))};function f(e){e.addEventListener("keyup",l)}},16070(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(74610))},46003(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184)),u=r(n(68821)),c=r(n(78252)),l={root:{overflow:"hidden"}};function f(e){var t=e.classes,n=e.className,r=e.raised,c=(0,a.default)(e,["classes","className","raised"]);return o.default.createElement(u.default,(0,i.default)({className:(0,s.default)(t.root,n),elevation:r?8:1},c))}t.styles=l,f.defaultProps={raised:!1};var d=(0,c.default)(l,{name:"MuiCard"})(f);t.default=d},82204(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(46003))},5780(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184));n(55252);var u=r(n(78252)),c={root:{padding:16,"&:last-child":{paddingBottom:24}}};function l(e){var t=e.classes,n=e.className,r=e.component,u=(0,a.default)(e,["classes","className","component"]);return o.default.createElement(r,(0,i.default)({className:(0,s.default)(t.root,n)},u))}t.styles=c,l.defaultProps={component:"div"};var f=(0,u.default)(c,{name:"MuiCardContent"})(l);t.default=f},30060(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(5780))},50704(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184));n(55252);var u=r(n(78252)),c=r(n(71426)),l={root:{display:"flex",alignItems:"center",padding:16},avatar:{flex:"0 0 auto",marginRight:16},action:{flex:"0 0 auto",alignSelf:"flex-start",marginTop:-8,marginRight:-8},content:{flex:"1 1 auto"},title:{},subheader:{}};function f(e){var t=e.action,n=e.avatar,r=e.classes,u=e.className,l=e.component,f=e.disableTypography,d=e.subheader,h=e.subheaderTypographyProps,p=e.title,b=e.titleTypographyProps,m=(0,a.default)(e,["action","avatar","classes","className","component","disableTypography","subheader","subheaderTypographyProps","title","titleTypographyProps"]),g=p;null==g||g.type===c.default||f||(g=o.default.createElement(c.default,(0,i.default)({variant:n?"body2":"headline",internalDeprecatedVariant:!0,className:r.title,component:"span"},b),g));var v=d;return null==v||v.type===c.default||f||(v=o.default.createElement(c.default,(0,i.default)({variant:n?"body2":"body1",className:r.subheader,color:"textSecondary",component:"span"},h),v)),o.default.createElement(l,(0,i.default)({className:(0,s.default)(r.root,u)},m),n&&o.default.createElement("div",{className:r.avatar},n),o.default.createElement("div",{className:r.content},g,v),t&&o.default.createElement("div",{className:r.action},t))}t.styles=l,f.defaultProps={component:"div",disableTypography:!1};var d=(0,u.default)(l,{name:"MuiCardHeader"})(f);t.default=d},52658(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(50704))},82811(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184)),c=r(n(85609)),l=r(n(42159)),f=r(n(41549)),d=r(n(61486)),h=n(98741),p=r(n(78252)),b=function(e){return{root:{color:e.palette.text.secondary},checked:{},disabled:{},indeterminate:{},colorPrimary:{"&$checked":{color:e.palette.primary.main},"&$disabled":{color:e.palette.action.disabled}},colorSecondary:{"&$checked":{color:e.palette.secondary.main},"&$disabled":{color:e.palette.action.disabled}}}};function m(e){var t=e.checkedIcon,n=e.classes,r=e.className,l=e.color,f=e.icon,d=e.indeterminate,p=e.indeterminateIcon,b=e.inputProps,m=(0,o.default)(e,["checkedIcon","classes","className","color","icon","indeterminate","indeterminateIcon","inputProps"]);return s.default.createElement(c.default,(0,i.default)({type:"checkbox",checkedIcon:d?p:t,className:(0,u.default)((0,a.default)({},n.indeterminate,d),r),classes:{root:(0,u.default)(n.root,n["color".concat((0,h.capitalize)(l))]),checked:n.checked,disabled:n.disabled},inputProps:(0,i.default)({"data-indeterminate":d},b),icon:d?p:f},m))}t.styles=b,m.defaultProps={checkedIcon:s.default.createElement(f.default,null),color:"secondary",icon:s.default.createElement(l.default,null),indeterminate:!1,indeterminateIcon:s.default.createElement(d.default,null)};var g=(0,p.default)(b,{name:"MuiCheckbox"})(m);t.default=g},71209(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(82811))},16444(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(34575)),u=r(n(93913)),c=r(n(78585)),l=r(n(29754)),f=r(n(2205)),d=r(n(67294));r(n(45697));var h=r(n(94184));r(n(42473)),n(55252);var p=r(n(99781)),b=r(n(78252)),m=n(59114);r(n(21677));var g=n(98741);n(68477);var v=function(e){var t=32,n="light"===e.palette.type?e.palette.grey[300]:e.palette.grey[700],r=(0,m.fade)(e.palette.text.primary,.26);return{root:{fontFamily:e.typography.fontFamily,fontSize:e.typography.pxToRem(13),display:"inline-flex",alignItems:"center",justifyContent:"center",height:t,color:e.palette.getContrastText(n),backgroundColor:n,borderRadius:t/2,whiteSpace:"nowrap",transition:e.transitions.create(["background-color","box-shadow"]),cursor:"default",outline:"none",textDecoration:"none",border:"none",padding:0,verticalAlign:"middle",boxSizing:"border-box"},colorPrimary:{backgroundColor:e.palette.primary.main,color:e.palette.primary.contrastText},colorSecondary:{backgroundColor:e.palette.secondary.main,color:e.palette.secondary.contrastText},clickable:{WebkitTapHighlightColor:"transparent",cursor:"pointer","&:hover, &:focus":{backgroundColor:(0,m.emphasize)(n,.08)},"&:active":{boxShadow:e.shadows[1],backgroundColor:(0,m.emphasize)(n,.12)}},clickableColorPrimary:{"&:hover, &:focus":{backgroundColor:(0,m.emphasize)(e.palette.primary.main,.08)},"&:active":{backgroundColor:(0,m.emphasize)(e.palette.primary.main,.12)}},clickableColorSecondary:{"&:hover, &:focus":{backgroundColor:(0,m.emphasize)(e.palette.secondary.main,.08)},"&:active":{backgroundColor:(0,m.emphasize)(e.palette.secondary.main,.12)}},deletable:{"&:focus":{backgroundColor:(0,m.emphasize)(n,.08)}},deletableColorPrimary:{"&:focus":{backgroundColor:(0,m.emphasize)(e.palette.primary.main,.2)}},deletableColorSecondary:{"&:focus":{backgroundColor:(0,m.emphasize)(e.palette.secondary.main,.2)}},outlined:{backgroundColor:"transparent",border:"1px solid ".concat("light"===e.palette.type?"rgba(0, 0, 0, 0.23)":"rgba(255, 255, 255, 0.23)"),"$clickable&:hover, $clickable&:focus, $deletable&:focus":{backgroundColor:(0,m.fade)(e.palette.text.primary,e.palette.action.hoverOpacity)},"& $avatar":{marginLeft:-1}},outlinedPrimary:{color:e.palette.primary.main,border:"1px solid ".concat(e.palette.primary.main),"$clickable&:hover, $clickable&:focus, $deletable&:focus":{backgroundColor:(0,m.fade)(e.palette.primary.main,e.palette.action.hoverOpacity)}},outlinedSecondary:{color:e.palette.secondary.main,border:"1px solid ".concat(e.palette.secondary.main),"$clickable&:hover, $clickable&:focus, $deletable&:focus":{backgroundColor:(0,m.fade)(e.palette.secondary.main,e.palette.action.hoverOpacity)}},avatar:{marginRight:-4,width:t,height:t,color:"light"===e.palette.type?e.palette.grey[700]:e.palette.grey[300],fontSize:e.typography.pxToRem(16)},avatarColorPrimary:{color:e.palette.primary.contrastText,backgroundColor:e.palette.primary.dark},avatarColorSecondary:{color:e.palette.secondary.contrastText,backgroundColor:e.palette.secondary.dark},avatarChildren:{width:19,height:19},icon:{color:"light"===e.palette.type?e.palette.grey[700]:e.palette.grey[300],marginLeft:4,marginRight:-8},iconColorPrimary:{color:"inherit"},iconColorSecondary:{color:"inherit"},label:{display:"flex",alignItems:"center",paddingLeft:12,paddingRight:12,userSelect:"none",whiteSpace:"nowrap",cursor:"inherit"},deleteIcon:{WebkitTapHighlightColor:"transparent",color:r,cursor:"pointer",height:"auto",margin:"0 4px 0 -8px","&:hover":{color:(0,m.fade)(r,.4)}},deleteIconColorPrimary:{color:(0,m.fade)(e.palette.primary.contrastText,.7),"&:hover, &:active":{color:e.palette.primary.contrastText}},deleteIconColorSecondary:{color:(0,m.fade)(e.palette.secondary.contrastText,.7),"&:hover, &:active":{color:e.palette.secondary.contrastText}},deleteIconOutlinedColorPrimary:{color:(0,m.fade)(e.palette.primary.main,.7),"&:hover, &:active":{color:e.palette.primary.main}},deleteIconOutlinedColorSecondary:{color:(0,m.fade)(e.palette.secondary.main,.7),"&:hover, &:active":{color:e.palette.secondary.main}}}};t.styles=v;var y=function(e){function t(){(0,s.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;a :last-child":{paddingRight:32},"&$expanded":{margin:"20px 0"}},expandIcon:{position:"absolute",top:"50%",right:8,transform:"translateY(-50%) rotate(0deg)",transition:e.transitions.create("transform",t),"&:hover":{backgroundColor:"transparent"},"&$expanded":{transform:"translateY(-50%) rotate(180deg)"}}}};t.styles=g;var v=function(e){function t(){(0,s.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;a $item":{padding:e/2}})}),n}var b=function(e){return(0,o.default)({container:{boxSizing:"border-box",display:"flex",flexWrap:"wrap",width:"100%"},item:{boxSizing:"border-box",margin:"0"},zeroMinWidth:{minWidth:0},"direction-xs-column":{flexDirection:"column"},"direction-xs-column-reverse":{flexDirection:"column-reverse"},"direction-xs-row-reverse":{flexDirection:"row-reverse"},"wrap-xs-nowrap":{flexWrap:"nowrap"},"wrap-xs-wrap-reverse":{flexWrap:"wrap-reverse"},"align-items-xs-center":{alignItems:"center"},"align-items-xs-flex-start":{alignItems:"flex-start"},"align-items-xs-flex-end":{alignItems:"flex-end"},"align-items-xs-baseline":{alignItems:"baseline"},"align-content-xs-center":{alignContent:"center"},"align-content-xs-flex-start":{alignContent:"flex-start"},"align-content-xs-flex-end":{alignContent:"flex-end"},"align-content-xs-space-between":{alignContent:"space-between"},"align-content-xs-space-around":{alignContent:"space-around"},"justify-xs-center":{justifyContent:"center"},"justify-xs-flex-end":{justifyContent:"flex-end"},"justify-xs-space-between":{justifyContent:"space-between"},"justify-xs-space-around":{justifyContent:"space-around"},"justify-xs-space-evenly":{justifyContent:"space-evenly"}},p(e,"xs"),l.keys.reduce(function(t,n){return h(t,e,n),t},{}))};function m(e){var t,n=e.alignContent,r=e.alignItems,c=e.classes,l=e.className,f=e.component,d=e.container,h=e.direction,p=e.item,b=e.justify,g=e.lg,v=e.md,y=e.sm,w=e.spacing,_=e.wrap,E=e.xl,S=e.xs,k=e.zeroMinWidth,x=(0,a.default)(e,["alignContent","alignItems","classes","className","component","container","direction","item","justify","lg","md","sm","spacing","wrap","xl","xs","zeroMinWidth"]),T=(0,u.default)((t={},(0,i.default)(t,c.container,d),(0,i.default)(t,c.item,p),(0,i.default)(t,c.zeroMinWidth,k),(0,i.default)(t,c["spacing-xs-".concat(String(w))],d&&0!==w),(0,i.default)(t,c["direction-xs-".concat(String(h))],h!==m.defaultProps.direction),(0,i.default)(t,c["wrap-xs-".concat(String(_))],_!==m.defaultProps.wrap),(0,i.default)(t,c["align-items-xs-".concat(String(r))],r!==m.defaultProps.alignItems),(0,i.default)(t,c["align-content-xs-".concat(String(n))],n!==m.defaultProps.alignContent),(0,i.default)(t,c["justify-xs-".concat(String(b))],b!==m.defaultProps.justify),(0,i.default)(t,c["grid-xs-".concat(String(S))],!1!==S),(0,i.default)(t,c["grid-sm-".concat(String(y))],!1!==y),(0,i.default)(t,c["grid-md-".concat(String(v))],!1!==v),(0,i.default)(t,c["grid-lg-".concat(String(g))],!1!==g),(0,i.default)(t,c["grid-xl-".concat(String(E))],!1!==E),t),l);return s.default.createElement(f,(0,o.default)({className:T},x))}t.styles=b,m.defaultProps={alignContent:"stretch",alignItems:"stretch",component:"div",container:!1,direction:"row",item:!1,justify:"flex-start",lg:!1,md:!1,sm:!1,spacing:0,wrap:"wrap",xl:!1,xs:!1,zeroMinWidth:!1};var g,v=(0,c.default)(b,{name:"MuiGrid"})(m);t.default=v},97779(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(27973))},57205(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294));r(n(45697));var d=r(n(60644)),h=r(n(82313)),p=n(41929);function b(e){return"scale(".concat(e,", ").concat(Math.pow(e,2),")")}var m={entering:{opacity:1,transform:b(1)},entered:{opacity:1,transform:"".concat(b(1)," translateZ(0)")}},g=function(e){function t(){(0,o.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;a=Number(e.rows)&&(n=Math.min(Number(e.rowsMax)*t,n)),n=Math.max(n,t),Math.abs(this.state.height-n)>1&&this.setState({height:n}))}}},{key:"render",value:function(){var e=this.props,t=e.classes,n=e.className,r=e.defaultValue,o=(e.onChange,e.rows),s=(e.rowsMax,e.style),u=(e.textareaRef,e.value),c=(0,a.default)(e,["classes","className","defaultValue","onChange","rows","rowsMax","style","textareaRef","value"]);return f.default.createElement("div",{className:t.root},f.default.createElement(p.default,{target:"window",onResize:this.handleResize}),f.default.createElement("textarea",{"aria-hidden":"true",className:(0,d.default)(t.textarea,t.shadow),readOnly:!0,ref:this.handleRefSinglelineShadow,rows:"1",tabIndex:-1,value:""}),f.default.createElement("textarea",{"aria-hidden":"true",className:(0,d.default)(t.textarea,t.shadow),defaultValue:r,readOnly:!0,ref:this.handleRefShadow,rows:o,tabIndex:-1,value:u}),f.default.createElement("textarea",(0,i.default)({rows:o,className:(0,d.default)(t.textarea,n),defaultValue:r,value:u,onChange:this.handleChange,ref:this.handleRefInput,style:(0,i.default)({height:this.state.height},s)},c)))}}]),t}(f.default.Component);y.defaultProps={rows:1};var w=(0,b.default)(v,{name:"MuiPrivateTextarea"})(y);t.default=w},67598(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(62010))},78586(e,t){"use strict";function n(e){return null!=e&&!(Array.isArray(e)&&0===e.length)}function r(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return e&&(n(e.value)&&""!==e.value||t&&n(e.defaultValue)&&""!==e.defaultValue)}function i(e){return e.startAdornment}Object.defineProperty(t,"__esModule",{value:!0}),t.hasValue=n,t.isFilled=r,t.isAdornedStart=i},56030(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184)),c=r(n(58189)),l=r(n(52598)),f=r(n(78252)),d=r(n(69645)),h=function(e){return{root:{transformOrigin:"top left"},focused:{},disabled:{},error:{},required:{},formControl:{position:"absolute",left:0,top:0,transform:"translate(0, 24px) scale(1)"},marginDense:{transform:"translate(0, 21px) scale(1)"},shrink:{transform:"translate(0, 1.5px) scale(0.75)",transformOrigin:"top left"},animated:{transition:e.transitions.create(["color","transform"],{duration:e.transitions.duration.shorter,easing:e.transitions.easing.easeOut})},filled:{zIndex:1,pointerEvents:"none",transform:"translate(12px, 20px) scale(1)","&$marginDense":{transform:"translate(12px, 17px) scale(1)"},"&$shrink":{transform:"translate(12px, 10px) scale(0.75)","&$marginDense":{transform:"translate(12px, 7px) scale(0.75)"}}},outlined:{zIndex:1,pointerEvents:"none",transform:"translate(14px, 20px) scale(1)","&$marginDense":{transform:"translate(14px, 17px) scale(1)"},"&$shrink":{transform:"translate(14px, -6px) scale(0.75)"}}}};function p(e){var t,n=e.children,r=e.classes,l=e.className,f=e.disableAnimation,h=e.FormLabelClasses,p=(e.margin,e.muiFormControl),b=e.shrink,m=(e.variant,(0,o.default)(e,["children","classes","className","disableAnimation","FormLabelClasses","margin","muiFormControl","shrink","variant"])),g=b;void 0===g&&p&&(g=p.filled||p.focused||p.adornedStart);var v=(0,c.default)({props:e,muiFormControl:p,states:["margin","variant"]}),y=(0,u.default)(r.root,(t={},(0,a.default)(t,r.formControl,p),(0,a.default)(t,r.animated,!f),(0,a.default)(t,r.shrink,g),(0,a.default)(t,r.marginDense,"dense"===v.margin),(0,a.default)(t,r.filled,"filled"===v.variant),(0,a.default)(t,r.outlined,"outlined"===v.variant),t),l);return s.default.createElement(d.default,(0,i.default)({"data-shrink":g,className:y,classes:(0,i.default)({focused:r.focused,disabled:r.disabled,error:r.error,required:r.required},h)},m),n)}t.styles=h,p.defaultProps={disableAnimation:!1};var b=(0,f.default)(h,{name:"MuiInputLabel"})((0,l.default)(p));t.default=b},23153(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(56030))},46616(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));r(n(42473));var c=r(n(78252)),l=n(59114),f=4,d=function(e){return{root:{position:"relative",overflow:"hidden",height:4},colorPrimary:{backgroundColor:(0,l.lighten)(e.palette.primary.light,.6)},colorSecondary:{backgroundColor:(0,l.lighten)(e.palette.secondary.light,.4)},determinate:{},indeterminate:{},buffer:{backgroundColor:"transparent"},query:{transform:"rotate(180deg)"},dashed:{position:"absolute",marginTop:0,height:"100%",width:"100%",animation:"buffer 3s infinite linear",animationName:"$buffer"},dashedColorPrimary:{backgroundImage:"radial-gradient(".concat((0,l.lighten)(e.palette.primary.light,.6)," 0%, ").concat((0,l.lighten)(e.palette.primary.light,.6)," 16%, transparent 42%)"),backgroundSize:"10px 10px",backgroundPosition:"0px -23px"},dashedColorSecondary:{backgroundImage:"radial-gradient(".concat((0,l.lighten)(e.palette.secondary.light,.4)," 0%, ").concat((0,l.lighten)(e.palette.secondary.light,.6)," 16%, transparent 42%)"),backgroundSize:"10px 10px",backgroundPosition:"0px -23px"},bar:{width:"100%",position:"absolute",left:0,bottom:0,top:0,transition:"transform 0.2s linear",transformOrigin:"left"},barColorPrimary:{backgroundColor:e.palette.primary.main},barColorSecondary:{backgroundColor:e.palette.secondary.main},bar1Indeterminate:{width:"auto",animation:"mui-indeterminate1 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite",animationName:"$mui-indeterminate1"},bar1Determinate:{transition:"transform .".concat(f,"s linear")},bar1Buffer:{zIndex:1,transition:"transform .".concat(f,"s linear")},bar2Indeterminate:{width:"auto",animation:"mui-indeterminate2 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite",animationName:"$mui-indeterminate2",animationDelay:"1.15s"},bar2Buffer:{transition:"transform .".concat(f,"s linear")},"@keyframes mui-indeterminate1":{"0%":{left:"-35%",right:"100%"},"60%":{left:"100%",right:"-90%"},"100%":{left:"100%",right:"-90%"}},"@keyframes mui-indeterminate2":{"0%":{left:"-200%",right:"100%"},"60%":{left:"107%",right:"-8%"},"100%":{left:"107%",right:"-8%"}},"@keyframes buffer":{"0%":{opacity:1,backgroundPosition:"0px -23px"},"50%":{opacity:0,backgroundPosition:"0px -23px"},"100%":{opacity:1,backgroundPosition:"-200px -23px"}}}};function h(e){var t,n,r,c,l=e.classes,f=e.className,d=e.color,h=e.value,p=e.valueBuffer,b=e.variant,m=(0,o.default)(e,["classes","className","color","value","valueBuffer","variant"]),g=(0,u.default)(l.root,(t={},(0,a.default)(t,l.colorPrimary,"primary"===d),(0,a.default)(t,l.colorSecondary,"secondary"===d),(0,a.default)(t,l.determinate,"determinate"===b),(0,a.default)(t,l.indeterminate,"indeterminate"===b),(0,a.default)(t,l.buffer,"buffer"===b),(0,a.default)(t,l.query,"query"===b),t),f),v=(0,u.default)(l.dashed,(n={},(0,a.default)(n,l.dashedColorPrimary,"primary"===d),(0,a.default)(n,l.dashedColorSecondary,"secondary"===d),n)),y=(0,u.default)(l.bar,(r={},(0,a.default)(r,l.barColorPrimary,"primary"===d),(0,a.default)(r,l.barColorSecondary,"secondary"===d),(0,a.default)(r,l.bar1Indeterminate,"indeterminate"===b||"query"===b),(0,a.default)(r,l.bar1Determinate,"determinate"===b),(0,a.default)(r,l.bar1Buffer,"buffer"===b),r)),w=(0,u.default)(l.bar,(c={},(0,a.default)(c,l.barColorPrimary,"primary"===d&&"buffer"!==b),(0,a.default)(c,l.colorPrimary,"primary"===d&&"buffer"===b),(0,a.default)(c,l.barColorSecondary,"secondary"===d&&"buffer"!==b),(0,a.default)(c,l.colorSecondary,"secondary"===d&&"buffer"===b),(0,a.default)(c,l.bar2Indeterminate,"indeterminate"===b||"query"===b),(0,a.default)(c,l.bar2Buffer,"buffer"===b),c)),_={},E={bar1:{},bar2:{}};return("determinate"===b||"buffer"===b)&&void 0!==h&&(_["aria-valuenow"]=Math.round(h),E.bar1.transform="scaleX(".concat(h/100,")")),"buffer"===b&&void 0!==p&&(E.bar2.transform="scaleX(".concat((p||0)/100,")")),s.default.createElement("div",(0,i.default)({className:g,role:"progressbar"},_,m),"buffer"===b?s.default.createElement("div",{className:v}):null,s.default.createElement("div",{className:y,style:E.bar1}),"determinate"===b?null:s.default.createElement("div",{className:w,style:E.bar2}))}t.styles=d,h.defaultProps={color:"primary",variant:"indeterminate"};var p=(0,c.default)(d,{name:"MuiLinearProgress"})(h);t.default=p},79424(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(46616))},74080(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=r(n(47457)),f={root:{listStyle:"none",margin:0,padding:0,position:"relative"},padding:{paddingTop:8,paddingBottom:8},dense:{paddingTop:4,paddingBottom:4},subheader:{paddingTop:0}};function d(e){var t,n=e.children,r=e.classes,c=e.className,f=e.component,d=e.dense,h=e.disablePadding,p=e.subheader,b=(0,o.default)(e,["children","classes","className","component","dense","disablePadding","subheader"]);return s.default.createElement(f,(0,i.default)({className:(0,u.default)(r.root,(t={},(0,a.default)(t,r.dense,d&&!h),(0,a.default)(t,r.padding,!h),(0,a.default)(t,r.subheader,p),t),c)},b),s.default.createElement(l.default.Provider,{value:{dense:d}},p,n))}t.styles=f,d.defaultProps={component:"ul",dense:!1,disablePadding:!1};var h=(0,c.default)(f,{name:"MuiList"})(d);t.default=h},47457(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)).default.createContext({});t.default=i},3022(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(74080))},29936(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=r(n(16070)),f=n(44370),d=r(n(671)),h=function(e){return{root:{display:"flex",justifyContent:"flex-start",alignItems:"center",position:"relative",textDecoration:"none",width:"100%",boxSizing:"border-box",textAlign:"left",paddingTop:11,paddingBottom:11,"&$selected, &$selected:hover, &$selected:focus":{backgroundColor:e.palette.action.selected}},container:{position:"relative"},focusVisible:{},default:{},dense:{paddingTop:8,paddingBottom:8},alignItemsFlexStart:{alignItems:"flex-start"},disabled:{opacity:.5},divider:{borderBottom:"1px solid ".concat(e.palette.divider),backgroundClip:"padding-box"},gutters:{paddingLeft:16,paddingRight:16},button:{transition:e.transitions.create("background-color",{duration:e.transitions.duration.shortest}),"&:hover":{textDecoration:"none",backgroundColor:e.palette.action.hover,"@media (hover: none)":{backgroundColor:"transparent"}},"&:focus":{backgroundColor:e.palette.action.hover}},secondaryAction:{paddingRight:32},selected:{}}};function p(e){var t=e.alignItems,n=e.button,r=e.children,c=e.classes,h=e.className,p=e.component,b=e.ContainerComponent,m=e.ContainerProps,g=(m=void 0===m?{}:m).className,v=(0,o.default)(m,["className"]),y=e.dense,w=e.disabled,_=e.disableGutters,E=e.divider,S=e.focusVisibleClassName,k=e.selected,x=(0,o.default)(e,["alignItems","button","children","classes","className","component","ContainerComponent","ContainerProps","dense","disabled","disableGutters","divider","focusVisibleClassName","selected"]);return s.default.createElement(d.default,{dense:y,alignItems:t},function(e){var o,d=e.dense,m=s.default.Children.toArray(r),y=m.some(function(e){return(0,f.isMuiElement)(e,["ListItemAvatar"])}),T=m.length&&(0,f.isMuiElement)(m[m.length-1],["ListItemSecondaryAction"]),M=(0,u.default)(c.root,c.default,(o={},(0,a.default)(o,c.dense,d||y),(0,a.default)(o,c.gutters,!_),(0,a.default)(o,c.divider,E),(0,a.default)(o,c.disabled,w),(0,a.default)(o,c.button,n),(0,a.default)(o,c.alignItemsFlexStart,"flex-start"===t),(0,a.default)(o,c.secondaryAction,T),(0,a.default)(o,c.selected,k),o),h),O=(0,i.default)({className:M,disabled:w},x),A=p||"li";return(n&&(O.component=p||"div",O.focusVisibleClassName=(0,u.default)(c.focusVisible,S),A=l.default),T)?(A=O.component||p?A:"div","li"===b&&("li"===A?A="div":"li"===O.component&&(O.component="div")),s.default.createElement(b,(0,i.default)({className:(0,u.default)(c.container,g)},v),s.default.createElement(A,O,m),m.pop())):s.default.createElement(A,O,m)})}t.styles=h,p.defaultProps={alignItems:"center",button:!1,ContainerComponent:"li",dense:!1,disabled:!1,disableGutters:!1,divider:!1,selected:!1};var b=(0,c.default)(h,{name:"MuiListItem"})(p);t.default=b},671(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294));r(n(45697));var a=r(n(47457));function o(e){var t=e.alignItems,n=e.children,r=e.dense;return i.default.createElement(a.default.Consumer,null,function(e){var o={dense:r||e.dense||!1,alignItems:t};return i.default.createElement(a.default.Provider,{value:o},n(o))})}var s=o;t.default=s},60323(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(29936))},69394(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184)),u=r(n(78252)),c=function(e){return{root:{marginRight:16,color:e.palette.action.active,flexShrink:0,display:"inline-flex"}}};function l(e){var t=e.children,n=e.classes,r=e.className,u=(0,a.default)(e,["children","classes","className"]);return o.default.createElement("div",(0,i.default)({className:(0,s.default)(n.root,r)},u),t)}t.styles=c;var f=(0,u.default)(c,{name:"MuiListItemIcon"})(l);t.default=f},11186(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(69394))},73390(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184)),c=r(n(78252)),l=r(n(71426)),f=r(n(47457)),d=function(e){return{root:{flex:"1 1 auto",minWidth:0,padding:"0 16px","&:first-child":{paddingLeft:0}},inset:{"&:first-child":{paddingLeft:56}},dense:{fontSize:e.typography.pxToRem(13)},primary:{"&$textDense":{fontSize:"inherit"}},secondary:{"&$textDense":{fontSize:"inherit"}},textDense:{}}};function h(e){var t=e.children,n=e.classes,r=e.className,c=e.disableTypography,d=e.inset,h=e.primary,p=e.primaryTypographyProps,b=e.secondary,m=e.secondaryTypographyProps,g=e.theme,v=(0,o.default)(e,["children","classes","className","disableTypography","inset","primary","primaryTypographyProps","secondary","secondaryTypographyProps","theme"]);return s.default.createElement(f.default.Consumer,null,function(e){var o,f=e.dense,y=null!=h?h:t;null==y||y.type===l.default||c||(y=s.default.createElement(l.default,(0,i.default)({variant:g.typography.useNextVariants?"body1":"subheading",className:(0,u.default)(n.primary,(0,a.default)({},n.textDense,f)),component:"span"},p),y));var w=b;return null==w||w.type===l.default||c||(w=s.default.createElement(l.default,(0,i.default)({className:(0,u.default)(n.secondary,(0,a.default)({},n.textDense,f)),color:"textSecondary"},m),w)),s.default.createElement("div",(0,i.default)({className:(0,u.default)(n.root,(o={},(0,a.default)(o,n.dense,f),(0,a.default)(o,n.inset,d),o),r)},v),y,w)})}t.styles=d,h.defaultProps={disableTypography:!1,inset:!1};var p=(0,c.default)(d,{name:"MuiListItemText",withTheme:!0})(h);t.default=p},87591(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(73390))},95890(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294));r(n(45697));var d=r(n(73935)),h=r(n(44825)),p=r(n(78252)),b=r(n(50810)),m=r(n(34980)),g={vertical:"top",horizontal:"right"},v={vertical:"top",horizontal:"left"},y={paper:{maxHeight:"calc(100% - 96px)",WebkitOverflowScrolling:"touch"}};t.styles=y;var w=function(e){function t(){(0,o.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;a=0?t.children[e].focus():t.firstChild.focus())}},{key:"resetTabIndex",value:function(){for(var e=this.listRef,t=(0,h.default)(e).activeElement,n=[],r=0;r0&&void 0!==arguments[0]?arguments[0]:{};(0,i.default)(this,e);var n=t.hideSiblingNodes,r=void 0===n||n,a=t.handleContainerOverflow,o=void 0===a||a;this.hideSiblingNodes=r,this.handleContainerOverflow=o,this.modals=[],this.data=[]}return(0,a.default)(e,[{key:"add",value:function(e,t){var n=this.modals.indexOf(e);if(-1!==n)return n;n=this.modals.length,this.modals.push(e),e.modalRef&&(0,l.ariaHidden)(e.modalRef,!1),this.hideSiblingNodes&&(0,l.ariaHiddenSiblings)(t,e.mountNode,e.modalRef,!0);var r=f(this.data,function(e){return e.container===t});if(-1!==r)return this.data[r].modals.push(e),n;var i={modals:[e],container:t,overflowing:(0,c.default)(t),prevPaddings:[]};return this.data.push(i),n}},{key:"mount",value:function(e){var t=f(this.data,function(t){return -1!==t.modals.indexOf(e)}),n=this.data[t];!n.style&&this.handleContainerOverflow&&h(n)}},{key:"remove",value:function(e){var t=this.modals.indexOf(e);if(-1===t)return t;var n=f(this.data,function(t){return -1!==t.modals.indexOf(e)}),r=this.data[n];if(r.modals.splice(r.modals.indexOf(e),1),this.modals.splice(t,1),0===r.modals.length)this.handleContainerOverflow&&p(r),e.modalRef&&(0,l.ariaHidden)(e.modalRef,!0),this.hideSiblingNodes&&(0,l.ariaHiddenSiblings)(r.container,e.mountNode,e.modalRef,!1),this.data.splice(n,1);else if(this.hideSiblingNodes){var i=r.modals[r.modals.length-1];i.modalRef&&(0,l.ariaHidden)(i.modalRef,!1)}return t}},{key:"isTopModal",value:function(e){return!!this.modals.length&&this.modals[this.modals.length-1]===e}}]),e}();t.default=b},55536(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(t,"ModalManager",{enumerable:!0,get:function(){return a.default}});var i=r(n(58228)),a=r(n(2158))},16575(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.isBody=s,t.default=u;var i=r(n(7624)),a=r(n(16143)),o=r(n(62614));function s(e){return e&&"body"===e.tagName.toLowerCase()}function u(e){var t=(0,a.default)(e),n=(0,o.default)(t);if(!(0,i.default)(t)&&!s(e))return e.scrollHeight>e.clientHeight;var r=n.getComputedStyle(t.body),u=parseInt(r.getPropertyValue("margin-left"),10),c=parseInt(r.getPropertyValue("margin-right"),10);return u+t.body.clientWidth+c0?.75*r+8:0;return s.default.createElement("fieldset",(0,a.default)({"aria-hidden":!0,style:(0,a.default)((0,i.default)({},"padding".concat((0,l.capitalize)(p)),8+(c?0:b/2)),f),className:(0,u.default)(t.root,n)},h),s.default.createElement("legend",{className:t.legend,style:{width:c?b:.01}},s.default.createElement("span",{dangerouslySetInnerHTML:{__html:""}})))}t.styles=f;var h=(0,c.withStyles)(f,{name:"MuiPrivateNotchedOutline",withTheme:!0})(d);t.default=h},96405(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184));n(55252);var u=r(n(67598)),c=r(n(21142)),l=r(n(78252)),f=function(e){var t="light"===e.palette.type?"rgba(0, 0, 0, 0.23)":"rgba(255, 255, 255, 0.23)";return{root:{position:"relative","& $notchedOutline":{borderColor:t},"&:hover:not($disabled):not($focused):not($error) $notchedOutline":{borderColor:e.palette.text.primary,"@media (hover: none)":{borderColor:t}},"&$focused $notchedOutline":{borderColor:e.palette.primary.main,borderWidth:2},"&$error $notchedOutline":{borderColor:e.palette.error.main},"&$disabled $notchedOutline":{borderColor:e.palette.action.disabled}},focused:{},disabled:{},adornedStart:{paddingLeft:14},adornedEnd:{paddingRight:14},error:{},multiline:{padding:"18.5px 14px",boxSizing:"border-box"},notchedOutline:{},input:{padding:"18.5px 14px"},inputMarginDense:{paddingTop:15,paddingBottom:15},inputMultiline:{padding:0},inputAdornedStart:{paddingLeft:0},inputAdornedEnd:{paddingRight:0}}};function d(e){var t=e.classes,n=e.labelWidth,r=e.notched,l=(0,a.default)(e,["classes","labelWidth","notched"]);return o.default.createElement(u.default,(0,i.default)({renderPrefix:function(e){return o.default.createElement(c.default,{className:t.notchedOutline,labelWidth:n,notched:void 0!==r?r:Boolean(e.startAdornment||e.filled||e.focused)})},classes:(0,i.default)({},t,{root:(0,s.default)(t.root,t.underline),notchedOutline:null})},l))}t.styles=f,u.default.defaultProps={fullWidth:!1,inputComponent:"input",multiline:!1,type:"text"},d.muiName="Input";var h=(0,l.default)(f,{name:"MuiOutlinedInput"})(d);t.default=h},59537(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(96405))},30083(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(59713)),a=r(n(6479)),o=r(n(67154)),s=r(n(67294));r(n(45697));var u=r(n(94184));r(n(42473)),n(55252);var c=r(n(78252)),l=function(e){var t={};return e.shadows.forEach(function(e,n){t["elevation".concat(n)]={boxShadow:e}}),(0,o.default)({root:{backgroundColor:e.palette.background.paper},rounded:{borderRadius:e.shape.borderRadius}},t)};function f(e){var t=e.classes,n=e.className,r=e.component,c=e.square,l=e.elevation,f=(0,a.default)(e,["classes","className","component","square","elevation"]),d=(0,u.default)(t.root,t["elevation".concat(l)],(0,i.default)({},t.rounded,!c),n);return s.default.createElement(r,(0,o.default)({className:d},f))}t.styles=l,f.defaultProps={component:"div",elevation:2,square:!1};var d=(0,c.default)(l,{name:"MuiPaper"})(f);t.default=d},68821(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(30083))},64224(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294));r(n(45697));var d=r(n(73935));r(n(42473));var h=r(n(20296)),p=r(n(96421));n(55252);var b=r(n(16143)),m=r(n(62614)),g=n(98741),v=r(n(78252)),y=r(n(55536)),w=r(n(261)),_=r(n(68821));function E(e,t){var n=0;return"number"==typeof t?n=t:"center"===t?n=e.height/2:"bottom"===t&&(n=e.height),n}function S(e,t){var n=0;return"number"==typeof t?n=t:"center"===t?n=e.width/2:"right"===t&&(n=e.width),n}function k(e){return[e.horizontal,e.vertical].map(function(e){return"number"==typeof e?"".concat(e,"px"):e}).join(" ")}function x(e,t){for(var n=t,r=0;n&&n!==e;)r+=(n=n.parentNode).scrollTop;return r}function T(e){return"function"==typeof e?e():e}var M={paper:{position:"absolute",overflowY:"auto",overflowX:"hidden",minWidth:16,minHeight:16,maxWidth:"calc(100% - 32px)",maxHeight:"calc(100% - 32px)",outline:"none"}};t.styles=M;var O=function(e){function t(){var e;return(0,o.default)(this,t),(e=(0,u.default)(this,(0,c.default)(t).call(this))).handleGetOffsetTop=E,e.handleGetOffsetLeft=S,e.componentWillUnmount=function(){e.handleResize.clear()},e.setPositioningStyles=function(t){var n=e.getPositioningStyle(t);null!==n.top&&(t.style.top=n.top),null!==n.left&&(t.style.left=n.left),t.style.transformOrigin=n.transformOrigin},e.getPositioningStyle=function(t){var n=e.props,r=n.anchorEl,i=n.anchorReference,a=n.marginThreshold,o=e.getContentAnchorOffset(t),s={width:t.offsetWidth,height:t.offsetHeight},u=e.getTransformOrigin(s,o);if("none"===i)return{top:null,left:null,transformOrigin:k(u)};var c=e.getAnchorOffset(o),l=c.top-u.vertical,f=c.left-u.horizontal,d=l+s.height,h=f+s.width,p=(0,m.default)(T(r)),b=p.innerHeight-a,g=p.innerWidth-a;if(lb){var y=d-b;l-=y,u.vertical+=y}if(fg){var _=h-g;f-=_,u.horizontal+=_}return{top:"".concat(l,"px"),left:"".concat(f,"px"),transformOrigin:k(u)}},e.handleEntering=function(t){e.props.onEntering&&e.props.onEntering(t),e.setPositioningStyles(t)},"undefined"!=typeof window&&(e.handleResize=(0,h.default)(function(){e.props.open&&e.setPositioningStyles(e.paperRef)},166)),e}return(0,l.default)(t,e),(0,s.default)(t,[{key:"componentDidMount",value:function(){this.props.action&&this.props.action({updatePosition:this.handleResize})}},{key:"getAnchorOffset",value:function(e){var t=this.props,n=t.anchorEl,r=t.anchorOrigin,i=t.anchorReference,a=t.anchorPosition;if("anchorPosition"===i)return a;var o=(T(n)||(0,b.default)(this.paperRef).body).getBoundingClientRect(),s=0===e?r.vertical:"center";return{top:o.top+this.handleGetOffsetTop(o,s),left:o.left+this.handleGetOffsetLeft(o,r.horizontal)}}},{key:"getContentAnchorOffset",value:function(e){var t=this.props,n=t.getContentAnchorEl,r=t.anchorReference,i=0;if(n&&"anchorEl"===r){var a=n(e);if(a&&e.contains(a)){var o=x(e,a);i=a.offsetTop+a.clientHeight/2-o||0}}return i}},{key:"getTransformOrigin",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=this.props.transformOrigin;return{vertical:this.handleGetOffsetTop(e,n.vertical)+t,horizontal:this.handleGetOffsetLeft(e,n.horizontal)}}},{key:"render",value:function(){var e=this,t=this.props,n=(t.action,t.anchorEl),r=(t.anchorOrigin,t.anchorPosition,t.anchorReference,t.children),o=t.classes,s=t.container,u=t.elevation,c=(t.getContentAnchorEl,t.marginThreshold,t.ModalClasses),l=t.onEnter,h=t.onEntered,m=(t.onEntering,t.onExit),v=t.onExited,w=t.onExiting,E=t.open,S=t.PaperProps,k=t.role,x=(t.transformOrigin,t.TransitionComponent),M=t.transitionDuration,O=t.TransitionProps,A=void 0===O?{}:O,L=(0,a.default)(t,["action","anchorEl","anchorOrigin","anchorPosition","anchorReference","children","classes","container","elevation","getContentAnchorEl","marginThreshold","ModalClasses","onEnter","onEntered","onEntering","onExit","onExited","onExiting","open","PaperProps","role","transformOrigin","TransitionComponent","transitionDuration","TransitionProps"]),C=M;"auto"!==M||x.muiSupportAuto||(C=void 0);var I=s||(n?(0,b.default)(T(n)).body:void 0);return f.default.createElement(y.default,(0,i.default)({classes:c,container:I,open:E,BackdropProps:{invisible:!0}},L),f.default.createElement(x,(0,i.default)({appear:!0,in:E,onEnter:l,onEntered:h,onExit:m,onExited:v,onExiting:w,role:k,timeout:C},A,{onEntering:(0,g.createChainedFunction)(this.handleEntering,A.onEntering)}),f.default.createElement(_.default,(0,i.default)({className:o.paper,elevation:u,ref:function(t){e.paperRef=d.default.findDOMNode(t)}},S),f.default.createElement(p.default,{target:"window",onResize:this.handleResize}),r)))}}]),t}(f.default.Component);O.defaultProps={anchorReference:"anchorEl",anchorOrigin:{vertical:"top",horizontal:"left"},elevation:8,marginThreshold:16,transformOrigin:{vertical:"top",horizontal:"left"},TransitionComponent:w.default,transitionDuration:"auto"};var A=(0,v.default)(M,{name:"MuiPopover"})(O);t.default=A},50810(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(64224))},24693(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(6479)),a=r(n(67154)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(81506)),d=r(n(67294)),h=r(n(73935));r(n(45697));var p=r(n(28981)),b=r(n(25649));function m(e){if("rtl"!==("undefined"!=typeof window&&document.body.getAttribute("dir")||"ltr"))return e;switch(e){case"bottom-end":return"bottom-start";case"bottom-start":return"bottom-end";case"top-end":return"top-start";case"top-start":return"top-end";default:return e}}function g(e){return"function"==typeof e?e():e}var v=function(e){function t(e){var n;return(0,o.default)(this,t),(n=(0,u.default)(this,(0,c.default)(t).call(this))).handleOpen=function(){var e=n.props,t=e.anchorEl,r=e.modifiers,i=e.open,o=e.placement,s=e.popperOptions,u=void 0===s?{}:s,c=e.disablePortal,l=h.default.findDOMNode((0,f.default)((0,f.default)(n)));l&&t&&i&&(n.popper&&(n.popper.destroy(),n.popper=null),n.popper=new p.default(g(t),l,(0,a.default)({placement:m(o)},u,{modifiers:(0,a.default)({},c?{}:{preventOverflow:{boundariesElement:"window"}},r,u.modifiers),onCreate:n.handlePopperUpdate,onUpdate:n.handlePopperUpdate})))},n.handlePopperUpdate=function(e){e.placement!==n.state.placement&&n.setState({placement:e.placement})},n.handleExited=function(){n.setState({exited:!0}),n.handleClose()},n.handleClose=function(){n.popper&&(n.popper.destroy(),n.popper=null)},n.state={exited:!e.open},n}return(0,l.default)(t,e),(0,s.default)(t,[{key:"componentDidUpdate",value:function(e){e.open===this.props.open||this.props.open||this.props.transition||this.handleClose(),(e.open!==this.props.open||e.anchorEl!==this.props.anchorEl||e.popperOptions!==this.props.popperOptions||e.modifiers!==this.props.modifiers||e.disablePortal!==this.props.disablePortal||e.placement!==this.props.placement)&&this.handleOpen()}},{key:"componentWillUnmount",value:function(){this.handleClose()}},{key:"render",value:function(){var e=this.props,t=(e.anchorEl,e.children),n=e.container,r=e.disablePortal,o=e.keepMounted,s=(e.modifiers,e.open),u=e.placement,c=(e.popperOptions,e.transition),l=(0,i.default)(e,["anchorEl","children","container","disablePortal","keepMounted","modifiers","open","placement","popperOptions","transition"]),f=this.state,h=f.exited,p=f.placement;if(!o&&!s&&(!c||h))return null;var g={placement:p||m(u)};return c&&(g.TransitionProps={in:s,onExited:this.handleExited}),d.default.createElement(b.default,{onRendered:this.handleOpen,disablePortal:r,container:n},d.default.createElement("div",(0,a.default)({role:"tooltip",style:{position:"absolute"}},l),"function"==typeof t?t(g):t))}}],[{key:"getDerivedStateFromProps",value:function(e){return e.open?{exited:!1}:e.transition?null:{exited:!0}}}]),t}(d.default.Component);v.defaultProps={disablePortal:!1,placement:"bottom",transition:!1};var y=v;t.default=y},60111(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(24693))},92261(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(34575)),a=r(n(93913)),o=r(n(78585)),s=r(n(29754)),u=r(n(2205)),c=r(n(67294)),l=r(n(73935));r(n(45697));var f=r(n(16143));function d(e,t){return e="function"==typeof e?e():e,l.default.findDOMNode(e)||t}function h(e){return(0,f.default)(l.default.findDOMNode(e))}n(55252);var p=function(e){function t(){(0,i.default)(this,t);for(var e,n,r=arguments.length,a=Array(r),u=0;u1;n.state.labelWrapped!==e&&n.setState({labelWrapped:e})}},n}return(0,c.default)(t,e),(0,o.default)(t,[{key:"componentDidMount",value:function(){this.checkTextWrap()}},{key:"componentDidUpdate",value:function(e,t){this.state.labelWrapped===t.labelWrapped&&this.checkTextWrap()}},{key:"render",value:function(){var e,t,n=this,r=this.props,a=r.classes,o=r.className,s=r.disabled,u=r.fullWidth,c=r.icon,p=r.indicator,g=r.label,v=(r.onChange,r.selected),y=r.textColor,w=(r.value,(0,i.default)(r,["classes","className","disabled","fullWidth","icon","indicator","label","onChange","selected","textColor","value"]));return void 0!==g&&(e=d.default.createElement("span",{className:a.labelContainer},d.default.createElement("span",{className:(0,h.default)(a.label,(0,l.default)({},a.labelWrapped,this.state.labelWrapped)),ref:function(e){n.labelRef=e}},g))),d.default.createElement(b.default,(0,f.default)({focusRipple:!0,className:(0,h.default)(a.root,a["textColor".concat((0,m.capitalize)(y))],(t={},(0,l.default)(t,a.disabled,s),(0,l.default)(t,a.selected,v),(0,l.default)(t,a.labelIcon,c&&e),(0,l.default)(t,a.fullWidth,u),t),o),role:"tab","aria-selected":v,disabled:s},w,{onClick:this.handleChange}),d.default.createElement("span",{className:a.wrapper},c,e),p)}}]),t}(d.default.Component);v.defaultProps={disabled:!1,textColor:"inherit"};var y=(0,p.default)(g,{name:"MuiTab"})(v);t.default=y},75759(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(70201))},7575(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294));r(n(45697));var d=r(n(94184));n(55252);var h=r(n(78252)),p=r(n(82577)),b=function(e){return{root:{display:"table",fontFamily:e.typography.fontFamily,width:"100%",borderCollapse:"collapse",borderSpacing:0}}};t.styles=b;var m=function(e){function t(){(0,o.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;ai&&n(null,i)}},{key:"render",value:function(){var e,t=this.props,n=t.ActionsComponent,r=t.backIconButtonProps,o=t.classes,s=t.colSpan,u=t.component,c=t.count,l=t.labelDisplayedRows,d=t.labelRowsPerPage,y=t.nextIconButtonProps,w=t.onChangePage,_=t.onChangeRowsPerPage,E=t.page,S=t.rowsPerPage,k=t.rowsPerPageOptions,x=t.SelectProps,T=void 0===x?{}:x,M=(0,a.default)(t,["ActionsComponent","backIconButtonProps","classes","colSpan","component","count","labelDisplayedRows","labelRowsPerPage","nextIconButtonProps","onChangePage","onChangeRowsPerPage","page","rowsPerPage","rowsPerPageOptions","SelectProps"]);(u===m.default||"td"===u)&&(e=s||1e3);var O=T.native?"option":p.default;return f.default.createElement(u,(0,i.default)({className:o.root,colSpan:e},M),f.default.createElement(g.default,{className:o.toolbar},f.default.createElement("div",{className:o.spacer}),k.length>1&&f.default.createElement(v.default,{color:"inherit",variant:"caption",className:o.caption},d),k.length>1&&f.default.createElement(b.default,(0,i.default)({classes:{root:o.selectRoot,select:o.select,icon:o.selectIcon},input:f.default.createElement(h.default,{className:o.input}),value:S,onChange:_},T),k.map(function(e){return f.default.createElement(O,{className:o.menuItem,key:e,value:e},e)})),f.default.createElement(v.default,{color:"inherit",variant:"caption",className:o.caption},l({from:0===c?0:E*S+1,to:Math.min(c,(E+1)*S),count:c,page:E})),f.default.createElement(n,{className:o.actions,backIconButtonProps:r,count:c,nextIconButtonProps:y,onChangePage:w,page:E,rowsPerPage:S})))}}]),t}(f.default.Component);_.defaultProps={ActionsComponent:y.default,component:m.default,labelDisplayedRows:function(e){var t=e.from,n=e.to,r=e.count;return"".concat(t,"-").concat(n," of ").concat(r)},labelRowsPerPage:"Rows per page:",rowsPerPageOptions:[10,25,50,100]};var E=(0,d.default)(w,{name:"MuiTablePagination"})(_);t.default=E},32844(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294));r(n(45697));var d=r(n(86861)),h=r(n(43836)),p=r(n(82313)),b=r(n(81701)),m=f.default.createElement(h.default,null),g=f.default.createElement(d.default,null),v=f.default.createElement(d.default,null),y=f.default.createElement(h.default,null),w=function(e){function t(){(0,o.default)(this,t);for(var e,n,r=arguments.length,i=Array(r),a=0;a=Math.ceil(n/s)-1,color:"inherit"},r),"rtl"===u.direction?v:y))}}]),t}(f.default.Component),_=(0,p.default)()(w);t.default=_},18217(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(71744))},86424(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=r(n(27628)),f=function(e){return{root:{color:"inherit",display:"table-row",height:48,verticalAlign:"middle",outline:"none","&$selected":{backgroundColor:"light"===e.palette.type?"rgba(0, 0, 0, 0.04)":"rgba(255, 255, 255, 0.08)"},"&$hover:hover":{backgroundColor:"light"===e.palette.type?"rgba(0, 0, 0, 0.07)":"rgba(255, 255, 255, 0.14)"}},selected:{},hover:{},head:{height:56},footer:{height:56}}};function d(e){var t=e.classes,n=e.className,r=e.component,c=e.hover,f=e.selected,d=(0,o.default)(e,["classes","className","component","hover","selected"]);return s.default.createElement(l.default.Consumer,null,function(e){var o,l=(0,u.default)(t.root,(o={},(0,a.default)(o,t.head,e&&"head"===e.variant),(0,a.default)(o,t.footer,e&&"footer"===e.variant),(0,a.default)(o,t.hover,c),(0,a.default)(o,t.selected,f),o),n);return s.default.createElement(r,(0,i.default)({className:l},d))})}t.styles=f,d.defaultProps={component:"tr",hover:!1,selected:!1};var h=(0,c.default)(f,{name:"MuiTableRow"})(d);t.default=h},17175(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(86424))},28550(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(34575)),a=r(n(93913)),o=r(n(78585)),s=r(n(29754)),u=r(n(2205)),c=r(n(67294));r(n(45697));var l,f=r(n(96421)),d=r(n(20296)),h={width:90,height:90,position:"absolute",top:-9e3,overflow:"scroll",msOverflowStyle:"scrollbar"},p=function(e){function t(){var e;return(0,i.default)(this,t),(e=(0,o.default)(this,(0,s.default)(t).call(this))).handleRef=function(t){e.nodeRef=t},e.setMeasurements=function(){var t=e.nodeRef;t&&(e.scrollbarHeight=t.offsetHeight-t.clientHeight)},"undefined"!=typeof window&&(e.handleResize=(0,d.default)(function(){var t=e.scrollbarHeight;e.setMeasurements(),t!==e.scrollbarHeight&&e.props.onChange(e.scrollbarHeight)},166)),e}return(0,u.default)(t,e),(0,a.default)(t,[{key:"componentDidMount",value:function(){this.setMeasurements(),this.props.onChange(this.scrollbarHeight)}},{key:"componentWillUnmount",value:function(){this.handleResize.clear()}},{key:"render",value:function(){return c.default.createElement(c.default.Fragment,null,c.default.createElement(f.default,{target:"window",onResize:this.handleResize}),c.default.createElement("div",{style:h,ref:this.handleRef}))}}]),t}(c.default.Component);t.default=p},12417(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184)),u=r(n(78252)),c=n(98741),l=function(e){return{root:{position:"absolute",height:2,bottom:0,width:"100%",transition:e.transitions.create()},colorPrimary:{backgroundColor:e.palette.primary.main},colorSecondary:{backgroundColor:e.palette.secondary.main}}};function f(e){var t=e.classes,n=e.className,r=e.color,u=(0,a.default)(e,["classes","className","color"]);return o.default.createElement("span",(0,i.default)({className:(0,s.default)(t.root,t["color".concat((0,c.capitalize)(r))],n)},u))}t.styles=l;var d=(0,u.default)(l,{name:"MuiPrivateTabIndicator"})(f);t.default=d},69583(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(67294));r(n(45697));var s=r(n(94184)),u=r(n(86861)),c=r(n(43836)),l=r(n(78252)),f=r(n(16070)),d={root:{color:"inherit",width:56,flexShrink:0}};t.styles=d;var h=o.default.createElement(u.default,null),p=o.default.createElement(c.default,null);function b(e){var t=e.classes,n=e.className,r=e.direction,u=e.onClick,c=e.visible,l=(0,a.default)(e,["classes","className","direction","onClick","visible"]),d=(0,s.default)(t.root,n);return c?o.default.createElement(f.default,(0,i.default)({className:d,onClick:u,tabIndex:-1},l),"left"===r?h:p):o.default.createElement("div",{className:d})}b.defaultProps={visible:!0};var m=(0,l.default)(d,{name:"MuiPrivateTabScrollButton"})(b);t.default=m},89172(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(59713)),d=r(n(67294));r(n(45697)),r(n(42473));var h=r(n(94184)),p=r(n(96421)),b=r(n(20296)),m=n(46417);n(55252);var g=r(n(13329)),v=r(n(28550)),y=r(n(78252)),w=r(n(12417)),_=r(n(69583));r(n(346));var E=function(e){return{root:{overflow:"hidden",minHeight:48,WebkitOverflowScrolling:"touch"},flexContainer:{display:"flex"},centered:{justifyContent:"center"},scroller:{position:"relative",display:"inline-block",flex:"1 1 auto",whiteSpace:"nowrap"},fixed:{overflowX:"hidden",width:"100%"},scrollable:{overflowX:"scroll"},scrollButtons:{},scrollButtonsAuto:(0,f.default)({},e.breakpoints.down("xs"),{display:"none"}),indicator:{}}};t.styles=E;var S=function(e){function t(){var e;return(0,o.default)(this,t),(e=(0,u.default)(this,(0,c.default)(t).call(this))).state={indicatorStyle:{},scrollerStyle:{marginBottom:0},showLeftScroll:!1,showRightScroll:!1,mounted:!1},e.getConditionalElements=function(){var t=e.props,n=t.classes,r=t.scrollable,i=t.ScrollButtonComponent,a=t.scrollButtons,o=t.theme,s=t.variant,u={},c="scrollable"===s||r;u.scrollbarSizeListener=c?d.default.createElement(v.default,{onChange:e.handleScrollbarSizeChange}):null;var l=c&&("auto"===a||"on"===a);return u.scrollButtonLeft=l?d.default.createElement(i,{direction:o&&"rtl"===o.direction?"right":"left",onClick:e.handleLeftScrollClick,visible:e.state.showLeftScroll,className:(0,h.default)(n.scrollButtons,(0,f.default)({},n.scrollButtonsAuto,"auto"===a))}):null,u.scrollButtonRight=l?d.default.createElement(i,{direction:o&&"rtl"===o.direction?"left":"right",onClick:e.handleRightScrollClick,visible:e.state.showRightScroll,className:(0,h.default)(n.scrollButtons,(0,f.default)({},n.scrollButtonsAuto,"auto"===a))}):null,u},e.getTabsMeta=function(t,n){if(e.tabsRef){var r,i,a=e.tabsRef.getBoundingClientRect();r={clientWidth:e.tabsRef.clientWidth,scrollLeft:e.tabsRef.scrollLeft,scrollLeftNormalized:(0,m.getNormalizedScrollLeft)(e.tabsRef,n),scrollWidth:e.tabsRef.scrollWidth,left:a.left,right:a.right}}if(e.tabsRef&&!1!==t){var o=e.tabsRef.children[0].children;if(o.length>0){var s=o[e.valueToIndex.get(t)];i=s?s.getBoundingClientRect():null}}return{tabsMeta:r,tabMeta:i}},e.handleLeftScrollClick=function(){e.moveTabsScroll(-e.tabsRef.clientWidth)},e.handleRightScrollClick=function(){e.moveTabsScroll(e.tabsRef.clientWidth)},e.handleScrollbarSizeChange=function(t){e.setState({scrollerStyle:{marginBottom:-t}})},e.moveTabsScroll=function(t){var n=e.props.theme,r="rtl"===n.direction?-1:1,i=e.tabsRef.scrollLeft+t*r,a="rtl"===n.direction&&"reverse"===(0,m.detectScrollType)()?-1:1;e.scroll(a*i)},e.scrollSelectedIntoView=function(){var t=e.props,n=t.theme,r=t.value,i=e.getTabsMeta(r,n.direction),a=i.tabsMeta,o=i.tabMeta;if(o&&a){if(o.lefta.right){var u=a.scrollLeft+(o.right-a.right);e.scroll(u)}}},e.scroll=function(t){(0,g.default)("scrollLeft",e.tabsRef,t)},e.updateScrollButtonState=function(){var t=e.props,n=t.scrollable,r=t.scrollButtons,i=t.theme;if(("scrollable"===t.variant||n)&&"off"!==r){var a=e.tabsRef,o=a.scrollWidth,s=a.clientWidth,u=(0,m.getNormalizedScrollLeft)(e.tabsRef,i.direction),c="rtl"===i.direction?o>s+u:u>0,l="rtl"===i.direction?u>0:o>s+u;(c!==e.state.showLeftScroll||l!==e.state.showRightScroll)&&e.setState({showLeftScroll:c,showRightScroll:l})}},"undefined"!=typeof window&&(e.handleResize=(0,b.default)(function(){e.updateIndicatorState(e.props),e.updateScrollButtonState()},166),e.handleTabsScroll=(0,b.default)(function(){e.updateScrollButtonState()},166)),e}return(0,l.default)(t,e),(0,s.default)(t,[{key:"componentDidMount",value:function(){this.setState({mounted:!0}),this.updateIndicatorState(this.props),this.updateScrollButtonState(),this.props.action&&this.props.action({updateIndicator:this.handleResize})}},{key:"componentDidUpdate",value:function(e,t){this.updateIndicatorState(this.props),this.updateScrollButtonState(),this.state.indicatorStyle!==t.indicatorStyle&&this.scrollSelectedIntoView()}},{key:"componentWillUnmount",value:function(){this.handleResize.clear(),this.handleTabsScroll.clear()}},{key:"updateIndicatorState",value:function(e){var t=e.theme,n=e.value,r=this.getTabsMeta(n,t.direction),i=r.tabsMeta,a=r.tabMeta,o=0;if(a&&i){var s="rtl"===t.direction?i.scrollLeftNormalized+i.clientWidth-i.scrollWidth:i.scrollLeft;o=Math.round(a.left-i.left+s)}var u={left:o,width:a?Math.round(a.width):0};u.left===this.state.indicatorStyle.left&&u.width===this.state.indicatorStyle.width||isNaN(u.left)||isNaN(u.width)||this.setState({indicatorStyle:u})}},{key:"render",value:function(){var e,t=this,n=this.props,r=(n.action,n.centered),o=n.children,s=n.classes,u=n.className,c=n.component,l=n.fullWidth,b=void 0!==l&&l,m=n.indicatorColor,g=n.onChange,v=n.scrollable,y=void 0!==v&&v,_=(n.ScrollButtonComponent,n.scrollButtons,n.TabIndicatorProps),E=void 0===_?{}:_,S=n.textColor,k=(n.theme,n.value),x=n.variant,T=(0,a.default)(n,["action","centered","children","classes","className","component","fullWidth","indicatorColor","onChange","scrollable","ScrollButtonComponent","scrollButtons","TabIndicatorProps","textColor","theme","value","variant"]),M="scrollable"===x||y,O=(0,h.default)(s.root,u),A=(0,h.default)(s.flexContainer,(0,f.default)({},s.centered,r&&!M)),L=(0,h.default)(s.scroller,(e={},(0,f.default)(e,s.fixed,!M),(0,f.default)(e,s.scrollable,M),e)),C=d.default.createElement(w.default,(0,i.default)({className:s.indicator,color:m},E,{style:(0,i.default)({},this.state.indicatorStyle,E.style)}));this.valueToIndex=new Map;var I=0,D=d.default.Children.map(o,function(e){if(!d.default.isValidElement(e))return null;var n=void 0===e.props.value?I:e.props.value;t.valueToIndex.set(n,I);var r=n===k;return I+=1,d.default.cloneElement(e,{fullWidth:"fullWidth"===x||b,indicator:r&&!t.state.mounted&&C,selected:r,onChange:g,textColor:S,value:n})}),N=this.getConditionalElements();return d.default.createElement(c,(0,i.default)({className:O},T),d.default.createElement(p.default,{target:"window",onResize:this.handleResize}),N.scrollbarSizeListener,d.default.createElement("div",{className:s.flexContainer},N.scrollButtonLeft,d.default.createElement("div",{className:L,style:this.state.scrollerStyle,ref:function(e){t.tabsRef=e},role:"tablist",onScroll:this.handleTabsScroll},d.default.createElement("div",{className:A},D),this.state.mounted&&C),N.scrollButtonRight))}}]),t}(d.default.Component);S.defaultProps={centered:!1,component:"div",indicatorColor:"secondary",ScrollButtonComponent:_.default,scrollButtons:"auto",textColor:"inherit",variant:"standard"};var k=(0,y.default)(E,{name:"MuiTabs",withTheme:!0})(S);t.default=k},12794(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(89172))},78592(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294)),d=r(n(73935));r(n(42473)),r(n(45697));var h=r(n(54846)),p=r(n(1402)),b=r(n(59537)),m=r(n(23153)),g=r(n(85461)),v=r(n(76023)),y=r(n(11970)),w={standard:h.default,filled:p.default,outlined:b.default},_=function(e){function t(e){var n;return(0,o.default)(this,t),(n=(0,u.default)(this,(0,c.default)(t).call(this,e))).labelRef=f.default.createRef(),n}return(0,l.default)(t,e),(0,s.default)(t,[{key:"componentDidMount",value:function(){"outlined"===this.props.variant&&(this.labelNode=d.default.findDOMNode(this.labelRef.current),this.forceUpdate())}},{key:"render",value:function(){var e=this.props,t=e.autoComplete,n=e.autoFocus,r=e.children,o=e.className,s=e.defaultValue,u=e.error,c=e.FormHelperTextProps,l=e.fullWidth,d=e.helperText,h=e.id,p=e.InputLabelProps,b=e.inputProps,_=e.InputProps,E=e.inputRef,S=e.label,k=e.multiline,x=e.name,T=e.onBlur,M=e.onChange,O=e.onFocus,A=e.placeholder,L=e.required,C=e.rows,I=e.rowsMax,D=e.select,N=e.SelectProps,P=e.type,R=e.value,j=e.variant,F=(0,a.default)(e,["autoComplete","autoFocus","children","className","defaultValue","error","FormHelperTextProps","fullWidth","helperText","id","InputLabelProps","inputProps","InputProps","inputRef","label","multiline","name","onBlur","onChange","onFocus","placeholder","required","rows","rowsMax","select","SelectProps","type","value","variant"]),Y={};"outlined"===j&&(p&&void 0!==p.shrink&&(Y.notched=p.shrink),Y.labelWidth=this.labelNode&&this.labelNode.offsetWidth||0);var B=d&&h?"".concat(h,"-helper-text"):void 0,U=w[j],H=f.default.createElement(U,(0,i.default)({"aria-describedby":B,autoComplete:t,autoFocus:n,defaultValue:s,fullWidth:l,multiline:k,name:x,rows:C,rowsMax:I,type:P,value:R,id:h,inputRef:E,onBlur:T,onChange:M,onFocus:O,placeholder:A,inputProps:b},Y,_));return f.default.createElement(g.default,(0,i.default)({className:o,error:u,fullWidth:l,required:L,variant:j},F),S&&f.default.createElement(m.default,(0,i.default)({htmlFor:h,ref:this.labelRef},p),S),D?f.default.createElement(y.default,(0,i.default)({"aria-describedby":B,value:R,input:H},N),r):H,d&&f.default.createElement(v.default,(0,i.default)({id:B},c),d))}}]),t}(f.default.Component);_.defaultProps={required:!1,select:!1,variant:"standard"};var E=_;t.default=E},60520(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(78592))},48596(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184)),c=r(n(78252)),l=function(e){return{root:{position:"relative",display:"flex",alignItems:"center"},gutters:e.mixins.gutters(),regular:e.mixins.toolbar,dense:{minHeight:48}}};function f(e){var t=e.children,n=e.classes,r=e.className,c=e.disableGutters,l=e.variant,f=(0,o.default)(e,["children","classes","className","disableGutters","variant"]),d=(0,u.default)(n.root,n[l],(0,a.default)({},n.gutters,!c),r);return s.default.createElement("div",(0,i.default)({className:d},f),t)}t.styles=l,f.defaultProps={disableGutters:!1,variant:"regular"};var d=(0,c.default)(l,{name:"MuiToolbar"})(f);t.default=d},28902(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(48596))},83065(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(59713)),d=r(n(67294));r(n(45697)),r(n(42473));var h=r(n(94184));n(55252);var p=r(n(39737)),b=r(n(78252)),m=n(98741),g=r(n(261)),v=r(n(60111)),y=function(e){return{popper:{zIndex:e.zIndex.tooltip,opacity:.9,pointerEvents:"none"},popperInteractive:{pointerEvents:"auto"},tooltip:{backgroundColor:e.palette.grey[700],borderRadius:e.shape.borderRadius,color:e.palette.common.white,fontFamily:e.typography.fontFamily,padding:"4px 8px",fontSize:e.typography.pxToRem(10),lineHeight:"".concat(e.typography.round(1.4),"em"),maxWidth:300},touch:{padding:"8px 16px",fontSize:e.typography.pxToRem(14),lineHeight:"".concat(e.typography.round(16/14),"em")},tooltipPlacementLeft:(0,f.default)({transformOrigin:"right center",margin:"0 24px "},e.breakpoints.up("sm"),{margin:"0 14px"}),tooltipPlacementRight:(0,f.default)({transformOrigin:"left center",margin:"0 24px"},e.breakpoints.up("sm"),{margin:"0 14px"}),tooltipPlacementTop:(0,f.default)({transformOrigin:"center bottom",margin:"24px 0"},e.breakpoints.up("sm"),{margin:"14px 0"}),tooltipPlacementBottom:(0,f.default)({transformOrigin:"center top",margin:"24px 0"},e.breakpoints.up("sm"),{margin:"14px 0"})}};t.styles=y;var w=function(e){function t(e){var n;return(0,o.default)(this,t),(n=(0,u.default)(this,(0,c.default)(t).call(this))).ignoreNonTouchEvents=!1,n.onRootRef=function(e){n.childrenRef=e},n.handleFocus=function(e){n.childrenRef||(n.childrenRef=e.currentTarget),n.handleEnter(e);var t=n.props.children.props;t.onFocus&&t.onFocus(e)},n.handleEnter=function(e){var t=n.props,r=t.children,i=t.enterDelay,a=r.props;"mouseover"===e.type&&a.onMouseOver&&a.onMouseOver(e),(!n.ignoreNonTouchEvents||"touchstart"===e.type)&&(n.childrenRef.setAttribute("title",""),clearTimeout(n.enterTimer),clearTimeout(n.leaveTimer),i?(e.persist(),n.enterTimer=setTimeout(function(){n.handleOpen(e)},i)):n.handleOpen(e))},n.handleOpen=function(e){n.isControlled||n.state.open||n.setState({open:!0}),n.props.onOpen&&n.props.onOpen(e)},n.handleLeave=function(e){var t=n.props,r=t.children,i=t.leaveDelay,a=r.props;"blur"===e.type&&a.onBlur&&a.onBlur(e),"mouseleave"===e.type&&a.onMouseLeave&&a.onMouseLeave(e),clearTimeout(n.enterTimer),clearTimeout(n.leaveTimer),i?(e.persist(),n.leaveTimer=setTimeout(function(){n.handleClose(e)},i)):n.handleClose(e)},n.handleClose=function(e){n.isControlled||n.setState({open:!1}),n.props.onClose&&n.props.onClose(e),clearTimeout(n.closeTimer),n.closeTimer=setTimeout(function(){n.ignoreNonTouchEvents=!1},n.props.theme.transitions.duration.shortest)},n.handleTouchStart=function(e){n.ignoreNonTouchEvents=!0;var t=n.props,r=t.children,i=t.enterTouchDelay;r.props.onTouchStart&&r.props.onTouchStart(e),clearTimeout(n.leaveTimer),clearTimeout(n.closeTimer),clearTimeout(n.touchTimer),e.persist(),n.touchTimer=setTimeout(function(){n.handleEnter(e)},i)},n.handleTouchEnd=function(e){var t=n.props,r=t.children,i=t.leaveTouchDelay;r.props.onTouchEnd&&r.props.onTouchEnd(e),clearTimeout(n.touchTimer),clearTimeout(n.leaveTimer),e.persist(),n.leaveTimer=setTimeout(function(){n.handleClose(e)},i)},n.isControlled=null!=e.open,n.state={open:null},n.isControlled||(n.state.open=!1),n}return(0,l.default)(t,e),(0,s.default)(t,[{key:"componentDidMount",value:function(){this.defaultId="mui-tooltip-".concat(Math.round(1e5*Math.random())),this.props.open&&this.forceUpdate()}},{key:"componentWillUnmount",value:function(){clearTimeout(this.closeTimer),clearTimeout(this.enterTimer),clearTimeout(this.focusTimer),clearTimeout(this.leaveTimer),clearTimeout(this.touchTimer)}},{key:"render",value:function(){var e=this,t=this.props,n=t.children,r=t.classes,o=t.disableFocusListener,s=t.disableHoverListener,u=t.disableTouchListener,c=(t.enterDelay,t.enterTouchDelay,t.id),l=t.interactive,b=(t.leaveDelay,t.leaveTouchDelay,t.onClose,t.onOpen,t.open),g=t.placement,y=t.PopperProps,w=t.theme,_=t.title,E=t.TransitionComponent,S=t.TransitionProps,k=(0,a.default)(t,["children","classes","disableFocusListener","disableHoverListener","disableTouchListener","enterDelay","enterTouchDelay","id","interactive","leaveDelay","leaveTouchDelay","onClose","onOpen","open","placement","PopperProps","theme","title","TransitionComponent","TransitionProps"]),x=this.isControlled?b:this.state.open;""===_&&(x=!1);var T=!x&&!s,M=(0,i.default)({"aria-describedby":x?c||this.defaultId:null,title:T&&"string"==typeof _?_:null},k,n.props,{className:(0,h.default)(k.className,n.props.className)});u||(M.onTouchStart=this.handleTouchStart,M.onTouchEnd=this.handleTouchEnd),s||(M.onMouseOver=this.handleEnter,M.onMouseLeave=this.handleLeave),o||(M.onFocus=this.handleFocus,M.onBlur=this.handleLeave);var O=l?{onMouseOver:M.onMouseOver,onMouseLeave:M.onMouseLeave,onFocus:M.onFocus,onBlur:M.onBlur}:{};return d.default.createElement(d.default.Fragment,null,d.default.createElement(p.default,{rootRef:this.onRootRef},d.default.cloneElement(n,M)),d.default.createElement(v.default,(0,i.default)({className:(0,h.default)(r.popper,(0,f.default)({},r.popperInteractive,l)),placement:g,anchorEl:this.childrenRef,open:x,id:M["aria-describedby"],transition:!0},O,y),function(t){var n=t.placement,a=t.TransitionProps;return d.default.createElement(E,(0,i.default)({timeout:w.transitions.duration.shorter},a,S),d.default.createElement("div",{className:(0,h.default)(r.tooltip,(0,f.default)({},r.touch,e.ignoreNonTouchEvents),r["tooltipPlacement".concat((0,m.capitalize)(n.split("-")[0]))])},_))}))}}]),t}(d.default.Component);w.defaultProps={disableFocusListener:!1,disableHoverListener:!1,disableTouchListener:!1,enterDelay:0,enterTouchDelay:1e3,interactive:!1,leaveDelay:0,leaveTouchDelay:1500,placement:"bottom",TransitionComponent:g.default};var _=(0,b.default)(y,{name:"MuiTooltip",withTheme:!0})(w);t.default=_},31657(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"Z",{enumerable:!0,get:function(){return a.default}});var a=i(n(83065))},49476(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(67294));r(n(45697));var u=r(n(94184));n(55252);var c=r(n(78252)),l=n(98741),f=function(e){return{root:{display:"block",margin:0},display4:e.typography.display4,display3:e.typography.display3,display2:e.typography.display2,display1:e.typography.display1,headline:e.typography.headline,title:e.typography.title,subheading:e.typography.subheading,body2:e.typography.body2,body1:e.typography.body1,caption:e.typography.caption,button:e.typography.button,h1:e.typography.h1,h2:e.typography.h2,h3:e.typography.h3,h4:e.typography.h4,h5:e.typography.h5,h6:e.typography.h6,subtitle1:e.typography.subtitle1,subtitle2:e.typography.subtitle2,overline:e.typography.overline,srOnly:{position:"absolute",height:1,width:1,overflow:"hidden"},alignLeft:{textAlign:"left"},alignCenter:{textAlign:"center"},alignRight:{textAlign:"right"},alignJustify:{textAlign:"justify"},noWrap:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},gutterBottom:{marginBottom:"0.35em"},paragraph:{marginBottom:16},colorInherit:{color:"inherit"},colorPrimary:{color:e.palette.primary.main},colorSecondary:{color:e.palette.secondary.main},colorTextPrimary:{color:e.palette.text.primary},colorTextSecondary:{color:e.palette.text.secondary},colorError:{color:e.palette.error.main},inline:{display:"inline"}}};t.styles=f;var d={display4:"h1",display3:"h2",display2:"h3",display1:"h4",headline:"h5",title:"h6",subheading:"subtitle1"};function h(e,t){var n=e.typography,r=t;return r||(r=n.useNextVariants?"body2":"body1"),n.useNextVariants&&(r=d[r]||r),r}var p={h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",subtitle1:"h6",subtitle2:"h6",body1:"p",body2:"p",display4:"h1",display3:"h1",display2:"h1",display1:"h1",headline:"h1",title:"h2",subheading:"h3"};function b(e){var t,n=e.align,r=e.classes,c=e.className,f=e.color,d=e.component,b=e.gutterBottom,m=e.headlineMapping,g=e.inline,v=(e.internalDeprecatedVariant,e.noWrap),y=e.paragraph,w=e.theme,_=e.variant,E=(0,o.default)(e,["align","classes","className","color","component","gutterBottom","headlineMapping","inline","internalDeprecatedVariant","noWrap","paragraph","theme","variant"]),S=h(w,_),k=(0,u.default)(r.root,(t={},(0,a.default)(t,r[S],"inherit"!==S),(0,a.default)(t,r["color".concat((0,l.capitalize)(f))],"default"!==f),(0,a.default)(t,r.noWrap,v),(0,a.default)(t,r.gutterBottom,b),(0,a.default)(t,r.paragraph,y),(0,a.default)(t,r["align".concat((0,l.capitalize)(n))],"inherit"!==n),(0,a.default)(t,r.inline,g),t),c),x=d||(y?"p":m[S]||p[S])||"span";return s.default.createElement(x,(0,i.default)({className:k},E))}b.defaultProps={align:"inherit",color:"default",gutterBottom:!1,headlineMapping:p,inline:!1,noWrap:!1,paragraph:!1};var m=(0,c.default)(f,{name:"MuiTypography",withTheme:!0})(b);t.default=m},71426(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return i.default}});var i=r(n(49476))},8070(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#fff8e1",100:"#ffecb3",200:"#ffe082",300:"#ffd54f",400:"#ffca28",500:"#ffc107",600:"#ffb300",700:"#ffa000",800:"#ff8f00",900:"#ff6f00",A100:"#ffe57f",A200:"#ffd740",A400:"#ffc400",A700:"#ffab00"};t.default=n},63259(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#e3f2fd",100:"#bbdefb",200:"#90caf9",300:"#64b5f6",400:"#42a5f5",500:"#2196f3",600:"#1e88e5",700:"#1976d2",800:"#1565c0",900:"#0d47a1",A100:"#82b1ff",A200:"#448aff",A400:"#2979ff",A700:"#2962ff"};t.default=n},38236(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#eceff1",100:"#cfd8dc",200:"#b0bec5",300:"#90a4ae",400:"#78909c",500:"#607d8b",600:"#546e7a",700:"#455a64",800:"#37474f",900:"#263238",A100:"#cfd8dc",A200:"#b0bec5",A400:"#78909c",A700:"#455a64"};t.default=n},60169(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#efebe9",100:"#d7ccc8",200:"#bcaaa4",300:"#a1887f",400:"#8d6e63",500:"#795548",600:"#6d4c41",700:"#5d4037",800:"#4e342e",900:"#3e2723",A100:"#d7ccc8",A200:"#bcaaa4",A400:"#8d6e63",A700:"#5d4037"};t.default=n},515(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={black:"#000",white:"#fff"};t.default=n},57646(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#e0f7fa",100:"#b2ebf2",200:"#80deea",300:"#4dd0e1",400:"#26c6da",500:"#00bcd4",600:"#00acc1",700:"#0097a7",800:"#00838f",900:"#006064",A100:"#84ffff",A200:"#18ffff",A400:"#00e5ff",A700:"#00b8d4"};t.default=n},50173(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#fbe9e7",100:"#ffccbc",200:"#ffab91",300:"#ff8a65",400:"#ff7043",500:"#ff5722",600:"#f4511e",700:"#e64a19",800:"#d84315",900:"#bf360c",A100:"#ff9e80",A200:"#ff6e40",A400:"#ff3d00",A700:"#dd2c00"};t.default=n},45018(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#ede7f6",100:"#d1c4e9",200:"#b39ddb",300:"#9575cd",400:"#7e57c2",500:"#673ab7",600:"#5e35b1",700:"#512da8",800:"#4527a0",900:"#311b92",A100:"#b388ff",A200:"#7c4dff",A400:"#651fff",A700:"#6200ea"};t.default=n},47559(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#e8f5e9",100:"#c8e6c9",200:"#a5d6a7",300:"#81c784",400:"#66bb6a",500:"#4caf50",600:"#43a047",700:"#388e3c",800:"#2e7d32",900:"#1b5e20",A100:"#b9f6ca",A200:"#69f0ae",A400:"#00e676",A700:"#00c853"};t.default=n},70167(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#fafafa",100:"#f5f5f5",200:"#eeeeee",300:"#e0e0e0",400:"#bdbdbd",500:"#9e9e9e",600:"#757575",700:"#616161",800:"#424242",900:"#212121",A100:"#d5d5d5",A200:"#aaaaaa",A400:"#303030",A700:"#616161"};t.default=n},19350(e,t,n){"use strict";var r,i=n(95318);r={value:!0},Object.defineProperty(t,"y0",{enumerable:!0,get:function(){return a.default}}),r={enumerable:!0,get:function(){return o.default}},r={enumerable:!0,get:function(){return s.default}},r={enumerable:!0,get:function(){return u.default}},r={enumerable:!0,get:function(){return c.default}},r={enumerable:!0,get:function(){return l.default}},r={enumerable:!0,get:function(){return f.default}},r={enumerable:!0,get:function(){return d.default}},r={enumerable:!0,get:function(){return h.default}},r={enumerable:!0,get:function(){return p.default}},Object.defineProperty(t,"ek",{enumerable:!0,get:function(){return b.default}}),r={enumerable:!0,get:function(){return m.default}},r={enumerable:!0,get:function(){return g.default}},r={enumerable:!0,get:function(){return v.default}},r={enumerable:!0,get:function(){return y.default}},r={enumerable:!0,get:function(){return w.default}},r={enumerable:!0,get:function(){return _.default}},r={enumerable:!0,get:function(){return E.default}},Object.defineProperty(t,"BA",{enumerable:!0,get:function(){return S.default}}),r={enumerable:!0,get:function(){return k.default}};var a=i(n(515)),o=i(n(83165)),s=i(n(124)),u=i(n(18118)),c=i(n(45018)),l=i(n(78768)),f=i(n(63259)),d=i(n(4923)),h=i(n(57646)),p=i(n(91605)),b=i(n(47559)),m=i(n(40192)),g=i(n(98567)),v=i(n(74578)),y=i(n(8070)),w=i(n(36594)),_=i(n(50173)),E=i(n(60169)),S=i(n(70167)),k=i(n(38236))},78768(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#e8eaf6",100:"#c5cae9",200:"#9fa8da",300:"#7986cb",400:"#5c6bc0",500:"#3f51b5",600:"#3949ab",700:"#303f9f",800:"#283593",900:"#1a237e",A100:"#8c9eff",A200:"#536dfe",A400:"#3d5afe",A700:"#304ffe"};t.default=n},4923(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#e1f5fe",100:"#b3e5fc",200:"#81d4fa",300:"#4fc3f7",400:"#29b6f6",500:"#03a9f4",600:"#039be5",700:"#0288d1",800:"#0277bd",900:"#01579b",A100:"#80d8ff",A200:"#40c4ff",A400:"#00b0ff",A700:"#0091ea"};t.default=n},40192(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#f1f8e9",100:"#dcedc8",200:"#c5e1a5",300:"#aed581",400:"#9ccc65",500:"#8bc34a",600:"#7cb342",700:"#689f38",800:"#558b2f",900:"#33691e",A100:"#ccff90",A200:"#b2ff59",A400:"#76ff03",A700:"#64dd17"};t.default=n},98567(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#f9fbe7",100:"#f0f4c3",200:"#e6ee9c",300:"#dce775",400:"#d4e157",500:"#cddc39",600:"#c0ca33",700:"#afb42b",800:"#9e9d24",900:"#827717",A100:"#f4ff81",A200:"#eeff41",A400:"#c6ff00",A700:"#aeea00"};t.default=n},36594(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#fff3e0",100:"#ffe0b2",200:"#ffcc80",300:"#ffb74d",400:"#ffa726",500:"#ff9800",600:"#fb8c00",700:"#f57c00",800:"#ef6c00",900:"#e65100",A100:"#ffd180",A200:"#ffab40",A400:"#ff9100",A700:"#ff6d00"};t.default=n},124(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#fce4ec",100:"#f8bbd0",200:"#f48fb1",300:"#f06292",400:"#ec407a",500:"#e91e63",600:"#d81b60",700:"#c2185b",800:"#ad1457",900:"#880e4f",A100:"#ff80ab",A200:"#ff4081",A400:"#f50057",A700:"#c51162"};t.default=n},18118(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#f3e5f5",100:"#e1bee7",200:"#ce93d8",300:"#ba68c8",400:"#ab47bc",500:"#9c27b0",600:"#8e24aa",700:"#7b1fa2",800:"#6a1b9a",900:"#4a148c",A100:"#ea80fc",A200:"#e040fb",A400:"#d500f9",A700:"#aa00ff"};t.default=n},83165(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#ffebee",100:"#ffcdd2",200:"#ef9a9a",300:"#e57373",400:"#ef5350",500:"#f44336",600:"#e53935",700:"#d32f2f",800:"#c62828",900:"#b71c1c",A100:"#ff8a80",A200:"#ff5252",A400:"#ff1744",A700:"#d50000"};t.default=n},91605(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#e0f2f1",100:"#b2dfdb",200:"#80cbc4",300:"#4db6ac",400:"#26a69a",500:"#009688",600:"#00897b",700:"#00796b",800:"#00695c",900:"#004d40",A100:"#a7ffeb",A200:"#64ffda",A400:"#1de9b6",A700:"#00bfa5"};t.default=n},74578(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={50:"#fffde7",100:"#fff9c4",200:"#fff59d",300:"#fff176",400:"#ffee58",500:"#ffeb3b",600:"#fdd835",700:"#fbc02d",800:"#f9a825",900:"#f57f17",A100:"#ffff8d",A200:"#ffff00",A400:"#ffea00",A700:"#ffd600"};t.default=n},85609(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.styles=void 0;var i=r(n(67154)),a=r(n(59713)),o=r(n(6479)),s=r(n(34575)),u=r(n(93913)),c=r(n(78585)),l=r(n(29754)),f=r(n(2205)),d=r(n(67294));r(n(45697));var h=r(n(94184)),p=r(n(52598)),b=r(n(78252)),m=r(n(81701)),g={root:{display:"inline-flex",alignItems:"center",transition:"none","&:hover":{backgroundColor:"transparent"}},checked:{},disabled:{},input:{cursor:"inherit",position:"absolute",opacity:0,width:"100%",height:"100%",top:0,left:0,margin:0,padding:0}};t.styles=g;var v=function(e){function t(e){var n;return(0,s.default)(this,t),(n=(0,c.default)(this,(0,l.default)(t).call(this))).handleFocus=function(e){n.props.onFocus&&n.props.onFocus(e);var t=n.props.muiFormControl;t&&t.onFocus&&t.onFocus(e)},n.handleBlur=function(e){n.props.onBlur&&n.props.onBlur(e);var t=n.props.muiFormControl;t&&t.onBlur&&t.onBlur(e)},n.handleInputChange=function(e){var t=e.target.checked;n.isControlled||n.setState({checked:t}),n.props.onChange&&n.props.onChange(e,t)},n.isControlled=null!=e.checked,n.state={},n.isControlled||(n.state.checked=void 0!==e.defaultChecked&&e.defaultChecked),n}return(0,f.default)(t,e),(0,u.default)(t,[{key:"render",value:function(){var e,t=this.props,n=t.autoFocus,r=t.checked,s=t.checkedIcon,u=t.classes,c=t.className,l=t.defaultChecked,f=t.disabled,p=t.icon,b=t.id,g=t.inputProps,v=t.inputRef,y=t.muiFormControl,w=t.name,_=(t.onBlur,t.onChange,t.onFocus,t.readOnly),E=t.required,S=t.tabIndex,k=t.type,x=t.value,T=(0,o.default)(t,["autoFocus","checked","checkedIcon","classes","className","defaultChecked","disabled","icon","id","inputProps","inputRef","muiFormControl","name","onBlur","onChange","onFocus","readOnly","required","tabIndex","type","value"]),M=f;y&&void 0===M&&(M=y.disabled);var O=this.isControlled?r:this.state.checked,A="checkbox"===k||"radio"===k;return d.default.createElement(m.default,(0,i.default)({component:"span",className:(0,h.default)(u.root,(e={},(0,a.default)(e,u.checked,O),(0,a.default)(e,u.disabled,M),e),c),disabled:M,tabIndex:null,role:void 0,onFocus:this.handleFocus,onBlur:this.handleBlur},T),O?s:p,d.default.createElement("input",(0,i.default)({autoFocus:n,checked:r,defaultChecked:l,className:u.input,disabled:M,id:A&&b,name:w,onChange:this.handleInputChange,readOnly:_,ref:v,required:E,tabIndex:S,type:k,value:x},g)))}}]),t}(d.default.Component),y=(0,b.default)(g,{name:"MuiPrivateSwitchBase"})((0,p.default)(v));t.default=y},13329(e,t){"use strict";function n(e){return(1+Math.sin(Math.PI*e-Math.PI/2))/2}function r(e,t,r){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){},o=i.ease,s=void 0===o?n:o,u=i.duration,c=void 0===u?300:u,l=null,f=t[e],d=!1,h=function(){d=!0},p=function n(i){if(d){a(Error("Animation cancelled"));return}null===l&&(l=i);var o=Math.min(1,(i-l)/c);if(t[e]=s(o)*(r-f)+f,o>=1){requestAnimationFrame(function(){a(null)});return}requestAnimationFrame(n)};return f===r?(a(Error("Element already at target position")),h):(requestAnimationFrame(p),h)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r;t.default=i},74622(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M7 10l5 5 5-5z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},99781(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},41549(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},42159(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},61486(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},86861(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},43836(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67294)),a=r(n(46949)),o=r(n(40577)),s=i.default.createElement("path",{d:"M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"}),u=function(e){return i.default.createElement(o.default,e,s)};(u=(0,a.default)(u)).muiName="SvgIcon";var c=u;t.default=c},93078(e,t,n){"use strict";/*!
+ * is-plain-object
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */ var r=n(47798);function i(e){return!0===r(e)&&"[object Object]"===Object.prototype.toString.call(e)}e.exports=function(e){var t,n;return!1!==i(e)&&"function"==typeof(t=e.constructor)&&!1!==i(n=t.prototype)&&!1!==n.hasOwnProperty("isPrototypeOf")}},72366(e,t,n){"use strict";var r=n(20862),i=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.MuiThemeProviderOld=void 0;var a=i(n(67154)),o=i(n(59713)),s=i(n(34575)),u=i(n(93913)),c=i(n(78585)),l=i(n(29754)),f=i(n(2205)),d=i(n(67294)),h=i(n(45697));i(n(42473));var p=i(n(43890)),b=n(55252),m=r(n(51067)),g=function(e){function t(e,n){var r;return(0,s.default)(this,t),(r=(0,c.default)(this,(0,l.default)(t).call(this))).broadcast=(0,p.default)(),r.outerTheme=m.default.initial(n),r.broadcast.setState(r.mergeOuterLocalTheme(e.theme)),r}return(0,f.default)(t,e),(0,u.default)(t,[{key:"getChildContext",value:function(){var e,t=this.props,n=t.disableStylesGeneration,r=t.sheetsCache,i=t.sheetsManager,a=this.context.muiThemeProviderOptions||{};return void 0!==n&&(a.disableStylesGeneration=n),void 0!==r&&(a.sheetsCache=r),void 0!==i&&(a.sheetsManager=i),e={},(0,o.default)(e,m.CHANNEL,this.broadcast),(0,o.default)(e,"muiThemeProviderOptions",a),e}},{key:"componentDidMount",value:function(){var e=this;this.unsubscribeId=m.default.subscribe(this.context,function(t){e.outerTheme=t,e.broadcast.setState(e.mergeOuterLocalTheme(e.props.theme))})}},{key:"componentDidUpdate",value:function(e){this.props.theme!==e.theme&&this.broadcast.setState(this.mergeOuterLocalTheme(this.props.theme))}},{key:"componentWillUnmount",value:function(){null!==this.unsubscribeId&&m.default.unsubscribe(this.context,this.unsubscribeId)}},{key:"mergeOuterLocalTheme",value:function(e){return"function"==typeof e?e(this.outerTheme):this.outerTheme?(0,a.default)({},this.outerTheme,e):e}},{key:"render",value:function(){return this.props.children}}]),t}(d.default.Component);t.MuiThemeProviderOld=g,g.childContextTypes=(0,a.default)({},m.default.contextTypes,{muiThemeProviderOptions:h.default.object}),g.contextTypes=(0,a.default)({},m.default.contextTypes,{muiThemeProviderOptions:h.default.object}),b.ponyfillGlobal.__MUI_STYLES__||(b.ponyfillGlobal.__MUI_STYLES__={}),b.ponyfillGlobal.__MUI_STYLES__.MuiThemeProvider||(b.ponyfillGlobal.__MUI_STYLES__.MuiThemeProvider=g);var v=b.ponyfillGlobal.__MUI_STYLES__.MuiThemeProvider;t.default=v},59114(e,t,n){"use strict";var r=n(95318);function i(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return en?n:e}function a(e){e=e.substr(1);var t=RegExp(".{1,".concat(e.length/3,"}"),"g"),n=e.match(t);return n&&1===n[0].length&&(n=n.map(function(e){return e+e})),n?"rgb(".concat(n.map(function(e){return parseInt(e,16)}).join(", "),")"):""}function o(e){if(0===e.indexOf("#"))return e;function t(e){var t=e.toString(16);return 1===t.length?"0".concat(t):t}var n=s(e).values;return n=n.map(function(e){return t(e)}),"#".concat(n.join(""))}function s(e){if("#"===e.charAt(0))return s(a(e));var t=e.indexOf("("),n=e.substring(0,t),r=e.substring(t+1,e.length-1).split(",");return r=r.map(function(e){return parseFloat(e)}),{type:n,values:r}}function u(e){var t=e.type,n=e.values;return -1!==t.indexOf("rgb")&&(n=n.map(function(e,t){return t<3?parseInt(e,10):e})),-1!==t.indexOf("hsl")&&(n[1]="".concat(n[1],"%"),n[2]="".concat(n[2],"%")),"".concat(e.type,"(").concat(n.join(", "),")")}function c(e,t){var n=l(e),r=l(t);return(Math.max(n,r)+.05)/(Math.min(n,r)+.05)}function l(e){var t=s(e);if(-1!==t.type.indexOf("rgb")){var n=t.values.map(function(e){return(e/=255)<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4)});return Number((.2126*n[0]+.7152*n[1]+.0722*n[2]).toFixed(3))}return t.values[2]/100}function f(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:.15;return l(e)>.5?h(e,t):p(e,t)}function d(e,t){return e?(e=s(e),t=i(t),("rgb"===e.type||"hsl"===e.type)&&(e.type+="a"),e.values[3]=t,u(e)):e}function h(e,t){if(!e)return e;if(e=s(e),t=i(t),-1!==e.type.indexOf("hsl"))e.values[2]*=1-t;else if(-1!==e.type.indexOf("rgb"))for(var n=0;n<3;n+=1)e.values[n]*=1-t;return u(e)}function p(e,t){if(!e)return e;if(e=s(e),t=i(t),-1!==e.type.indexOf("hsl"))e.values[2]+=(100-e.values[2])*t;else if(-1!==e.type.indexOf("rgb"))for(var n=0;n<3;n+=1)e.values[n]+=(255-e.values[n])*t;return u(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.convertHexToRGB=a,t.rgbToHex=o,t.decomposeColor=s,t.recomposeColor=u,t.getContrastRatio=c,t.getLuminance=l,t.emphasize=f,t.fade=d,t.darken=h,t.lighten=p,r(n(42473))},94811(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=s,t.keys=void 0;var i=r(n(67154)),a=r(n(6479)),o=["xs","sm","md","lg","xl"];function s(e){var t=e.values,n=void 0===t?{xs:0,sm:600,md:960,lg:1280,xl:1920}:t,r=e.unit,s=void 0===r?"px":r,u=e.step,c=void 0===u?5:u,l=(0,a.default)(e,["values","unit","step"]);function f(e){var t="number"==typeof n[e]?n[e]:e;return"@media (min-width:".concat(t).concat(s,")")}function d(e){var t=o.indexOf(e)+1,r=n[o[t]];if(t===o.length)return f("xs");var i="number"==typeof r&&t>0?r:e;return"@media (max-width:".concat(i-c/100).concat(s,")")}function h(e,t){var r=o.indexOf(t)+1;return r===o.length?f(e):"@media (min-width:".concat(n[e]).concat(s,") and ")+"(max-width:".concat(n[o[r]]-c/100).concat(s,")")}function p(e){return h(e,e)}function b(e){return n[e]}return(0,i.default)({keys:o,values:n,up:f,down:d,between:h,only:p,width:b},l)}t.keys=o},20237(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=o,r(n(42473));var i=/([[\].#*$><+~=|^:(),"'`\s])/g;function a(e){var t;return String(e).replace(i,"-")}function o(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.dangerouslyUseGlobalCSS,n=void 0!==t&&t,r=e.productionPrefix,i=void 0===r?"jss":r,o=e.seed,s=void 0===o?"":o,u=0;return function(e,t){return(u+=1,n&&t&&t.options.name)?"".concat(a(t.options.name),"-").concat(e.key):"".concat(i).concat(s).concat(u)}}},40226(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=o;var i=r(n(59713)),a=r(n(67154));function o(e,t,n){var r;return(0,a.default)({gutters:function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return(0,a.default)({paddingLeft:2*t.unit,paddingRight:2*t.unit},n,(0,i.default)({},e.up("sm"),(0,a.default)({paddingLeft:3*t.unit,paddingRight:3*t.unit},n[e.up("sm")])))},toolbar:(r={minHeight:56},(0,i.default)(r,"".concat(e.up("xs")," and (orientation: landscape)"),{minHeight:48}),(0,i.default)(r,e.up("sm"),{minHeight:64}),r)},n)}},71615(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,r(n(59713));var i=r(n(67154)),a=r(n(6479)),o=r(n(94863)),s=r(n(93078));r(n(42473));var u=r(n(94811)),c=r(n(40226)),l=r(n(21091)),f=r(n(45184)),d=r(n(80743)),h=r(n(59591)),p=r(n(5324)),b=r(n(15406)),m=r(n(88676));function g(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.breakpoints,r=void 0===n?{}:n,g=t.mixins,v=void 0===g?{}:g,y=t.palette,w=void 0===y?{}:y,_=t.shadows,E=t.spacing,S=void 0===E?{}:E,k=t.typography,x=void 0===k?{}:k,T=(0,a.default)(t,["breakpoints","mixins","palette","shadows","spacing","typography"]),M=(0,l.default)(w),O=(0,u.default)(r),A=(0,i.default)({},p.default,S);return(0,i.default)({breakpoints:O,direction:"ltr",mixins:(0,c.default)(O,A,v),overrides:{},palette:M,props:{},shadows:_||d.default,typography:(0,f.default)(M,x)},(0,o.default)({shape:h.default,spacing:A,transitions:b.default,zIndex:m.default},T,{isMergeableObject:s.default}))}var v=g;t.default=v},21091(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=m,t.dark=t.light=void 0;var i=r(n(67154)),a=r(n(6479));r(n(42473));var o=r(n(94863)),s=r(n(78768)),u=r(n(124)),c=r(n(70167)),l=r(n(83165)),f=r(n(515)),d=n(59114),h={text:{primary:"rgba(0, 0, 0, 0.87)",secondary:"rgba(0, 0, 0, 0.54)",disabled:"rgba(0, 0, 0, 0.38)",hint:"rgba(0, 0, 0, 0.38)"},divider:"rgba(0, 0, 0, 0.12)",background:{paper:f.default.white,default:c.default[50]},action:{active:"rgba(0, 0, 0, 0.54)",hover:"rgba(0, 0, 0, 0.08)",hoverOpacity:.08,selected:"rgba(0, 0, 0, 0.14)",disabled:"rgba(0, 0, 0, 0.26)",disabledBackground:"rgba(0, 0, 0, 0.12)"}};t.light=h;var p={text:{primary:f.default.white,secondary:"rgba(255, 255, 255, 0.7)",disabled:"rgba(255, 255, 255, 0.5)",hint:"rgba(255, 255, 255, 0.5)",icon:"rgba(255, 255, 255, 0.5)"},divider:"rgba(255, 255, 255, 0.12)",background:{paper:c.default[800],default:"#303030"},action:{active:f.default.white,hover:"rgba(255, 255, 255, 0.1)",hoverOpacity:.1,selected:"rgba(255, 255, 255, 0.2)",disabled:"rgba(255, 255, 255, 0.3)",disabledBackground:"rgba(255, 255, 255, 0.12)"}};function b(e,t,n,r){e[t]||(e.hasOwnProperty(n)?e[t]=e[n]:"light"===t?e.light=(0,d.lighten)(e.main,r):"dark"===t&&(e.dark=(0,d.darken)(e.main,1.5*r)))}function m(e){var t=e.primary,n=void 0===t?{light:s.default[300],main:s.default[500],dark:s.default[700]}:t,r=e.secondary,m=void 0===r?{light:u.default.A200,main:u.default.A400,dark:u.default.A700}:r,g=e.error,v=void 0===g?{light:l.default[300],main:l.default[500],dark:l.default[700]}:g,y=e.type,w=void 0===y?"light":y,_=e.contrastThreshold,E=void 0===_?3:_,S=e.tonalOffset,k=void 0===S?.2:S,x=(0,a.default)(e,["primary","secondary","error","type","contrastThreshold","tonalOffset"]);function T(e){var t;return(0,d.getContrastRatio)(e,p.text.primary)>=E?p.text.primary:h.text.primary}function M(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:500,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:300,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:700;return!e.main&&e[t]&&(e.main=e[t]),b(e,"light",n,k),b(e,"dark",r,k),e.contrastText||(e.contrastText=T(e.main)),e}M(n),M(m,"A400","A200","A700"),M(v);var O={dark:p,light:h};return(0,o.default)((0,i.default)({common:f.default,type:w,primary:n,secondary:m,error:v,grey:c.default,contrastThreshold:E,getContrastText:T,augmentColor:M,tonalOffset:k},O[w]),x,{clone:!1})}t.dark=p},16059(e,t){"use strict";function n(e){return e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},45184(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=f;var i=r(n(67154)),a=r(n(6479)),o=r(n(94863));r(n(42473));var s=n(55252);function u(e){return Math.round(1e5*e)/1e5}var c={textTransform:"uppercase"},l='"Roboto", "Helvetica", "Arial", sans-serif';function f(e,t){var n="function"==typeof t?t(e):t,r=n.fontFamily,f=void 0===r?l:r,d=n.fontSize,h=void 0===d?14:d,p=n.fontWeightLight,b=void 0===p?300:p,m=n.fontWeightRegular,g=void 0===m?400:m,v=n.fontWeightMedium,y=void 0===v?500:v,w=n.htmlFontSize,_=void 0===w?16:w,E=n.useNextVariants,S=void 0===E?Boolean(s.ponyfillGlobal.__MUI_USE_NEXT_TYPOGRAPHY_VARIANTS__):E,k=(n.suppressWarning,n.allVariants),x=(0,a.default)(n,["fontFamily","fontSize","fontWeightLight","fontWeightRegular","fontWeightMedium","htmlFontSize","useNextVariants","suppressWarning","allVariants"]),T=h/14,M=function(e){return"".concat(e/_*T,"rem")},O=function(t,n,r,a,o){return(0,i.default)({color:e.text.primary,fontFamily:f,fontWeight:t,fontSize:M(n),lineHeight:r},f===l?{letterSpacing:"".concat(u(a/n),"em")}:{},o,k)},A={h1:O(b,96,1,-1.5),h2:O(b,60,1,-.5),h3:O(g,48,1.04,0),h4:O(g,34,1.17,.25),h5:O(g,24,1.33,0),h6:O(y,20,1.6,.15),subtitle1:O(g,16,1.75,.15),subtitle2:O(y,14,1.57,.1),body1Next:O(g,16,1.5,.15),body2Next:O(g,14,1.5,.15),buttonNext:O(y,14,1.75,.4,c),captionNext:O(g,12,1.66,.4),overline:O(g,12,2.66,1,c)},L={display4:(0,i.default)({fontSize:M(112),fontWeight:b,fontFamily:f,letterSpacing:"-.04em",lineHeight:"".concat(u(128/112),"em"),marginLeft:"-.04em",color:e.text.secondary},k),display3:(0,i.default)({fontSize:M(56),fontWeight:g,fontFamily:f,letterSpacing:"-.02em",lineHeight:"".concat(u(73/56),"em"),marginLeft:"-.02em",color:e.text.secondary},k),display2:(0,i.default)({fontSize:M(45),fontWeight:g,fontFamily:f,lineHeight:"".concat(u(51/45),"em"),marginLeft:"-.02em",color:e.text.secondary},k),display1:(0,i.default)({fontSize:M(34),fontWeight:g,fontFamily:f,lineHeight:"".concat(u(41/34),"em"),color:e.text.secondary},k),headline:(0,i.default)({fontSize:M(24),fontWeight:g,fontFamily:f,lineHeight:"".concat(u(32.5/24),"em"),color:e.text.primary},k),title:(0,i.default)({fontSize:M(21),fontWeight:y,fontFamily:f,lineHeight:"".concat(u(24.5/21),"em"),color:e.text.primary},k),subheading:(0,i.default)({fontSize:M(16),fontWeight:g,fontFamily:f,lineHeight:"".concat(u(1.5),"em"),color:e.text.primary},k),body2:(0,i.default)({fontSize:M(14),fontWeight:y,fontFamily:f,lineHeight:"".concat(u(24/14),"em"),color:e.text.primary},k),body1:(0,i.default)({fontSize:M(14),fontWeight:g,fontFamily:f,lineHeight:"".concat(u(20.5/14),"em"),color:e.text.primary},k),caption:(0,i.default)({fontSize:M(12),fontWeight:g,fontFamily:f,lineHeight:"".concat(u(1.375),"em"),color:e.text.secondary},k),button:(0,i.default)({fontSize:M(14),textTransform:"uppercase",fontWeight:y,fontFamily:f,color:e.text.primary},k)};return(0,o.default)((0,i.default)({pxToRem:M,round:u,fontFamily:f,fontSize:h,fontWeightLight:b,fontWeightRegular:g,fontWeightMedium:y},L,A,S?{body1:A.body1Next,body2:A.body2Next,button:A.buttonNext,caption:A.captionNext}:{},{useNextVariants:S}),x,{clone:!1})}},42458(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67154));r(n(50008)),r(n(42473));var a=r(n(94863));function o(e,t){return t}function s(e){var t="function"==typeof e;function n(n,r){var s=t?e(n):e;if(!r||!n.overrides||!n.overrides[r])return s;var u=n.overrides[r],c=(0,i.default)({},s);return Object.keys(u).forEach(function(e){c[e]=(0,a.default)(c[e],u[e],{arrayMerge:o})}),c}return{create:n,options:{},themingEnabled:t}}var u=s;t.default=u},58057(e,t){"use strict";function n(e){var t,n=e.theme,r=e.name,i=e.props;if(!n.props||!r||!n.props[r])return i;var a=n.props[r];for(t in a)void 0===i[t]&&(i[t]=a[t]);return i}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n;t.default=r},32316(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"createGenerateClassName",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(t,"createMuiTheme",{enumerable:!0,get:function(){return a.default}}),Object.defineProperty(t,"jssPreset",{enumerable:!0,get:function(){return o.default}}),Object.defineProperty(t,"MuiThemeProvider",{enumerable:!0,get:function(){return s.default}}),Object.defineProperty(t,"createStyles",{enumerable:!0,get:function(){return u.default}}),Object.defineProperty(t,"withStyles",{enumerable:!0,get:function(){return c.default}}),Object.defineProperty(t,"withTheme",{enumerable:!0,get:function(){return l.default}});var i=r(n(20237)),a=r(n(71615)),o=r(n(9399)),s=r(n(72366)),u=r(n(16059)),c=r(n(78252)),l=r(n(82313))},9399(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(29059)),a=r(n(28752)),o=r(n(35828)),s=r(n(50462)),u=r(n(65926)),c=r(n(89347));function l(){return{plugins:[(0,i.default)(),(0,a.default)(),(0,o.default)(),(0,s.default)(),"undefined"==typeof window?null:(0,u.default)(),(0,c.default)()]}}var f=l;t.default=f},35199(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=r(n(67154));function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.baseClasses,n=e.newClasses;if(e.Component,!n)return t;var r=(0,i.default)({},t);return Object.keys(n).forEach(function(e){n[e]&&(r[e]="".concat(t[e]," ").concat(n[e]))}),r}r(n(42473)),n(55252);var o=a;t.default=o},88693(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={set:function(e,t,n,r){var i=e.get(t);i||(i=new Map,e.set(t,i)),i.set(n,r)},get:function(e,t,n){var r=e.get(t);return r?r.get(n):void 0},delete:function(e,t,n){e.get(t).delete(n)}};t.default=n},31898(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={jss:"64a55d578f856d258dc345b094a2a2b3",sheetsRegistry:"d4bd0baacbc52bbd48bbb9eb24344ecd",sheetOptions:"6fc570d6bd61383819d0f9e7407c452d"};t.default=n},80743(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=.2,r=.14,i=.12;function a(){return["".concat(arguments.length<=0?void 0:arguments[0],"px ").concat(arguments.length<=1?void 0:arguments[1],"px ").concat(arguments.length<=2?void 0:arguments[2],"px ").concat(arguments.length<=3?void 0:arguments[3],"px rgba(0,0,0,").concat(n,")"),"".concat(arguments.length<=4?void 0:arguments[4],"px ").concat(arguments.length<=5?void 0:arguments[5],"px ").concat(arguments.length<=6?void 0:arguments[6],"px ").concat(arguments.length<=7?void 0:arguments[7],"px rgba(0,0,0,").concat(r,")"),"".concat(arguments.length<=8?void 0:arguments[8],"px ").concat(arguments.length<=9?void 0:arguments[9],"px ").concat(arguments.length<=10?void 0:arguments[10],"px ").concat(arguments.length<=11?void 0:arguments[11],"px rgba(0,0,0,").concat(i,")")].join(",")}var o=["none",a(0,1,3,0,0,1,1,0,0,2,1,-1),a(0,1,5,0,0,2,2,0,0,3,1,-2),a(0,1,8,0,0,3,4,0,0,3,3,-2),a(0,2,4,-1,0,4,5,0,0,1,10,0),a(0,3,5,-1,0,5,8,0,0,1,14,0),a(0,3,5,-1,0,6,10,0,0,1,18,0),a(0,4,5,-2,0,7,10,1,0,2,16,1),a(0,5,5,-3,0,8,10,1,0,3,14,2),a(0,5,6,-3,0,9,12,1,0,3,16,2),a(0,6,6,-3,0,10,14,1,0,4,18,3),a(0,6,7,-4,0,11,15,1,0,4,20,3),a(0,7,8,-4,0,12,17,2,0,5,22,4),a(0,7,8,-4,0,13,19,2,0,5,24,4),a(0,7,9,-4,0,14,21,2,0,5,26,4),a(0,8,9,-5,0,15,22,2,0,6,28,5),a(0,8,10,-5,0,16,24,2,0,6,30,5),a(0,8,11,-5,0,17,26,2,0,6,32,5),a(0,9,11,-5,0,18,28,2,0,7,34,6),a(0,9,12,-6,0,19,29,2,0,7,36,6),a(0,10,13,-6,0,20,31,3,0,8,38,7),a(0,10,13,-6,0,21,33,3,0,8,40,7),a(0,10,14,-6,0,22,35,3,0,8,42,7),a(0,11,14,-7,0,23,36,3,0,9,44,8),a(0,11,15,-7,0,24,38,3,0,9,46,8)];t.default=o},59591(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={borderRadius:4};t.default=n},5324(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={unit:8};t.default=n},51067(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.CHANNEL=void 0;var i=r(n(59713)),a="__THEMING__";t.CHANNEL=a;var o={contextTypes:(0,i.default)({},a,function(){}),initial:function(e){return e[a]?e[a].getState():null},subscribe:function(e,t){return e[a]?e[a].subscribe(t):null},unsubscribe:function(e,t){e[a]&&e[a].unsubscribe(t)}};t.default=o},15406(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.isNumber=t.isString=t.formatMs=t.duration=t.easing=void 0;var i=r(n(6479));r(n(42473));var a={easeInOut:"cubic-bezier(0.4, 0, 0.2, 1)",easeOut:"cubic-bezier(0.0, 0, 0.2, 1)",easeIn:"cubic-bezier(0.4, 0, 1, 1)",sharp:"cubic-bezier(0.4, 0, 0.6, 1)"};t.easing=a;var o={shortest:150,shorter:200,short:250,standard:300,complex:375,enteringScreen:225,leavingScreen:195};t.duration=o;var s=function(e){return"".concat(Math.round(e),"ms")};t.formatMs=s;var u=function(e){return"string"==typeof e};t.isString=u;var c=function(e){return!isNaN(parseFloat(e))};t.isNumber=c;var l={easing:a,duration:o,create:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["all"],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.duration,r=void 0===n?o.standard:n,u=t.easing,c=void 0===u?a.easeInOut:u,l=t.delay,f=void 0===l?0:l;return(0,i.default)(t,["duration","easing","delay"]),(Array.isArray(e)?e:[e]).map(function(e){return"".concat(e," ").concat("string"==typeof r?r:s(r)," ").concat(c," ").concat("string"==typeof f?f:s(f))}).join(",")},getAutoHeightDuration:function(e){if(!e)return 0;var t=e/36;return Math.round((4+15*Math.pow(t,.25)+t/5)*10)}};t.default=l},78252(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.sheetsManager=void 0;var i=r(n(59713)),a=r(n(67154)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(6479)),d=r(n(67294)),h=r(n(45697));r(n(42473));var p=r(n(8679)),b=n(55252),m=n(55690),g=r(n(31898)),v=r(n(9399)),y=r(n(35199)),w=r(n(88693)),_=r(n(71615)),E=r(n(51067)),S=r(n(20237)),k=r(n(42458)),x=r(n(58057)),T=(0,m.create)((0,v.default)()),M=(0,S.default)(),O=-1e11,A=new Map;t.sheetsManager=A;var L={},C=(0,_.default)({typography:{suppressWarning:!0}}),I=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return function(n){var r,b=t.withTheme,m=void 0!==b&&b,v=t.flip,_=void 0===v?null:v,S=t.name,I=(0,f.default)(t,["withTheme","flip","name"]),D=(0,k.default)(e),N=D.themingEnabled||"string"==typeof S||m;O+=1,D.options.index=O;var P=function(e){function t(e,n){(0,o.default)(this,t),(r=(0,u.default)(this,(0,c.default)(t).call(this,e,n))).jss=n[g.default.jss]||T,r.sheetsManager=A,r.unsubscribeId=null;var r,i=n.muiThemeProviderOptions;return i&&(i.sheetsManager&&(r.sheetsManager=i.sheetsManager),r.sheetsCache=i.sheetsCache,r.disableStylesGeneration=i.disableStylesGeneration),r.stylesCreatorSaved=D,r.sheetOptions=(0,a.default)({generateClassName:M},n[g.default.sheetOptions]),r.theme=N?E.default.initial(n)||C:L,r.attach(r.theme),r.cacheClasses={value:null,lastProp:null,lastJSS:{}},r}return(0,l.default)(t,e),(0,s.default)(t,[{key:"componentDidMount",value:function(){var e=this;N&&(this.unsubscribeId=E.default.subscribe(this.context,function(t){var n=e.theme;e.theme=t,e.attach(e.theme),e.setState({},function(){e.detach(n)})}))}},{key:"componentDidUpdate",value:function(){this.stylesCreatorSaved}},{key:"componentWillUnmount",value:function(){this.detach(this.theme),null!==this.unsubscribeId&&E.default.unsubscribe(this.context,this.unsubscribeId)}},{key:"getClasses",value:function(){if(this.disableStylesGeneration)return this.props.classes||{};var e=!1,t=w.default.get(this.sheetsManager,this.stylesCreatorSaved,this.theme);return t.sheet.classes!==this.cacheClasses.lastJSS&&(this.cacheClasses.lastJSS=t.sheet.classes,e=!0),this.props.classes!==this.cacheClasses.lastProp&&(this.cacheClasses.lastProp=this.props.classes,e=!0),e&&(this.cacheClasses.value=(0,y.default)({baseClasses:this.cacheClasses.lastJSS,newClasses:this.props.classes,Component:n})),this.cacheClasses.value}},{key:"attach",value:function(e){if(!this.disableStylesGeneration){var t=this.stylesCreatorSaved,n=w.default.get(this.sheetsManager,t,e);if(n||(n={refs:0,sheet:null},w.default.set(this.sheetsManager,t,e,n)),0===n.refs){this.sheetsCache&&(r=w.default.get(this.sheetsCache,t,e)),!r&&((r=this.createSheet(e)).attach(),this.sheetsCache&&w.default.set(this.sheetsCache,t,e,r)),n.sheet=r;var r,i=this.context[g.default.sheetsRegistry];i&&i.add(r)}n.refs+=1}}},{key:"createSheet",value:function(e){var t=this.stylesCreatorSaved.create(e,S),r=S;return this.jss.createStyleSheet(t,(0,a.default)({meta:r,classNamePrefix:r,flip:"boolean"==typeof _?_:"rtl"===e.direction,link:!1},this.sheetOptions,this.stylesCreatorSaved.options,{name:S||n.displayName},I))}},{key:"detach",value:function(e){if(!this.disableStylesGeneration){var t=w.default.get(this.sheetsManager,this.stylesCreatorSaved,e);if(t.refs-=1,0===t.refs){w.default.delete(this.sheetsManager,this.stylesCreatorSaved,e),this.jss.removeStyleSheet(t.sheet);var n=this.context[g.default.sheetsRegistry];n&&n.remove(t.sheet)}}}},{key:"render",value:function(){var e=this.props,t=(e.classes,e.innerRef),r=(0,f.default)(e,["classes","innerRef"]),i=(0,x.default)({theme:this.theme,name:S,props:r});return m&&!i.theme&&(i.theme=this.theme),d.default.createElement(n,(0,a.default)({},i,{classes:this.getClasses(),ref:t}))}}]),t}(d.default.Component);return P.contextTypes=(0,a.default)((r={muiThemeProviderOptions:h.default.object},(0,i.default)(r,g.default.jss,h.default.object),(0,i.default)(r,g.default.sheetOptions,h.default.object),(0,i.default)(r,g.default.sheetsRegistry,h.default.object),r),N?E.default.contextTypes:{}),(0,p.default)(P,n),P}};b.ponyfillGlobal.__MUI_STYLES__||(b.ponyfillGlobal.__MUI_STYLES__={}),b.ponyfillGlobal.__MUI_STYLES__.withStyles||(b.ponyfillGlobal.__MUI_STYLES__.withStyles=I);var D=function(e,t){return b.ponyfillGlobal.__MUI_STYLES__.withStyles(e,(0,a.default)({defaultTheme:C},t))};t.default=D},82313(e,t,n){"use strict";var r,i=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=i(n(67154)),o=i(n(6479)),s=i(n(34575)),u=i(n(93913)),c=i(n(78585)),l=i(n(29754)),f=i(n(2205)),d=i(n(67294));i(n(45697));var h=i(n(8679)),p=n(55252),b=i(n(71615)),m=i(n(51067));function g(){return r||(r=(0,b.default)({typography:{suppressWarning:!0}}))}var v=function(){return function(e){var t=function(t){function n(e,t){var r;return(0,s.default)(this,n),(r=(0,c.default)(this,(0,l.default)(n).call(this))).state={theme:m.default.initial(t)||g()},r}return(0,f.default)(n,t),(0,u.default)(n,[{key:"componentDidMount",value:function(){var e=this;this.unsubscribeId=m.default.subscribe(this.context,function(t){e.setState({theme:t})})}},{key:"componentWillUnmount",value:function(){null!==this.unsubscribeId&&m.default.unsubscribe(this.context,this.unsubscribeId)}},{key:"render",value:function(){var t=this.props,n=t.innerRef,r=(0,o.default)(t,["innerRef"]);return d.default.createElement(e,(0,a.default)({theme:this.state.theme,ref:n},r))}}]),n}(d.default.Component);return t.contextTypes=m.default.contextTypes,(0,h.default)(t,e),t}};p.ponyfillGlobal.__MUI_STYLES__||(p.ponyfillGlobal.__MUI_STYLES__={}),p.ponyfillGlobal.__MUI_STYLES__.withTheme||(p.ponyfillGlobal.__MUI_STYLES__.withTheme=v);var y=p.ponyfillGlobal.__MUI_STYLES__.withTheme;t.default=y},88676(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={mobileStepper:1e3,appBar:1100,drawer:1200,modal:1300,snackbar:1400,tooltip:1500};t.default=n},41929(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getTransitionProps=r,t.reflow=void 0;var n=function(e){return e.scrollTop};function r(e,t){var n=e.timeout,r=e.style,i=void 0===r?{}:r;return{duration:i.transitionDuration||"number"==typeof n?n:n[t.mode],delay:i.transitionDelay}}t.reflow=n},346(e,t){"use strict";function n(e,t){return function(){return null}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n;t.default=r},98741(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.capitalize=a,t.contains=o,t.findIndex=s,t.find=u,t.createChainedFunction=c;var i=r(n(50008));function a(e){return e.charAt(0).toUpperCase()+e.slice(1)}function o(e,t){return Object.keys(t).every(function(n){return e.hasOwnProperty(n)&&e[n]===t[n]})}function s(e,t){for(var n=(0,i.default)(t),r=0;r-1?e[n]:void 0}function c(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:window,n=(0,i.default)(e);return n.defaultView||n.parentView||t}var o=a;t.default=o},44370(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.cloneElementWithClassName=o,t.cloneChildrenWithClassName=s,t.isMuiElement=u,t.setRef=c;var i=r(n(67294)),a=r(n(94184));function o(e,t){return i.default.cloneElement(e,{className:(0,a.default)(e.props.className,t)})}function s(e,t){return i.default.Children.map(e,function(e){return i.default.isValidElement(e)&&o(e,t)})}function u(e,t){return i.default.isValidElement(e)&&-1!==t.indexOf(e.type.muiName)}function c(e,t){"function"==typeof e?e(t):e&&(e.current=t)}},47348(e,t){"use strict";function n(e){return function(){return null}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n;t.default=r},21677(e,t){"use strict";function n(e,t,n,r,i){return null}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n;t.default=r},78290(e,t,n){"use strict";var r=n(20862);Object.defineProperty(t,"__esModule",{value:!0});var i={};Object.defineProperty(t,"default",{enumerable:!0,get:function(){return a.default}});var a=r(n(88446));Object.keys(a).forEach(function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(i,e)||Object.defineProperty(t,e,{enumerable:!0,get:function(){return a[e]}}))})},88446(e,t,n){"use strict";var r=n(95318);Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.isWidthDown=t.isWidthUp=void 0;var i=r(n(67154)),a=r(n(6479)),o=r(n(34575)),s=r(n(93913)),u=r(n(78585)),c=r(n(29754)),l=r(n(2205)),f=r(n(67294));r(n(45697));var d=r(n(96421)),h=r(n(20296));n(55252);var p=r(n(8679)),b=r(n(82313)),m=n(94811),g=r(n(58057)),v=function(e,t){var n=!(arguments.length>2)||void 0===arguments[2]||arguments[2];return n?m.keys.indexOf(e)<=m.keys.indexOf(t):m.keys.indexOf(e)2)||void 0===arguments[2]||arguments[2];return n?m.keys.indexOf(t)<=m.keys.indexOf(e):m.keys.indexOf(t)0&&void 0!==arguments[0]?arguments[0]:{};return function(t){var n=e.withTheme,r=void 0!==n&&n,v=e.noSSR,y=void 0!==v&&v,w=e.initialWidth,_=e.resizeInterval,E=void 0===_?166:_,S=function(e){function n(e){var t;return(0,o.default)(this,n),(t=(0,u.default)(this,(0,c.default)(n).call(this,e))).state={width:y?t.getWidth():void 0},"undefined"!=typeof window&&(t.handleResize=(0,h.default)(function(){var e=t.getWidth();e!==t.state.width&&t.setState({width:e})},E)),t}return(0,l.default)(n,e),(0,s.default)(n,[{key:"componentDidMount",value:function(){var e=this.getWidth();e!==this.state.width&&this.setState({width:e})}},{key:"componentWillUnmount",value:function(){this.handleResize.clear()}},{key:"getWidth",value:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.innerWidth,t=this.props.theme.breakpoints,n=null,r=1;null===n&&ri.Z,componentPropType:()=>r.Z,exactProp:()=>a.ZP,getDisplayName:()=>o.ZP,ponyfillGlobal:()=>s.Z});var r=n(78728),i=n(5477),a=n(43781),o=n(25189),s=n(34712);/** @license Material-UI v3.0.0-alpha.3
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */ },34712(e,t){"use strict";n={value:!0},t.Z=void 0;var n,r="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();t.Z=r},82152(e,t,n){"use strict";n.d(t,{D:()=>u});var r=Object.prototype,i=r.toString,a=r.hasOwnProperty,o=Function.prototype.toString,s=new Map;function u(e,t){try{return c(e,t)}finally{s.clear()}}function c(e,t){if(e===t)return!0;var n=i.call(e),r=i.call(t);if(n!==r)return!1;switch(n){case"[object Array]":if(e.length!==t.length)break;case"[object Object]":if(p(e,t))return!0;var s=l(e),u=l(t),f=s.length;if(f!==u.length)break;for(var b=0;b=0&&e.indexOf(t,n)===n}function p(e,t){var n=s.get(e);if(n){if(n.has(t))return!0}else s.set(e,n=new Set);return n.add(t),!1}},79742(e,t){"use strict";t.byteLength=c,t.toByteArray=f,t.fromByteArray=p;for(var n=[],r=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,s=a.length;o0)throw Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");-1===n&&(n=t);var r=n===t?0:4-n%4;return[n,r]}function c(e){var t=u(e),n=t[0],r=t[1];return(n+r)*3/4-r}function l(e,t,n){return(t+n)*3/4-n}function f(e){var t,n,a=u(e),o=a[0],s=a[1],c=new i(l(e,o,s)),f=0,d=s>0?o-4:o;for(n=0;n>16&255,c[f++]=t>>8&255,c[f++]=255&t;return 2===s&&(t=r[e.charCodeAt(n)]<<2|r[e.charCodeAt(n+1)]>>4,c[f++]=255&t),1===s&&(t=r[e.charCodeAt(n)]<<10|r[e.charCodeAt(n+1)]<<4|r[e.charCodeAt(n+2)]>>2,c[f++]=t>>8&255,c[f++]=255&t),c}function d(e){return n[e>>18&63]+n[e>>12&63]+n[e>>6&63]+n[63&e]}function h(e,t,n){for(var r,i=[],a=t;au?u:s+o));return 1===i?a.push(n[(t=e[r-1])>>2]+n[t<<4&63]+"=="):2===i&&a.push(n[(t=(e[r-2]<<8)+e[r-1])>>10]+n[t>>4&63]+n[t<<2&63]+"="),a.join("")}r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63},44431:function(e,t,n){var r;!function(i){"use strict";var a,o=/^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i,s=Math.ceil,u=Math.floor,c="[BigNumber Error] ",l=c+"Number primitive has more than 15 significant digits: ",f=1e14,d=14,h=9007199254740991,p=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],b=1e7,m=1e9;function g(e){var t,n,r,i,a,x,T,M,O,A,L=$.prototype={constructor:$,toString:null,valueOf:null},C=new $(1),I=20,D=4,N=-7,P=21,R=-1e7,j=1e7,F=!1,Y=1,B=0,U={prefix:"",groupSize:3,secondaryGroupSize:0,groupSeparator:",",decimalSeparator:".",fractionGroupSize:0,fractionGroupSeparator:"\xa0",suffix:""},H="0123456789abcdefghijklmnopqrstuvwxyz";function $(e,t){var n,r,i,a,s,c,f,p,b=this;if(!(b instanceof $))return new $(e,t);if(null==t){if(e&&!0===e._isBigNumber){b.s=e.s,!e.c||e.e>j?b.c=b.e=null:e.e=10;s/=10,a++);a>j?b.c=b.e=null:(b.e=a,b.c=[e]);return}p=String(e)}else{if(!o.test(p=String(e)))return A(b,p,c);b.s=45==p.charCodeAt(0)?(p=p.slice(1),-1):1}(a=p.indexOf("."))>-1&&(p=p.replace(".","")),(s=p.search(/e/i))>0?(a<0&&(a=s),a+=+p.slice(s+1),p=p.substring(0,s)):a<0&&(a=p.length)}else{if(_(t,2,H.length,"Base"),10==t)return b=new $(e),K(b,I+b.e+1,D);if(p=String(e),c="number"==typeof e){if(0*e!=0)return A(b,p,c,t);if(b.s=1/e<0?(p=p.slice(1),-1):1,$.DEBUG&&p.replace(/^0\.0*|\./,"").length>15)throw Error(l+e)}else b.s=45===p.charCodeAt(0)?(p=p.slice(1),-1):1;for(n=H.slice(0,t),a=s=0,f=p.length;sn.indexOf(r=p.charAt(s))){if("."==r){if(s>a){a=f;continue}}else if(!i&&(p==p.toUpperCase()&&(p=p.toLowerCase())||p==p.toLowerCase()&&(p=p.toUpperCase()))){i=!0,s=-1,a=0;continue}return A(b,String(e),c,t)}c=!1,(a=(p=O(p,t,10,b.s)).indexOf("."))>-1?p=p.replace(".",""):a=p.length}for(s=0;48===p.charCodeAt(s);s++);for(f=p.length;48===p.charCodeAt(--f););if(p=p.slice(s,++f)){if(f-=s,c&&$.DEBUG&&f>15&&(e>h||e!==u(e)))throw Error(l+b.s*e);if((a=a-s-1)>j)b.c=b.e=null;else if(a=P)?S(u,o):k(u,o,"0");else if(a=(e=K(new $(e),t,n)).e,s=(u=y(e.c)).length,1==r||2==r&&(t<=a||a<=N)){for(;ss){if(--t>0)for(u+=".";t--;u+="0");}else if((t+=a-s)>0)for(a+1==s&&(u+=".");t--;u+="0");return e.s<0&&i?"-"+u:u}function G(e,t){for(var n,r=1,i=new $(e[0]);r=10;i/=10,r++);return(n=r+n*d-1)>j?e.c=e.e=null:n=10;c/=10,i++);if((a=t-i)<0)a+=d,o=t,b=(l=m[h=0])/g[i-o-1]%10|0;else if((h=s((a+1)/d))>=m.length){if(r){for(;m.length<=h;m.push(0));l=b=0,i=1,a%=d,o=a-d+1}else break out}else{for(i=1,l=c=m[h];c>=10;c/=10,i++);a%=d,b=(o=a-d+i)<0?0:l/g[i-o-1]%10|0}if(r=r||t<0||null!=m[h+1]||(o<0?l:l%g[i-o-1]),r=n<4?(b||r)&&(0==n||n==(e.s<0?3:2)):b>5||5==b&&(4==n||r||6==n&&(a>0?o>0?l/g[i-o]:0:m[h-1])%10&1||n==(e.s<0?8:7)),t<1||!m[0])return m.length=0,r?(t-=e.e+1,m[0]=g[(d-t%d)%d],e.e=-t||0):m[0]=e.e=0,e;if(0==a?(m.length=h,c=1,h--):(m.length=h+1,c=g[d-a],m[h]=o>0?u(l/g[i-o]%g[o])*c:0),r)for(;;){if(0==h){for(a=1,o=m[0];o>=10;o/=10,a++);for(o=m[0]+=c,c=1;o>=10;o/=10,c++);a!=c&&(e.e++,m[0]==f&&(m[0]=1));break}if(m[h]+=c,m[h]!=f)break;m[h--]=0,c=1}for(a=m.length;0===m[--a];m.pop());}e.e>j?e.c=e.e=null:e.e=P?S(t,n):k(t,n,"0"),e.s<0?"-"+t:t)}return $.clone=g,$.ROUND_UP=0,$.ROUND_DOWN=1,$.ROUND_CEIL=2,$.ROUND_FLOOR=3,$.ROUND_HALF_UP=4,$.ROUND_HALF_DOWN=5,$.ROUND_HALF_EVEN=6,$.ROUND_HALF_CEIL=7,$.ROUND_HALF_FLOOR=8,$.EUCLID=9,$.config=$.set=function(e){var t,n;if(null!=e){if("object"==typeof e){if(e.hasOwnProperty(t="DECIMAL_PLACES")&&(_(n=e[t],0,m,t),I=n),e.hasOwnProperty(t="ROUNDING_MODE")&&(_(n=e[t],0,8,t),D=n),e.hasOwnProperty(t="EXPONENTIAL_AT")&&((n=e[t])&&n.pop?(_(n[0],-m,0,t),_(n[1],0,m,t),N=n[0],P=n[1]):(_(n,-m,m,t),N=-(P=n<0?-n:n))),e.hasOwnProperty(t="RANGE")){if((n=e[t])&&n.pop)_(n[0],-m,-1,t),_(n[1],1,m,t),R=n[0],j=n[1];else if(_(n,-m,m,t),n)R=-(j=n<0?-n:n);else throw Error(c+t+" cannot be zero: "+n)}if(e.hasOwnProperty(t="CRYPTO")){if(!!(n=e[t])===n){if(n){if("undefined"!=typeof crypto&&crypto&&(crypto.getRandomValues||crypto.randomBytes))F=n;else throw F=!n,Error(c+"crypto unavailable")}else F=n}else throw Error(c+t+" not true or false: "+n)}if(e.hasOwnProperty(t="MODULO_MODE")&&(_(n=e[t],0,9,t),Y=n),e.hasOwnProperty(t="POW_PRECISION")&&(_(n=e[t],0,m,t),B=n),e.hasOwnProperty(t="FORMAT")){if("object"==typeof(n=e[t]))U=n;else throw Error(c+t+" not an object: "+n)}if(e.hasOwnProperty(t="ALPHABET")){if("string"!=typeof(n=e[t])||/^.?$|[+\-.\s]|(.).*\1/.test(n))throw Error(c+t+" invalid: "+n);H=n}}else throw Error(c+"Object expected: "+e)}return{DECIMAL_PLACES:I,ROUNDING_MODE:D,EXPONENTIAL_AT:[N,P],RANGE:[R,j],CRYPTO:F,MODULO_MODE:Y,POW_PRECISION:B,FORMAT:U,ALPHABET:H}},$.isBigNumber=function(e){if(!e||!0!==e._isBigNumber)return!1;if(!$.DEBUG)return!0;var t,n,r=e.c,i=e.e,a=e.s;out:if("[object Array]"==({}).toString.call(r)){if((1===a||-1===a)&&i>=-m&&i<=m&&i===u(i)){if(0===r[0]){if(0===i&&1===r.length)return!0;break out}if((t=(i+1)%d)<1&&(t+=d),String(r[0]).length==t){for(t=0;t=f||n!==u(n))break out;if(0!==n)return!0}}}else if(null===r&&null===i&&(null===a||1===a||-1===a))return!0;throw Error(c+"Invalid BigNumber: "+e)},$.maximum=$.max=function(){return G(arguments,L.lt)},$.minimum=$.min=function(){return G(arguments,L.gt)},$.random=(n=Math.random()*(t=9007199254740992)&2097151?function(){return u(Math.random()*t)}:function(){return(1073741824*Math.random()|0)*8388608+(8388608*Math.random()|0)},function(e){var t,r,i,a,o,l=0,f=[],h=new $(C);if(null==e?e=I:_(e,0,m),a=s(e/d),F){if(crypto.getRandomValues){for(t=crypto.getRandomValues(new Uint32Array(a*=2));l>>11))>=9e15?(r=crypto.getRandomValues(new Uint32Array(2)),t[l]=r[0],t[l+1]=r[1]):(f.push(o%1e14),l+=2);l=a/2}else if(crypto.randomBytes){for(t=crypto.randomBytes(a*=7);l=9e15?crypto.randomBytes(7).copy(t,l):(f.push(o%1e14),l+=7);l=a/7}else throw F=!1,Error(c+"crypto unavailable")}if(!F)for(;l=10;o/=10,l++);ln-1&&(null==o[i+1]&&(o[i+1]=0),o[i+1]+=o[i]/n|0,o[i]%=n)}return o.reverse()}return function(n,r,i,a,o){var s,u,c,l,f,d,h,p,b=n.indexOf("."),m=I,g=D;for(b>=0&&(l=B,B=0,n=n.replace(".",""),d=(p=new $(r)).pow(n.length-b),B=l,p.c=t(k(y(d.c),d.e,"0"),10,i,e),p.e=p.c.length),c=l=(h=t(n,r,i,o?(s=H,e):(s=e,H))).length;0==h[--l];h.pop());if(!h[0])return s.charAt(0);if(b<0?--c:(d.c=h,d.e=c,d.s=a,h=(d=M(d,p,m,g,i)).c,f=d.r,c=d.e),b=h[u=c+m+1],l=i/2,f=f||u<0||null!=h[u+1],f=g<4?(null!=b||f)&&(0==g||g==(d.s<0?3:2)):b>l||b==l&&(4==g||f||6==g&&1&h[u-1]||g==(d.s<0?8:7)),u<1||!h[0])n=f?k(s.charAt(1),-m,s.charAt(0)):s.charAt(0);else{if(h.length=u,f)for(--i;++h[--u]>i;)h[u]=0,u||(++c,h=[1].concat(h));for(l=h.length;!h[--l];);for(b=0,n="";b<=l;n+=s.charAt(h[b++]));n=k(n,c,s.charAt(0))}return n}}(),M=function(){function e(e,t,n){var r,i,a,o,s=0,u=e.length,c=t%b,l=t/b|0;for(e=e.slice();u--;)r=l*(a=e[u]%b)+(o=e[u]/b|0)*c,s=((i=c*a+r%b*b+s)/n|0)+(r/b|0)+l*o,e[u]=i%n;return s&&(e=[s].concat(e)),e}function t(e,t,n,r){var i,a;if(n!=r)a=n>r?1:-1;else for(i=a=0;it[i]?1:-1;break}return a}function n(e,t,n,r){for(var i=0;n--;)e[n]-=i,i=e[n]1;e.splice(0,1));}return function(r,i,a,o,s){var c,l,h,p,b,m,g,y,w,_,E,S,k,x,T,M,O,A=r.s==i.s?1:-1,L=r.c,C=i.c;if(!L||!L[0]||!C||!C[0])return new $(r.s&&i.s&&(L?!C||L[0]!=C[0]:C)?L&&0==L[0]||!C?0*A:A/0:NaN);for(w=(y=new $(A)).c=[],A=a+(l=r.e-i.e)+1,s||(s=f,l=v(r.e/d)-v(i.e/d),A=A/d|0),h=0;C[h]==(L[h]||0);h++);if(C[h]>(L[h]||0)&&l--,A<0)w.push(1),p=!0;else{for(x=L.length,M=C.length,h=0,A+=2,(b=u(s/(C[0]+1)))>1&&(C=e(C,b,s),L=e(L,b,s),M=C.length,x=L.length),k=M,E=(_=L.slice(0,M)).length;E=s/2&&T++;do{if(b=0,(c=t(C,_,M,E))<0){if(S=_[0],M!=E&&(S=S*s+(_[1]||0)),(b=u(S/T))>1)for(b>=s&&(b=s-1),g=(m=e(C,b,s)).length,E=_.length;1==t(m,_,g,E);)b--,n(m,Mt(C,_,M,E);)b++,n(_,M=10;A/=10,h++);K(y,a+(y.e=h+l*d-1)+1,o,p)}else y.e=l,y.r=+p;return y}}(),A=(r=/^(-?)0([xbo])(?=\w[\w.]*$)/i,i=/^([^.]+)\.$/,a=/^\.([^.]+)$/,x=/^-?(Infinity|NaN)$/,T=/^\s*\+(?=[\w.])|^\s+|\s+$/g,function(e,t,n,o){var s,u=n?t:t.replace(T,"");if(x.test(u))e.s=isNaN(u)?null:u<0?-1:1;else{if(!n&&(u=u.replace(r,function(e,t,n){return s="x"==(n=n.toLowerCase())?16:"b"==n?2:8,o&&o!=s?e:t}),o&&(s=o,u=u.replace(i,"$1").replace(a,"0.$1")),t!=u))return new $(u,s);if($.DEBUG)throw Error(c+"Not a"+(o?" base "+o:"")+" number: "+t);e.s=null}e.c=e.e=null}),L.absoluteValue=L.abs=function(){var e=new $(this);return e.s<0&&(e.s=1),e},L.comparedTo=function(e,t){return w(this,new $(e,t))},L.decimalPlaces=L.dp=function(e,t){var n,r,i,a=this;if(null!=e)return _(e,0,m),null==t?t=D:_(t,0,8),K(new $(a),e+a.e+1,t);if(!(n=a.c))return null;if(r=((i=n.length-1)-v(this.e/d))*d,i=n[i])for(;i%10==0;i/=10,r--);return r<0&&(r=0),r},L.dividedBy=L.div=function(e,t){return M(this,new $(e,t),I,D)},L.dividedToIntegerBy=L.idiv=function(e,t){return M(this,new $(e,t),0,1)},L.exponentiatedBy=L.pow=function(e,t){var n,r,i,a,o,l,f,h,p,b=this;if((e=new $(e)).c&&!e.isInteger())throw Error(c+"Exponent not an integer: "+V(e));if(null!=t&&(t=new $(t)),l=e.e>14,!b.c||!b.c[0]||1==b.c[0]&&!b.e&&1==b.c.length||!e.c||!e.c[0])return p=new $(Math.pow(+V(b),l?2-E(e):+V(e))),t?p.mod(t):p;if(f=e.s<0,t){if(t.c?!t.c[0]:!t.s)return new $(NaN);(r=!f&&b.isInteger()&&t.isInteger())&&(b=b.mod(t))}else{if(e.e>9&&(b.e>0||b.e<-1||(0==b.e?b.c[0]>1||l&&b.c[1]>=24e7:b.c[0]<8e13||l&&b.c[0]<=9999975e7)))return a=(b.s<0&&E(e),-0),b.e>-1&&(a=1/a),new $(f?1/a:a);B&&(a=s(B/d+2))}for(l?(n=new $(.5),f&&(e.s=1),h=E(e)):h=(i=Math.abs(+V(e)))%2,p=new $(C);;){if(h){if(!(p=p.times(b)).c)break;a?p.c.length>a&&(p.c.length=a):r&&(p=p.mod(t))}if(i){if(0===(i=u(i/2)))break;h=i%2}else if(K(e=e.times(n),e.e+1,1),e.e>14)h=E(e);else{if(0==(i=+V(e)))break;h=i%2}b=b.times(b),a?b.c&&b.c.length>a&&(b.c.length=a):r&&(b=b.mod(t))}return r?p:(f&&(p=C.div(p)),t?p.mod(t):a?K(p,B,D,o):p)},L.integerValue=function(e){var t=new $(this);return null==e?e=D:_(e,0,8),K(t,t.e+1,e)},L.isEqualTo=L.eq=function(e,t){return 0===w(this,new $(e,t))},L.isFinite=function(){return!!this.c},L.isGreaterThan=L.gt=function(e,t){return w(this,new $(e,t))>0},L.isGreaterThanOrEqualTo=L.gte=function(e,t){return 1===(t=w(this,new $(e,t)))||0===t},L.isInteger=function(){return!!this.c&&v(this.e/d)>this.c.length-2},L.isLessThan=L.lt=function(e,t){return 0>w(this,new $(e,t))},L.isLessThanOrEqualTo=L.lte=function(e,t){return -1===(t=w(this,new $(e,t)))||0===t},L.isNaN=function(){return!this.s},L.isNegative=function(){return this.s<0},L.isPositive=function(){return this.s>0},L.isZero=function(){return!!this.c&&0==this.c[0]},L.minus=function(e,t){var n,r,i,a,o=this,s=o.s;if(t=(e=new $(e,t)).s,!s||!t)return new $(NaN);if(s!=t)return e.s=-t,o.plus(e);var u=o.e/d,c=e.e/d,l=o.c,h=e.c;if(!u||!c){if(!l||!h)return l?(e.s=-t,e):new $(h?o:NaN);if(!l[0]||!h[0])return h[0]?(e.s=-t,e):new $(l[0]?o:-0)}if(u=v(u),c=v(c),l=l.slice(),s=u-c){for((a=s<0)?(s=-s,i=l):(c=u,i=h),i.reverse(),t=s;t--;i.push(0));i.reverse()}else for(r=(a=(s=l.length)<(t=h.length))?s:t,s=t=0;t0)for(;t--;l[n++]=0);for(t=f-1;r>s;){if(l[--r]=0;){for(n=0,p=S[i]%w,m=S[i]/w|0,a=i+(o=u);a>i;)s=m*(c=E[--o]%w)+(l=E[o]/w|0)*p,n=((c=p*c+s%w*w+g[a]+n)/y|0)+(s/w|0)+m*l,g[a--]=c%y;g[a]=n}return n?++r:g.splice(0,1),W(e,g,r)},L.negated=function(){var e=new $(this);return e.s=-e.s||null,e},L.plus=function(e,t){var n,r=this,i=r.s;if(t=(e=new $(e,t)).s,!i||!t)return new $(NaN);if(i!=t)return e.s=-t,r.minus(e);var a=r.e/d,o=e.e/d,s=r.c,u=e.c;if(!a||!o){if(!s||!u)return new $(i/0);if(!s[0]||!u[0])return u[0]?e:new $(s[0]?r:0*i)}if(a=v(a),o=v(o),s=s.slice(),i=a-o){for(i>0?(o=a,n=u):(i=-i,n=s),n.reverse();i--;n.push(0));n.reverse()}for((i=s.length)-(t=u.length)<0&&(n=u,u=s,s=n,t=i),i=0;t;)i=(s[--t]=s[t]+u[t]+i)/f|0,s[t]=f===s[t]?0:s[t]%f;return i&&(s=[i].concat(s),++o),W(e,s,o)},L.precision=L.sd=function(e,t){var n,r,i,a=this;if(null!=e&&!!e!==e)return _(e,1,m),null==t?t=D:_(t,0,8),K(new $(a),e,t);if(!(n=a.c))return null;if(r=(i=n.length-1)*d+1,i=n[i]){for(;i%10==0;i/=10,r--);for(i=n[0];i>=10;i/=10,r++);}return e&&a.e+1>r&&(r=a.e+1),r},L.shiftedBy=function(e){return _(e,-h,h),this.times("1e"+e)},L.squareRoot=L.sqrt=function(){var e,t,n,r,i,a=this,o=a.c,s=a.s,u=a.e,c=I+4,l=new $("0.5");if(1!==s||!o||!o[0])return new $(!s||s<0&&(!o||o[0])?NaN:o?a:1/0);if(0==(s=Math.sqrt(+V(a)))||s==1/0?(((t=y(o)).length+u)%2==0&&(t+="0"),s=Math.sqrt(+t),u=v((u+1)/2)-(u<0||u%2),t=s==1/0?"5e"+u:(t=s.toExponential()).slice(0,t.indexOf("e")+1)+u,n=new $(t)):n=new $(s+""),n.c[0]){for((s=(u=n.e)+c)<3&&(s=0);;)if(i=n,n=l.times(i.plus(M(a,i,c,1))),y(i.c).slice(0,s)===(t=y(n.c)).slice(0,s)){if(n.e0&&b>0){for(a=b%s||s,f=p.substr(0,a);a0&&(f+=l+p.slice(a)),h&&(f="-"+f)}r=d?f+(n.decimalSeparator||"")+((u=+n.fractionGroupSize)?d.replace(RegExp("\\d{"+u+"}\\B","g"),"$&"+(n.fractionGroupSeparator||"")):d):f}return(n.prefix||"")+r+(n.suffix||"")},L.toFraction=function(e){var t,n,r,i,a,o,s,u,l,f,h,b,m=this,g=m.c;if(null!=e&&(!(s=new $(e)).isInteger()&&(s.c||1!==s.s)||s.lt(C)))throw Error(c+"Argument "+(s.isInteger()?"out of range: ":"not an integer: ")+V(s));if(!g)return new $(m);for(t=new $(C),l=n=new $(C),r=u=new $(C),b=y(g),a=t.e=b.length-m.e-1,t.c[0]=p[(o=a%d)<0?d+o:o],e=!e||s.comparedTo(t)>0?a>0?t:l:s,o=j,j=1/0,s=new $(b),u.c[0]=0;f=M(s,t,0,1),1!=(i=n.plus(f.times(r))).comparedTo(e);)n=r,r=i,l=u.plus(f.times(i=l)),u=i,t=s.minus(f.times(i=t)),s=i;return i=M(e.minus(n),r,0,1),u=u.plus(i.times(l)),n=n.plus(i.times(r)),u.s=l.s=m.s,a*=2,h=1>M(l,r,a,D).minus(m).abs().comparedTo(M(u,n,a,D).minus(m).abs())?[l,r]:[u,n],j=o,h},L.toNumber=function(){return+V(this)},L.toPrecision=function(e,t){return null!=e&&_(e,1,m),z(this,e,t,2)},L.toString=function(e){var t,n=this,r=n.s,i=n.e;return null===i?r?(t="Infinity",r<0&&(t="-"+t)):t="NaN":(null==e?t=i<=N||i>=P?S(y(n.c),i):k(y(n.c),i,"0"):10===e?(n=K(new $(n),I+i+1,D),t=k(y(n.c),n.e,"0")):(_(e,2,H.length,"Base"),t=O(k(y(n.c),i,"0"),10,e,r,!0)),r<0&&n.c[0]&&(t="-"+t)),t},L.valueOf=L.toJSON=function(){return V(this)},L._isBigNumber=!0,null!=e&&$.set(e),$}function v(e){var t=0|e;return e>0||e===t?t:t-1}function y(e){for(var t,n,r=1,i=e.length,a=e[0]+"";rc^n?1:-1;for(o=0,s=(u=i.length)<(c=a.length)?u:c;oa[o]^n?1:-1;return u==c?0:u>c^n?1:-1}function _(e,t,n,r){if(en||e!==u(e))throw Error(c+(r||"Argument")+("number"==typeof e?en?" out of range: ":" not an integer: ":" not a primitive number: ")+String(e))}function E(e){var t=e.c.length-1;return v(e.e/d)==t&&e.c[t]%2!=0}function S(e,t){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(t<0?"e":"e+")+t}function k(e,t,n){var r,i;if(t<0){for(i=n+".";++t;i+=n);e=i+e}else if(r=e.length,++t>r){for(i=n,t-=r;--t;i+=n);e+=i}else ti});let i=r},48764(e,t,n){"use strict";/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh
+ * @license MIT
+ */ var r=n(79742),i=n(80645),a="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;t.Buffer=c,t.SlowBuffer=w,t.INSPECT_MAX_BYTES=50;var o=2147483647;function s(){try{var e=new Uint8Array(1),t={foo:function(){return 42}};return Object.setPrototypeOf(t,Uint8Array.prototype),Object.setPrototypeOf(e,t),42===e.foo()}catch(n){return!1}}function u(e){if(e>o)throw RangeError('The value "'+e+'" is invalid for option "size"');var t=new Uint8Array(e);return Object.setPrototypeOf(t,c.prototype),t}function c(e,t,n){if("number"==typeof e){if("string"==typeof t)throw TypeError('The "string" argument must be of type string. Received type number');return h(e)}return l(e,t,n)}function l(e,t,n){if("string"==typeof e)return p(e,t);if(ArrayBuffer.isView(e))return m(e);if(null==e)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(X(e,ArrayBuffer)||e&&X(e.buffer,ArrayBuffer)||"undefined"!=typeof SharedArrayBuffer&&(X(e,SharedArrayBuffer)||e&&X(e.buffer,SharedArrayBuffer)))return g(e,t,n);if("number"==typeof e)throw TypeError('The "value" argument must not be of type number. Received type number');var r=e.valueOf&&e.valueOf();if(null!=r&&r!==e)return c.from(r,t,n);var i=v(e);if(i)return i;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof e[Symbol.toPrimitive])return c.from(e[Symbol.toPrimitive]("string"),t,n);throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e)}function f(e){if("number"!=typeof e)throw TypeError('"size" argument must be of type number');if(e<0)throw RangeError('The value "'+e+'" is invalid for option "size"')}function d(e,t,n){return(f(e),e<=0)?u(e):void 0!==t?"string"==typeof n?u(e).fill(t,n):u(e).fill(t):u(e)}function h(e){return f(e),u(e<0?0:0|y(e))}function p(e,t){if(("string"!=typeof t||""===t)&&(t="utf8"),!c.isEncoding(t))throw TypeError("Unknown encoding: "+t);var n=0|_(e,t),r=u(n),i=r.write(e,t);return i!==n&&(r=r.slice(0,i)),r}function b(e){for(var t=e.length<0?0:0|y(e.length),n=u(t),r=0;r=o)throw RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o.toString(16)+" bytes");return 0|e}function w(e){return+e!=e&&(e=0),c.alloc(+e)}function _(e,t){if(c.isBuffer(e))return e.length;if(ArrayBuffer.isView(e)||X(e,ArrayBuffer))return e.byteLength;if("string"!=typeof e)throw TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof e);var n=e.length,r=arguments.length>2&&!0===arguments[2];if(!r&&0===n)return 0;for(var i=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return W(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return q(e).length;default:if(i)return r?-1:W(e).length;t=(""+t).toLowerCase(),i=!0}}function E(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length||((void 0===n||n>this.length)&&(n=this.length),n<=0||(n>>>=0)<=(t>>>=0)))return"";for(e||(e="utf8");;)switch(e){case"hex":return j(this,t,n);case"utf8":case"utf-8":return I(this,t,n);case"ascii":return P(this,t,n);case"latin1":case"binary":return R(this,t,n);case"base64":return C(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return F(this,t,n);default:if(r)throw TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function S(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function k(e,t,n,r,i){if(0===e.length)return -1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),J(n=+n)&&(n=i?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(i)return -1;n=e.length-1}else if(n<0){if(!i)return -1;n=0}if("string"==typeof t&&(t=c.from(t,r)),c.isBuffer(t))return 0===t.length?-1:x(e,t,n,r,i);if("number"==typeof t)return(t&=255,"function"==typeof Uint8Array.prototype.indexOf)?i?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):x(e,[t],n,r,i);throw TypeError("val must be string, number or Buffer")}function x(e,t,n,r,i){var a,o=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return -1;o=2,s/=2,u/=2,n/=2}function c(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(i){var l=-1;for(a=n;as&&(n=s-u),a=n;a>=0;a--){for(var f=!0,d=0;di&&(r=i):r=i;var a=t.length;r>a/2&&(r=a/2);for(var o=0;o239?4:c>223?3:c>191?2:1;if(i+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:(192&(a=e[i+1]))==128&&(u=(31&c)<<6|63&a)>127&&(l=u);break;case 3:a=e[i+1],o=e[i+2],(192&a)==128&&(192&o)==128&&(u=(15&c)<<12|(63&a)<<6|63&o)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:a=e[i+1],o=e[i+2],s=e[i+3],(192&a)==128&&(192&o)==128&&(192&s)==128&&(u=(15&c)<<18|(63&a)<<12|(63&o)<<6|63&s)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),i+=f}return N(r)}t.kMaxLength=o,c.TYPED_ARRAY_SUPPORT=s(),c.TYPED_ARRAY_SUPPORT||"undefined"==typeof console||"function"!=typeof console.error||console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."),Object.defineProperty(c.prototype,"parent",{enumerable:!0,get:function(){if(c.isBuffer(this))return this.buffer}}),Object.defineProperty(c.prototype,"offset",{enumerable:!0,get:function(){if(c.isBuffer(this))return this.byteOffset}}),c.poolSize=8192,c.from=function(e,t,n){return l(e,t,n)},Object.setPrototypeOf(c.prototype,Uint8Array.prototype),Object.setPrototypeOf(c,Uint8Array),c.alloc=function(e,t,n){return d(e,t,n)},c.allocUnsafe=function(e){return h(e)},c.allocUnsafeSlow=function(e){return h(e)},c.isBuffer=function(e){return null!=e&&!0===e._isBuffer&&e!==c.prototype},c.compare=function(e,t){if(X(e,Uint8Array)&&(e=c.from(e,e.offset,e.byteLength)),X(t,Uint8Array)&&(t=c.from(t,t.offset,t.byteLength)),!c.isBuffer(e)||!c.isBuffer(t))throw TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(e===t)return 0;for(var n=e.length,r=t.length,i=0,a=Math.min(n,r);ir.length?c.from(a).copy(r,i):Uint8Array.prototype.set.call(r,a,i);else if(c.isBuffer(a))a.copy(r,i);else throw TypeError('"list" argument must be an Array of Buffers');i+=a.length}return r},c.byteLength=_,c.prototype._isBuffer=!0,c.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;tn&&(e+=" ... "),""},a&&(c.prototype[a]=c.prototype.inspect),c.prototype.compare=function(e,t,n,r,i){if(X(e,Uint8Array)&&(e=c.from(e,e.offset,e.byteLength)),!c.isBuffer(e))throw TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),t<0||n>e.length||r<0||i>this.length)throw RangeError("out of range index");if(r>=i&&t>=n)return 0;if(r>=i)return -1;if(t>=n)return 1;if(t>>>=0,n>>>=0,r>>>=0,i>>>=0,this===e)return 0;for(var a=i-r,o=n-t,s=Math.min(a,o),u=this.slice(r,i),l=e.slice(t,n),f=0;f>>=0,isFinite(n)?(n>>>=0,void 0===r&&(r="utf8")):(r=n,n=void 0);else throw Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");var i=this.length-t;if((void 0===n||n>i)&&(n=i),e.length>0&&(n<0||t<0)||t>this.length)throw RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var a=!1;;)switch(r){case"hex":return T(this,e,t,n);case"utf8":case"utf-8":return M(this,e,t,n);case"ascii":case"latin1":case"binary":return O(this,e,t,n);case"base64":return A(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return L(this,e,t,n);default:if(a)throw TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var D=4096;function N(e){var t=e.length;if(t<=D)return String.fromCharCode.apply(String,e);for(var n="",r=0;rr)&&(n=r);for(var i="",a=t;an)throw RangeError("Trying to access beyond buffer length")}function B(e,t,n,r,i,a){if(!c.isBuffer(e))throw TypeError('"buffer" argument must be a Buffer instance');if(t>i||te.length)throw RangeError("Index out of range")}function U(e,t,n,r,i,a){if(n+r>e.length||n<0)throw RangeError("Index out of range")}function H(e,t,n,r,a){return t=+t,n>>>=0,a||U(e,t,n,4,34028234663852886e22,-34028234663852886e22),i.write(e,t,n,r,23,4),n+4}function $(e,t,n,r,a){return t=+t,n>>>=0,a||U(e,t,n,8,17976931348623157e292,-17976931348623157e292),i.write(e,t,n,r,52,8),n+8}c.prototype.slice=function(e,t){var n=this.length;e=~~e,t=void 0===t?n:~~t,e<0?(e+=n)<0&&(e=0):e>n&&(e=n),t<0?(t+=n)<0&&(t=0):t>n&&(t=n),t>>=0,t>>>=0,n||Y(e,t,this.length);for(var r=this[e],i=1,a=0;++a>>=0,t>>>=0,n||Y(e,t,this.length);for(var r=this[e+--t],i=1;t>0&&(i*=256);)r+=this[e+--t]*i;return r},c.prototype.readUint8=c.prototype.readUInt8=function(e,t){return e>>>=0,t||Y(e,1,this.length),this[e]},c.prototype.readUint16LE=c.prototype.readUInt16LE=function(e,t){return e>>>=0,t||Y(e,2,this.length),this[e]|this[e+1]<<8},c.prototype.readUint16BE=c.prototype.readUInt16BE=function(e,t){return e>>>=0,t||Y(e,2,this.length),this[e]<<8|this[e+1]},c.prototype.readUint32LE=c.prototype.readUInt32LE=function(e,t){return e>>>=0,t||Y(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},c.prototype.readUint32BE=c.prototype.readUInt32BE=function(e,t){return e>>>=0,t||Y(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},c.prototype.readIntLE=function(e,t,n){e>>>=0,t>>>=0,n||Y(e,t,this.length);for(var r=this[e],i=1,a=0;++a=(i*=128)&&(r-=Math.pow(2,8*t)),r},c.prototype.readIntBE=function(e,t,n){e>>>=0,t>>>=0,n||Y(e,t,this.length);for(var r=t,i=1,a=this[e+--r];r>0&&(i*=256);)a+=this[e+--r]*i;return a>=(i*=128)&&(a-=Math.pow(2,8*t)),a},c.prototype.readInt8=function(e,t){return(e>>>=0,t||Y(e,1,this.length),128&this[e])?-((255-this[e]+1)*1):this[e]},c.prototype.readInt16LE=function(e,t){e>>>=0,t||Y(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt16BE=function(e,t){e>>>=0,t||Y(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt32LE=function(e,t){return e>>>=0,t||Y(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},c.prototype.readInt32BE=function(e,t){return e>>>=0,t||Y(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},c.prototype.readFloatLE=function(e,t){return e>>>=0,t||Y(e,4,this.length),i.read(this,e,!0,23,4)},c.prototype.readFloatBE=function(e,t){return e>>>=0,t||Y(e,4,this.length),i.read(this,e,!1,23,4)},c.prototype.readDoubleLE=function(e,t){return e>>>=0,t||Y(e,8,this.length),i.read(this,e,!0,52,8)},c.prototype.readDoubleBE=function(e,t){return e>>>=0,t||Y(e,8,this.length),i.read(this,e,!1,52,8)},c.prototype.writeUintLE=c.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t>>>=0,n>>>=0,!r){var i=Math.pow(2,8*n)-1;B(this,e,t,n,i,0)}var a=1,o=0;for(this[t]=255&e;++o>>=0,n>>>=0,!r){var i=Math.pow(2,8*n)-1;B(this,e,t,n,i,0)}var a=n-1,o=1;for(this[t+a]=255&e;--a>=0&&(o*=256);)this[t+a]=e/o&255;return t+n},c.prototype.writeUint8=c.prototype.writeUInt8=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,1,255,0),this[t]=255&e,t+1},c.prototype.writeUint16LE=c.prototype.writeUInt16LE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},c.prototype.writeUint16BE=c.prototype.writeUInt16BE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},c.prototype.writeUint32LE=c.prototype.writeUInt32LE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},c.prototype.writeUint32BE=c.prototype.writeUInt32BE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},c.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t>>>=0,!r){var i=Math.pow(2,8*n-1);B(this,e,t,n,i-1,-i)}var a=0,o=1,s=0;for(this[t]=255&e;++a>0)-s&255;return t+n},c.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t>>>=0,!r){var i=Math.pow(2,8*n-1);B(this,e,t,n,i-1,-i)}var a=n-1,o=1,s=0;for(this[t+a]=255&e;--a>=0&&(o*=256);)e<0&&0===s&&0!==this[t+a+1]&&(s=1),this[t+a]=(e/o>>0)-s&255;return t+n},c.prototype.writeInt8=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,1,127,-128),e<0&&(e=255+e+1),this[t]=255&e,t+1},c.prototype.writeInt16LE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},c.prototype.writeInt16BE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},c.prototype.writeInt32LE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},c.prototype.writeInt32BE=function(e,t,n){return e=+e,t>>>=0,n||B(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},c.prototype.writeFloatLE=function(e,t,n){return H(this,e,t,!0,n)},c.prototype.writeFloatBE=function(e,t,n){return H(this,e,t,!1,n)},c.prototype.writeDoubleLE=function(e,t,n){return $(this,e,t,!0,n)},c.prototype.writeDoubleBE=function(e,t,n){return $(this,e,t,!1,n)},c.prototype.copy=function(e,t,n,r){if(!c.isBuffer(e))throw TypeError("argument should be a Buffer");if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw RangeError("Index out of range");if(r<0)throw RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!i){if(n>56319||o+1===r){(t-=3)>-1&&a.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&a.push(239,191,189),i=n;continue}n=(i-55296<<10|n-56320)+65536}else i&&(t-=3)>-1&&a.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;a.push(n)}else if(n<2048){if((t-=2)<0)break;a.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;a.push(n>>12|224,n>>6&63|128,63&n|128)}else if(n<1114112){if((t-=4)<0)break;a.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}else throw Error("Invalid code point")}return a}function K(e){for(var t=[],n=0;n>8,a.push(i=n%256),a.push(r);return a}function q(e){return r.toByteArray(G(e))}function Z(e,t,n,r){for(var i=0;i=t.length)&&!(i>=e.length);++i)t[i+n]=e[i];return i}function X(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function J(e){return e!=e}var Q=function(){for(var e="0123456789abcdef",t=Array(256),n=0;n<16;++n)for(var r=16*n,i=0;i<16;++i)t[r+i]=e[n]+e[i];return t}()},94184(e,t){var n,r; /*!
+ Copyright (c) 2018 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/ !function(){"use strict";var i={}.hasOwnProperty;function a(){for(var e=[],t=0;t>8&255]},F=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},Y=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},B=function(e){return N(e,23,4)},U=function(e){return N(e,52,8)},H=function(e,t){g(e[x],t,{get:function(){return _(this)[t]}})},$=function(e,t,n,r){var i=d(n),a=_(e);if(i+t>a.byteLength)throw D(M);var o=_(a.buffer).bytes,s=i+a.byteOffset,u=o.slice(s,s+t);return r?u:u.reverse()},z=function(e,t,n,r,i,a){var o=d(n),s=_(e);if(o+t>s.byteLength)throw D(M);for(var u=_(s.buffer).bytes,c=o+s.byteOffset,l=r(+i),f=0;fV;)(G=K[V++])in A||o(A,G,O[G]);W.constructor=A}b&&p(C)!==I&&b(C,I);var q=new L(new A(2)),Z=C.setInt8;q.setInt8(0,2147483648),q.setInt8(1,2147483649),(q.getInt8(0)||!q.getInt8(1))&&s(C,{setInt8:function(e,t){Z.call(this,e,t<<24>>24)},setUint8:function(e,t){Z.call(this,e,t<<24>>24)}},{unsafe:!0})}else A=function(e){c(this,A,S);var t=d(e);E(this,{bytes:v.call(Array(t),0),byteLength:t}),i||(this.byteLength=t)},L=function(e,t,n){c(this,L,k),c(e,A,k);var r=_(e).byteLength,a=l(t);if(a<0||a>r)throw D("Wrong offset");if(n=void 0===n?r-a:f(n),a+n>r)throw D(T);E(this,{buffer:e,byteLength:n,byteOffset:a}),i||(this.buffer=e,this.byteLength=n,this.byteOffset=a)},i&&(H(A,"byteLength"),H(L,"buffer"),H(L,"byteLength"),H(L,"byteOffset")),s(L[x],{getInt8:function(e){return $(this,1,e)[0]<<24>>24},getUint8:function(e){return $(this,1,e)[0]},getInt16:function(e){var t=$(this,2,e,arguments.length>1?arguments[1]:void 0);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=$(this,2,e,arguments.length>1?arguments[1]:void 0);return t[1]<<8|t[0]},getInt32:function(e){return Y($(this,4,e,arguments.length>1?arguments[1]:void 0))},getUint32:function(e){return Y($(this,4,e,arguments.length>1?arguments[1]:void 0))>>>0},getFloat32:function(e){return P($(this,4,e,arguments.length>1?arguments[1]:void 0),23)},getFloat64:function(e){return P($(this,8,e,arguments.length>1?arguments[1]:void 0),52)},setInt8:function(e,t){z(this,1,e,R,t)},setUint8:function(e,t){z(this,1,e,R,t)},setInt16:function(e,t){z(this,2,e,j,t,arguments.length>2?arguments[2]:void 0)},setUint16:function(e,t){z(this,2,e,j,t,arguments.length>2?arguments[2]:void 0)},setInt32:function(e,t){z(this,4,e,F,t,arguments.length>2?arguments[2]:void 0)},setUint32:function(e,t){z(this,4,e,F,t,arguments.length>2?arguments[2]:void 0)},setFloat32:function(e,t){z(this,4,e,B,t,arguments.length>2?arguments[2]:void 0)},setFloat64:function(e,t){z(this,8,e,U,t,arguments.length>2?arguments[2]:void 0)}});y(A,S),y(L,k),e.exports={ArrayBuffer:A,DataView:L}},1048(e,t,n){"use strict";var r=n(47908),i=n(51400),a=n(17466),o=Math.min;e.exports=[].copyWithin||function(e,t){var n=r(this),s=a(n.length),u=i(e,s),c=i(t,s),l=arguments.length>2?arguments[2]:void 0,f=o((void 0===l?s:i(l,s))-c,s-u),d=1;for(c0;)c in n?n[u]=n[c]:delete n[u],u+=d,c+=d;return n}},21285(e,t,n){"use strict";var r=n(47908),i=n(51400),a=n(17466);e.exports=function(e){for(var t=r(this),n=a(t.length),o=arguments.length,s=i(o>1?arguments[1]:void 0,n),u=o>2?arguments[2]:void 0,c=void 0===u?n:i(u,n);c>s;)t[s++]=e;return t}},18533(e,t,n){"use strict";var r=n(42092).forEach,i=n(9341)("forEach");e.exports=i?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},97745(e){e.exports=function(e,t){for(var n=0,r=t.length,i=new e(r);r>n;)i[n]=t[n++];return i}},48457(e,t,n){"use strict";var r=n(49974),i=n(47908),a=n(53411),o=n(97659),s=n(17466),u=n(86135),c=n(18554),l=n(71246);e.exports=function(e){var t,n,f,d,h,p,b=i(e),m="function"==typeof this?this:Array,g=arguments.length,v=g>1?arguments[1]:void 0,y=void 0!==v,w=l(b),_=0;if(y&&(v=r(v,g>2?arguments[2]:void 0,2)),void 0==w||m==Array&&o(w))for(t=s(b.length),n=new m(t);t>_;_++)p=y?v(b[_],_):b[_],u(n,_,p);else for(h=(d=c(b,w)).next,n=new m;!(f=h.call(d)).done;_++)p=y?a(d,v,[f.value,_],!0):f.value,u(n,_,p);return n.length=_,n}},61386(e,t,n){var r=n(49974),i=n(68361),a=n(47908),o=n(17466),s=n(34948),u=n(70030),c=n(97745),l=[].push;e.exports=function(e,t,n,f){for(var d,h,p,b=a(e),m=i(b),g=r(t,n,3),v=u(null),y=o(m.length),w=0;y>w;w++)(h=s(g(p=m[w],w,b)))in v?l.call(v[h],p):v[h]=[p];if(f&&(d=f(b))!==Array)for(h in v)v[h]=c(d,v[h]);return v}},41318(e,t,n){var r=n(45656),i=n(17466),a=n(51400),o=function(e){return function(t,n,o){var s,u=r(t),c=i(u.length),l=a(o,c);if(e&&n!=n){for(;c>l;)if((s=u[l++])!=s)return!0}else for(;c>l;l++)if((e||l in u)&&u[l]===n)return e||l||0;return!e&&-1}};e.exports={includes:o(!0),indexOf:o(!1)}},9671(e,t,n){var r=n(49974),i=n(68361),a=n(47908),o=n(17466),s=function(e){var t=1==e;return function(n,s,u){for(var c,l,f=a(n),d=i(f),h=r(s,u,3),p=o(d.length);p-- >0;)if(l=h(c=d[p],p,f))switch(e){case 0:return c;case 1:return p}return t?-1:void 0}};e.exports={findLast:s(0),findLastIndex:s(1)}},42092(e,t,n){var r=n(49974),i=n(68361),a=n(47908),o=n(17466),s=n(65417),u=[].push,c=function(e){var t=1==e,n=2==e,c=3==e,l=4==e,f=6==e,d=7==e,h=5==e||f;return function(p,b,m,g){for(var v,y,w=a(p),_=i(w),E=r(b,m,3),S=o(_.length),k=0,x=g||s,T=t?x(p,S):n||d?x(p,0):void 0;S>k;k++)if((h||k in _)&&(y=E(v=_[k],k,w),e)){if(t)T[k]=y;else if(y)switch(e){case 3:return!0;case 5:return v;case 6:return k;case 2:u.call(T,v)}else switch(e){case 4:return!1;case 7:u.call(T,v)}}return f?-1:c||l?l:T}};e.exports={forEach:c(0),map:c(1),filter:c(2),some:c(3),every:c(4),find:c(5),findIndex:c(6),filterReject:c(7)}},86583(e,t,n){"use strict";var r=n(45656),i=n(99958),a=n(17466),o=n(9341),s=Math.min,u=[].lastIndexOf,c=!!u&&1/[1].lastIndexOf(1,-0)<0,l=o("lastIndexOf"),f=c||!l;e.exports=f?function(e){if(c)return u.apply(this,arguments)||0;var t=r(this),n=a(t.length),o=n-1;for(arguments.length>1&&(o=s(o,i(arguments[1]))),o<0&&(o=n+o);o>=0;o--)if(o in t&&t[o]===e)return o||0;return -1}:u},81194(e,t,n){var r=n(47293),i=n(5112),a=n(7392),o=i("species");e.exports=function(e){return a>=51||!r(function(){var t=[];return(t.constructor={})[o]=function(){return{foo:1}},1!==t[e](Boolean).foo})}},9341(e,t,n){"use strict";var r=n(47293);e.exports=function(e,t){var n=[][e];return!!n&&r(function(){n.call(null,t||function(){throw 1},1)})}},53671(e,t,n){var r=n(13099),i=n(47908),a=n(68361),o=n(17466),s=function(e){return function(t,n,s,u){r(n);var c=i(t),l=a(c),f=o(c.length),d=e?f-1:0,h=e?-1:1;if(s<2)for(;;){if(d in l){u=l[d],d+=h;break}if(d+=h,e?d<0:f<=d)throw TypeError("Reduce of empty array with no initial value")}for(;e?d>=0:f>d;d+=h)d in l&&(u=n(u,l[d],d,c));return u}};e.exports={left:s(!1),right:s(!0)}},94362(e){var t=Math.floor,n=function(e,a){var o=e.length,s=t(o/2);return o<8?r(e,a):i(n(e.slice(0,s),a),n(e.slice(s),a),a)},r=function(e,t){for(var n,r,i=e.length,a=1;a0;)e[r]=e[--r];r!==a++&&(e[r]=n)}return e},i=function(e,t,n){for(var r=e.length,i=t.length,a=0,o=0,s=[];a=n(e[a],t[o])?e[a++]:t[o++]):s.push(a